/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.glass.sample.apidemo.card; import com.google.android.glass.media.Sounds; import com.google.android.glass.sample.apidemo.R; import com.google.android.glass.widget.CardBuilder; import com.google.android.glass.widget.CardScrollView; import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * Creates a card scroll view with various examples of its API. */ public final class CardScrollViewActivity extends Activity { /** Actions associated with cards. */ private enum Action { DELETION_HERE(R.string.text_card_tap_to_delete, R.drawable.codemonkey1), NAVIGATION_TO_BEGIN(R.string.text_card_tap_to_navigate_begin, R.drawable.codemonkey2), NAVIGATION_TO_END(R.string.text_card_tap_to_navigate_end, R.drawable.codemonkey3), INSERTION_AT_BEGIN(R.string.text_card_tap_to_insert_begin, R.drawable.codemonkey4), INSERTION_BEFORE(R.string.text_card_tap_to_insert_before, R.drawable.codemonkey5), INSERTION_AFTER(R.string.text_card_tap_to_insert_after, R.drawable.codemonkey6), INSERTION_AT_END(R.string.text_card_tap_to_insert_end, R.drawable.codemonkey7), NO_ACTION(R.string.text_card_no_action, R.drawable.codemonkey8); final int textId; final int imageId; Action(int textId, int imageId) { this.textId = textId; this.imageId = imageId; } } /** * Adapter class that handles list of cards with associated actions and * allows for mutations without notifying the adapter of the data change yet * (through method {@link #notifyDataSetChanged}). Useful to demonstrate * mutation animations. */ private final class CardAdapterWithMutations extends CardAdapter { private final List<Action> mActions; public CardAdapterWithMutations() { super(new ArrayList<CardBuilder>()); mActions = new ArrayList<Action>(); } /** Inserts a card into the adapter, without notifying. */ public void insertCardWithoutNotification(int position, CardBuilder card, Action action) { mCards.add(position, card); mActions.add(position, action); } /** Deletes card from the adapter, without notifying. */ public void deleteCardWithoutNotification(int position) { mCards.remove(position); mActions.remove(position); } /** Returns the action associated with the card at position. */ public Action getActionAt(int position) { return mActions.get(position); } } private final Random mRandom = new Random(); private CardScrollView mCardScroller; private CardAdapterWithMutations mAdapter; @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); mCardScroller = new CardScrollView(this); setupAdapter(); setupClickListener(); setContentView(mCardScroller); } /** * Sets up adapter. */ private void setupAdapter() { mAdapter = new CardAdapterWithMutations(); // Insert initial cards, one of each kind. for (int i = 0; i < 8; i++) { int position = i; Action action = Action.values()[i]; CardBuilder card = new CardBuilder(this, CardBuilder.Layout.COLUMNS); card.setText(action.textId).addImage(action.imageId); mAdapter.insertCardWithoutNotification(position, card, action); } // Setting adapter notifies the card scroller of new content. mCardScroller.setAdapter(mAdapter); } /** * Sets up click listener. */ private void setupClickListener() { mCardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); switch (mAdapter.getActionAt(position)) { case DELETION_HERE: am.playSoundEffect(Sounds.TAP); deleteCard(position); break; case NAVIGATION_TO_BEGIN: am.playSoundEffect(Sounds.TAP); navigateToCard(0); break; case NAVIGATION_TO_END: am.playSoundEffect(Sounds.TAP); navigateToCard(mAdapter.getCount() - 1); break; case INSERTION_AT_BEGIN: am.playSoundEffect(Sounds.TAP); insertNewCard(0); break; case INSERTION_BEFORE: am.playSoundEffect(Sounds.TAP); insertNewCard(position); break; case INSERTION_AFTER: am.playSoundEffect(Sounds.TAP); insertNewCard(position + 1); break; case INSERTION_AT_END: am.playSoundEffect(Sounds.TAP); insertNewCard(mAdapter.getCount()); break; default: am.playSoundEffect(Sounds.DISALLOWED); break; } } }); } /** * Deletes a card at the given position using proper insertion animation * (the card scroller will animate the old card from view). */ private void deleteCard(int position) { // Delete card in the adapter, but don't call notifyDataSetChanged() yet. // Instead, request proper animation for deleted card from card scroller, // which will notify the adapter at the right time during the animation. mAdapter.deleteCardWithoutNotification(position); mCardScroller.animate(position, CardScrollView.Animation.DELETION); } /** Navigates to card at given position. */ private void navigateToCard(int position) { mCardScroller.animate(position, CardScrollView.Animation.NAVIGATION); } /** * Inserts a new card at the given position using proper insertion animation * (the card scroller will animate to the new card). */ private void insertNewCard(int position) { // Insert new card in the adapter, but don't call notifyDataSetChanged() // yet. Instead, request proper animation to inserted card from card scroller, // which will notify the adapter at the right time during the animation. CardBuilder card = new CardBuilder(this, CardBuilder.Layout.COLUMNS); Action action = Action.values()[mRandom.nextInt(8)]; card.setText(action.textId).addImage(action.imageId); mAdapter.insertCardWithoutNotification(position, card, action); mCardScroller.animate(position, CardScrollView.Animation.INSERTION); } @Override protected void onResume() { super.onResume(); mCardScroller.activate(); } @Override protected void onPause() { mCardScroller.deactivate(); super.onPause(); } }