1ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu/*
2ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * Copyright (C) 2013 The Android Open Source Project
3ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu *
4ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * Licensed under the Apache License, Version 2.0 (the "License");
5ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * you may not use this file except in compliance with the License.
6ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * You may obtain a copy of the License at
7ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu *
8ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu *      http://www.apache.org/licenses/LICENSE-2.0
9ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu *
10ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * Unless required by applicable law or agreed to in writing, software
11ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * distributed under the License is distributed on an "AS IS" BASIS,
12ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * See the License for the specific language governing permissions and
14ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu * limitations under the License.
15ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu */
16ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
17ccea98979aa38d1061ae38a31271040a698c9d87Dake Gupackage com.example.android.leanback;
18ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
19ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.app.Activity;
20ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.content.Intent;
21ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.graphics.Color;
22ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.os.Bundle;
23b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Guimport android.support.v17.leanback.widget.HorizontalGridView;
24b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Guimport android.support.v17.leanback.widget.OnChildViewHolderSelectedListener;
25b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Guimport android.support.v7.widget.RecyclerView;
26ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.util.Log;
27ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.view.View;
28ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.view.View.OnClickListener;
29ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.view.View.OnFocusChangeListener;
30ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.view.ViewGroup;
31ccea98979aa38d1061ae38a31271040a698c9d87Dake Guimport android.widget.TextView;
32ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
33ccea98979aa38d1061ae38a31271040a698c9d87Dake Gupublic class HorizontalGridTestActivity extends Activity {
34ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private static final String TAG = "HorizontalGridTestActivity";
35ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private static final boolean DEBUG = true;
36ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private static final String SELECT_ACTION = "android.test.leanback.widget.SELECT";
37ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private static final int NUM_ITEMS = 100;
38ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private static final boolean STAGGERED = true;
39ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
40ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private HorizontalGridView mHorizontalGridView;
41ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
42ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
43ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        @Override
44ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
45ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            if (DEBUG) {
46ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                final String[] stateNames = { "IDLE", "DRAGGING", "SETTLING" };
47ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                Log.v(TAG, "onScrollStateChanged "
48ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                        + (newState < stateNames.length ? stateNames[newState] : newState));
49ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            }
50ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
51ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    };
52ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
53ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private View createView() {
54ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        View view = getLayoutInflater().inflate(R.layout.horizontal_grid, null, false);
55ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        mHorizontalGridView = (HorizontalGridView) view.findViewById(R.id.gridview);
56ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
57ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        mHorizontalGridView.setWindowAlignment(HorizontalGridView.WINDOW_ALIGN_BOTH_EDGE);
58ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        mHorizontalGridView.setWindowAlignmentOffsetPercent(35);
59b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu        mHorizontalGridView.setOnChildViewHolderSelectedListener(
60b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                new OnChildViewHolderSelectedListener() {
61b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                    @Override
62b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                    public void onChildViewHolderSelected(RecyclerView parent,
63b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                                                          RecyclerView.ViewHolder child,
64b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                                                          int position, int subposition) {
65b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                        if (DEBUG) Log.d(TAG, "onChildSelected position=" + position);
66b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                    }
67b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu
68b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu                });
69ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        return view;
70ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    }
71ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
72ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    @Override
73ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    protected void onCreate(Bundle savedInstanceState) {
74ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        super.onCreate(savedInstanceState);
75ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
76ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        if (DEBUG) Log.v(TAG, "onCreate");
77ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
78ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        RecyclerView.Adapter adapter = new MyAdapter();
79ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
80ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        View view = createView();
81ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
82ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        mHorizontalGridView.setAdapter(new MyAdapter());
83ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        setContentView(view);
84ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
85b7087e036a48f5a3db28d02ff7f9b97fbbc46c4fDake Gu        mHorizontalGridView.addOnScrollListener(mScrollListener);
86ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    }
87ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
88ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    @Override
89ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    protected void onNewIntent(Intent intent) {
90ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        if (DEBUG) Log.v(TAG, "onNewIntent " + intent);
91ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        if (intent.getAction().equals(SELECT_ACTION)) {
92ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            int position = intent.getIntExtra("SELECT_POSITION", -1);
93ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            if (position >= 0) {
94ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                mHorizontalGridView.setSelectedPosition(position);
95ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            }
96ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
97ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        super.onNewIntent(intent);
98ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    }
99ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
100ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private OnFocusChangeListener mItemFocusChangeListener = new OnFocusChangeListener() {
101ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
102ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        @Override
103ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public void onFocusChange(View v, boolean hasFocus) {
104ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            if (hasFocus) {
105ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                v.setBackgroundColor(Color.YELLOW);
106ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            } else {
107ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                v.setBackgroundColor(Color.LTGRAY);
108ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            }
109ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
110ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    };
111ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
112ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    private OnClickListener mItemClickListener = new OnClickListener() {
113ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        @Override
114ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public void onClick(View v) {
115ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            mHorizontalGridView.getAdapter().notifyDataSetChanged();
116ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
117ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    };
118ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
119ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    class MyAdapter extends RecyclerView.Adapter {
120ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
121ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        private int[] mItemLengths;
122ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
123ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        MyAdapter() {
124ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            mItemLengths = new int[NUM_ITEMS];
125ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            for (int i = 0; i < mItemLengths.length; i++) {
126ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                mItemLengths[i] = STAGGERED ? (int)(Math.random() * 180) + 180 : 240;
127ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            }
128ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
129ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
130ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        @Override
131ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
132ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            if (DEBUG) Log.v(TAG, "createViewHolder " + viewType);
133ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            TextView textView = new TextView(parent.getContext());
134ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            textView.setTextColor(Color.BLACK);
135ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            textView.setFocusable(true);
136ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            textView.setFocusableInTouchMode(true);
137ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            textView.setOnFocusChangeListener(mItemFocusChangeListener);
138ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            textView.setOnClickListener(mItemClickListener);
139ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            return new ViewHolder(textView);
140ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
141ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
142ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        @Override
143ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public void onBindViewHolder(RecyclerView.ViewHolder baseHolder, int position) {
144ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            if (DEBUG) Log.v(TAG, "bindViewHolder " + position + " " + baseHolder);
145ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            ViewHolder holder = (ViewHolder) baseHolder;
146ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            ((TextView) holder.itemView).setText("Item "+position);
147ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            holder.itemView.setBackgroundColor(Color.LTGRAY);
148ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            holder.itemView.setLayoutParams(new ViewGroup.MarginLayoutParams(mItemLengths[position],
149ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu                    80));
150ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
151ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
152ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        @Override
153ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public int getItemCount() {
154ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            return mItemLengths.length;
155ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
156ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    }
157ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
158ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    static class ViewHolder extends RecyclerView.ViewHolder {
159ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu
160ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        public ViewHolder(View v) {
161ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu            super(v);
162ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu        }
163ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu    }
164ccea98979aa38d1061ae38a31271040a698c9d87Dake Gu}
165