カードスクローラー

Glass では、スクロールなどのカードとの充実したインタラクションを構築できます 作成できます

アクティビティでのカードのスクロール

Glass のディスプレイとタッチパッドは、スワイプ可能なカードの表示や、 タイムラインが表示されます。アクティビティを作成する場合は、 同じタイプのエフェクトを CardScrollView 追加します。

  1. 実装 CardScrollAdapter カードをクラウドに CardScrollView。 標準のビュー階層を自分で作成することも、 CardBuilder クラスです。
  2. 作成: CardScrollView 使用する CardScrollAdapter クレジットカードのサプライヤーとして 選ばれました
  3. アクティビティのコンテンツ ビューを CardScrollView 表示させることができる CardScrollView 渡します。

3 つのカードをスクロールするシンプルな実装を次に示します。

public class CardScrollActivity extends Activity {

    private List<CardBuilder> mCards;
    private CardScrollView mCardScrollView;
    private ExampleCardScrollAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        createCards();

        mCardScrollView = new CardScrollView(this);
        mAdapter = new ExampleCardScrollAdapter();
        mCardScrollView.setAdapter(mAdapter);
        mCardScrollView.activate();
        setContentView(mCardScrollView);
    }

    private void createCards() {
        mCards = new ArrayList<CardBuilder>();

        mCards.add(new CardBuilder(this, CardBuilder.Layout.TEXT)
                .setText("This card has a footer.")
                .setFootnote("I'm the footer!"));

        mCards.add(new CardBuilder(this, CardBuilder.Layout.CAPTION)
                .setText("This card has a puppy background image.")
                .setFootnote("How can you resist?")
                .addImage(R.drawable.puppy_bg));

        mCards.add(new CardBuilder(this, CardBuilder.Layout.COLUMNS)
                .setText("This card has a mosaic of puppies.")
                .setFootnote("Aren't they precious?")
                .addImage(R.drawable.puppy_small_1);
                .addImage(R.drawable.puppy_small_2);
                .addImage(R.drawable.puppy_small_3));
    }

    private class ExampleCardScrollAdapter extends CardScrollAdapter {

        @Override
        public int getPosition(Object item) {
            return mCards.indexOf(item);
        }

        @Override
        public int getCount() {
            return mCards.size();
        }

        @Override
        public Object getItem(int position) {
            return mCards.get(position);
        }

        @Override
        public int getViewTypeCount() {
            return CardBuilder.getViewTypeCount();
        }

        @Override
        public int getItemViewType(int position){
            return mCards.get(position).getItemViewType();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return mCards.get(position).getView(convertView, parent);
        }
    }
}

スクロール カードの操作

以降 CardScrollView AdapterView の拡張 標準の Android リスナーを実装できます。

  1. 継承された CardScrollViewsetOnItemClickListener()
  2. 新しい onItemClick() 使用します。

以下は、タップ音を再生する前の例を拡張したものです。 カードをタップしたとき:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        setupClickListener();
        setContentView(mCardScrollView);
    }

    private void setupClickListener() {
        mCardScrollView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                am.playSoundEffect(Sounds.TAP);
            }
        });
    }

スクロール カードのアニメーション化

カードのスクロールに使用できるアニメーションは、ナビゲーション、挿入、削除の 3 つです。

  1. カードセット内の指定された位置にあるカードに対して挿入アクションや削除アクションを実装します。
  2. 発信 animate() CardScrollView.Animation 列挙型の値を使用します。
  3. スムーズなアニメーションを表示するには、 notifyDataSetChanged()animate() データセット ビューの更新を処理します。

    private class ExampleCardScrollAdapter extends CardScrollAdapter {
        ...
    
        // Inserts a card into the adapter, without notifying.
        public void insertCardWithoutNotification(int position, CardBuilder card) {
            mCards.add(position, card);
        }
    }
    
    private void insertNewCard(int position, CardBuilder card) {
        // 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.
        mAdapter.insertCardWithoutNotification(position, card);
        mCardScrollView.animate(position, CardScrollView.Animation.INSERTION);
    }
    

スクロール カードのパフォーマンスと実装に関するヒント

作成時には、次の設計とパフォーマンスへの影響に留意してください カード スクローラー。

カードのライフサイクル

パフォーマンスを向上させるには、CardScrollView カードのサブセットのみが読み込まれるように CardScrollAdapter 提供されるもの(一般に、ユーザーに表示されるもの以外に、その他のもの)があります。 そのため、カードは一般的に次の 4 つの状態のいずれかになります。

  • Detached - 現在の時刻では、カードのスクロール ビューにこのカードは必要ありません。 カードの onDetachedToWindow() によって通知されます。 以前にカードがアタッチされた後に切断された場合は、メソッドを呼び出します。
  • 接続済み - カードのスクロール ビューが、アダプターにカードをリクエストします。 カードが「有効化」間近のため、getView()。 その場合は、カードの onAttachedToWindow() メソッドによって通知されます。
  • 有効 - カードは部分的に表示されますが、カードのスクロールは可能です。 ビューが「selected」になっていないユーザーに表示するカードです「 'isActivated()' メソッド この場合は true を返します。
  • 選択済み - カードがユーザーの 表示できます。getSelectedView() を呼び出すと、現在選択されているカードが返されます。isSelected() メソッドが返す true になります。

