1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.example.android.supportv7.util;
17
18import android.os.Bundle;
19import android.support.v7.app.AppCompatActivity;
20import android.support.v7.util.SortedList;
21import android.support.v7.widget.LinearLayoutManager;
22import android.support.v7.widget.RecyclerView;
23import android.support.v7.widget.util.SortedListAdapterCallback;
24import android.view.KeyEvent;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
28import android.view.inputmethod.EditorInfo;
29import android.widget.CheckBox;
30import android.widget.CompoundButton;
31import android.widget.EditText;
32import android.widget.TextView;
33
34import com.example.android.supportv7.R;
35
36/**
37 * A sample activity that uses {@link SortedList} in combination with RecyclerView.
38 */
39public class SortedListActivity extends AppCompatActivity {
40    private RecyclerView mRecyclerView;
41    private LinearLayoutManager mLinearLayoutManager;
42    private SortedListAdapter mAdapter;
43    @Override
44    protected void onCreate(Bundle savedInstanceState) {
45        super.onCreate(savedInstanceState);
46        setContentView(R.layout.sorted_list_activity);
47        mRecyclerView = findViewById(R.id.recycler_view);
48        mRecyclerView.setHasFixedSize(true);
49        mLinearLayoutManager = new LinearLayoutManager(this);
50        mRecyclerView.setLayoutManager(mLinearLayoutManager);
51        mAdapter = new SortedListAdapter(getLayoutInflater(),
52                new Item("buy milk"), new Item("wash the car"),
53                new Item("wash the dishes"));
54        mRecyclerView.setAdapter(mAdapter);
55        mRecyclerView.setHasFixedSize(true);
56        final EditText newItemTextView = findViewById(R.id.new_item_text_view);
57        newItemTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
58            @Override
59            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
60                if (id == EditorInfo.IME_ACTION_DONE &&
61                        (keyEvent == null || keyEvent.getAction() == KeyEvent.ACTION_DOWN)) {
62                    final String text = textView.getText().toString().trim();
63                    if (text.length() > 0) {
64                        mAdapter.addItem(new Item(text));
65                    }
66                    textView.setText("");
67                    return true;
68                }
69                return false;
70            }
71        });
72    }
73
74    private static class SortedListAdapter extends RecyclerView.Adapter<TodoViewHolder> {
75        SortedList<Item> mData;
76        final LayoutInflater mLayoutInflater;
77        public SortedListAdapter(LayoutInflater layoutInflater, Item... items) {
78            mLayoutInflater = layoutInflater;
79            mData = new SortedList<Item>(Item.class, new SortedListAdapterCallback<Item>(this) {
80                @Override
81                public int compare(Item t0, Item t1) {
82                    if (t0.mIsDone != t1.mIsDone) {
83                        return t0.mIsDone ? 1 : -1;
84                    }
85                    int txtComp = t0.mText.compareTo(t1.mText);
86                    if (txtComp != 0) {
87                        return txtComp;
88                    }
89                    if (t0.id < t1.id) {
90                        return -1;
91                    } else if (t0.id > t1.id) {
92                        return 1;
93                    }
94                    return 0;
95                }
96
97                @Override
98                public boolean areContentsTheSame(Item oldItem,
99                        Item newItem) {
100                    return oldItem.mText.equals(newItem.mText);
101                }
102
103                @Override
104                public boolean areItemsTheSame(Item item1, Item item2) {
105                    return item1.id == item2.id;
106                }
107            });
108            for (Item item : items) {
109                mData.add(item);
110            }
111        }
112
113        public void addItem(Item item) {
114            mData.add(item);
115        }
116
117        @Override
118        public TodoViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
119            return new TodoViewHolder (
120                    mLayoutInflater.inflate(R.layout.sorted_list_item_view, parent, false)) {
121                @Override
122                void onDoneChanged(boolean isDone) {
123                    int adapterPosition = getAdapterPosition();
124                    if (adapterPosition == RecyclerView.NO_POSITION) {
125                        return;
126                    }
127                    mBoundItem.mIsDone = isDone;
128                    mData.recalculatePositionOfItemAt(adapterPosition);
129                }
130            };
131        }
132
133        @Override
134        public void onBindViewHolder(TodoViewHolder holder, int position) {
135            holder.bindTo(mData.get(position));
136        }
137
138        @Override
139        public int getItemCount() {
140            return mData.size();
141        }
142    }
143
144    abstract private static class TodoViewHolder extends RecyclerView.ViewHolder {
145        final CheckBox mCheckBox;
146        Item mBoundItem;
147        public TodoViewHolder(View itemView) {
148            super(itemView);
149            mCheckBox = (CheckBox) itemView;
150            mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
151                @Override
152                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
153                    if (mBoundItem != null && isChecked != mBoundItem.mIsDone) {
154                        onDoneChanged(isChecked);
155                    }
156                }
157            });
158        }
159
160        public void bindTo(Item item) {
161            mBoundItem = item;
162            mCheckBox.setText(item.mText);
163            mCheckBox.setChecked(item.mIsDone);
164        }
165
166        abstract void onDoneChanged(boolean isChecked);
167    }
168
169    private static class Item {
170        String mText;
171        boolean mIsDone = false;
172        final public int id;
173        private static int idCounter = 0;
174
175        public Item(String text) {
176            id = idCounter ++;
177            this.mText = text;
178        }
179    }
180}
181