カードのビューをアニメーション化したり、その他のコストのかかる処理を行っている場合は、 操作の開始と停止を onAttachedToWindow() および onDetachedToWindow() リソースを節約できます。

カードのリサイクル

カードをアタッチしてからデタッチすると、関連付けられているビュー オブジェクトが カードはリサイクルされて、添付されたカードで使用できます。 更新された情報でビューを再利用することは、 新しいビューを作成します。

カードのリサイクルを利用するには、 getItemViewType() getViewTypeCount(), および getView() メソッド CardScrollAdapter クラスです。次に、CardBuilder の便利なメソッドをいくつか使用します。 クラスを使用して CardScrollAdapter でリサイクルを実装する。 次のようになります。

private List<CardBuilder> mCards;
...
/**
 * Returns the number of view types for the CardBuilder class. The
 * CardBuilder class has a convenience method that returns this value for
 * you.
 */
@Override
public int getViewTypeCount() {
    return CardBuilder.getViewTypeCount();
}

/**
 * Returns the view type of this card, so the system can figure out
 * if it can be recycled. The CardBuilder.getItemViewType() method
 * returns it's own type.
 */
@Override
public int getItemViewType(int position){
    return mCards.get(position).getItemViewType();
}

/**
 * When requesting a card from the adapter, recycle the view if possible.
 * The CardBuilder.getView() method automatically recycles the convertView
 * it receives, if possible, or creates a new view if convertView is null or
 * of the wrong type.
 */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    return  mCards.get(position).getView(convertView, parent);
}

固定のカード ID を実装する

カードが選択されてユーザーに表示されるとき、 基になるアダプターを変更して、ユーザーに表示されるカードに影響を与える場合 できます。たとえば、ユーザーが選択したカードを表示していて、 ユーザーがカードを削除する場合は 実際に見たときの様子が左にシフトしています。 CardScrollAdapter デフォルトでは、変更が発生したときに基になるデータセットに ID が再割り当てされます。

カードに一意の ID を割り当てることが論理的に合理的である場合は、 基になるデータセットに一貫した ID を割り当てることで、前述の問題を防止できます。 これを行うには、 hasStableIds() true を返します。これにより、システムに対して CardScrollAdapter データセットの変更後も不変の ID を維持します。さらに getItemId() を使用して、アダプタ内のカードの適切な一意の ID を返します。 デフォルトの実装では、アダプター内のカードの位置インデックスが返されますが、 本質的に不安定です

空の Card スクロールアダプタ

アダプタの空のデータセットがある場合、デフォルトのビューには、 画面が黒くなることがあります。このような場合に別のビューを表示するには、 setEmptyView() は使用しないでください。 代わりに、CardScrollAdapter でカードを 1 枚作成します。

水平方向のスライドのフィードバック

Glass に内蔵されている多くの浸透器は「引っ張り」を提供します。フィードバック機能 アクションを実行しません。たとえばこのフィードバックは スワイプですばやく操作できます。

水平方向のスワイプ操作で 使用する場合は、Terraform でモジュールをラップすることで、 スペース内のレイアウトを CardScrollView 1 枚のカードが表示されます

  1. 次のヘルパークラスをプロジェクトにコピーします。

    public class TuggableView extends CardScrollView {
    
        private final View mContentView;
    
        /**
         * Initializes a TuggableView that uses the specified layout
         * resource for its user interface.
         */
        public TuggableView(Context context, int layoutResId) {
            this(context, LayoutInflater.from(context)
                    .inflate(layoutResId, null));
        }
    
        /**
         * Initializes a TuggableView that uses the specified view
         * for its user interface.
         */
        public TuggableView(Context context, View view) {
            super(context);
    
            mContentView = view;
            setAdapter(new SingleCardAdapter());
            activate();
        }
    
        /**
         * Overridden to return false so that all motion events still
         * bubble up to the activity's onGenericMotionEvent() method after
         * they are handled by the card scroller. This allows the activity
         * to handle TAP gestures using a GestureDetector instead of the
         * card scroller's OnItemClickedListener.
         */
        @Override
        protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
            super.dispatchGenericFocusedEvent(event);
            return false;
        }
    
        /** Holds the single "card" inside the card scroll view. */
        private class SingleCardAdapter extends CardScrollAdapter {
    
            @Override
            public int getPosition(Object item) {
                return 0;
            }
    
            @Override
            public int getCount() {
                return 1;
            }
    
            @Override
            public Object getItem(int position) {
                return mContentView;
            }
    
            @Override
            public View getView(int position, View recycleView,
                    ViewGroup parent) {
                return mContentView;
            }
        }
    }
    
  2. アクティビティの onCreate メソッドを変更して、CardScrollView を表示する レイアウトを格納します。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // was: setContentView(R.layout.main_activity);
        setContentView(new TuggableView(this, R.layout.main_activity));
    }