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.view.KeyEvent;
20import android.view.LayoutInflater;
21import android.view.View;
22import android.view.ViewGroup;
23import android.view.inputmethod.EditorInfo;
24import android.widget.CheckBox;
25import android.widget.CompoundButton;
26import android.widget.EditText;
27import android.widget.TextView;
28
29import androidx.appcompat.app.AppCompatActivity;
30import androidx.recyclerview.widget.LinearLayoutManager;
31import androidx.recyclerview.widget.RecyclerView;
32import androidx.recyclerview.widget.SortedList;
33import androidx.recyclerview.widget.SortedListAdapterCallback;
34
35import com.example.android.supportv7.R;
36
37/**
38 * A sample activity that uses {@link SortedList} in combination with RecyclerView.
39 */
40public class SortedListActivity extends AppCompatActivity {
41    private RecyclerView mRecyclerView;
42    private LinearLayoutManager mLinearLayoutManager;
43    private SortedListAdapter mAdapter;
44    @Override
45    protected void onCreate(Bundle savedInstanceState) {
46        super.onCreate(savedInstanceState);
47        setContentView(R.layout.sorted_list_activity);
48        mRecyclerView = findViewById(R.id.recycler_view);
49        mRecyclerView.setHasFixedSize(true);
50        mLinearLayoutManager = new LinearLayoutManager(this);
51        mRecyclerView.setLayoutManager(mLinearLayoutManager);
52        mAdapter = new SortedListAdapter(getLayoutInflater(),
53                new Item("buy milk"), new Item("wash the car"),
54                new Item("wash the dishes"));
55        mRecyclerView.setAdapter(mAdapter);
56        mRecyclerView.setHasFixedSize(true);
57        final EditText newItemTextView = findViewById(R.id.new_item_text_view);
58        newItemTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
59            @Override
60            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
61                if (id == EditorInfo.IME_ACTION_DONE &&
62                        (keyEvent == null || keyEvent.getAction() == KeyEvent.ACTION_DOWN)) {
63                    final String text = textView.getText().toString().trim();
64                    if (text.length() > 0) {
65                        mAdapter.addItem(new Item(text));
66                    }
67                    textView.setText("");
68                    return true;
69                }
70                return false;
71            }
72        });
73    }
74
75    private static class SortedListAdapter extends RecyclerView.Adapter<TodoViewHolder> {
76        SortedList<Item> mData;
77        final LayoutInflater mLayoutInflater;
78        public SortedListAdapter(LayoutInflater layoutInflater, Item... items) {
79            mLayoutInflater = layoutInflater;
80            mData = new SortedList<Item>(Item.class, new SortedListAdapterCallback<Item>(this) {
81                @Override
82                public int compare(Item t0, Item t1) {
83                    if (t0.mIsDone != t1.mIsDone) {
84                        return t0.mIsDone ? 1 : -1;
85                    }
86                    int txtComp = t0.mText.compareTo(t1.mText);
87                    if (txtComp != 0) {
88                        return txtComp;
89                    }
90                    if (t0.id < t1.id) {
91                        return -1;
92                    } else if (t0.id > t1.id) {
93                        return 1;
94                    }
95                    return 0;
96                }
97
98                @Override
99                public boolean areContentsTheSame(Item oldItem,
100                        Item newItem) {
101                    return oldItem.mText.equals(newItem.mText);
102                }
103
104                @Override
105                public boolean areItemsTheSame(Item item1, Item item2) {
106                    return item1.id == item2.id;
107                }
108            });
109            for (Item item : items) {
110                mData.add(item);
111            }
112        }
113
114        public void addItem(Item item) {
115            mData.add(item);
116        }
117
118        @Override
119        public TodoViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
120            return new TodoViewHolder (
121                    mLayoutInflater.inflate(R.layout.sorted_list_item_view, parent, false)) {
122                @Override
123                void onDoneChanged(boolean isDone) {
124                    int adapterPosition = getAdapterPosition();
125                    if (adapterPosition == RecyclerView.NO_POSITION) {
126                        return;
127                    }
128                    mBoundItem.mIsDone = isDone;
129                    mData.recalculatePositionOfItemAt(adapterPosition);
130                }
131            };
132        }
133
134        @Override
135        public void onBindViewHolder(TodoViewHolder holder, int position) {
136            holder.bindTo(mData.get(position));
137        }
138
139        @Override
140        public int getItemCount() {
141            return mData.size();
142        }
143    }
144
145    abstract private static class TodoViewHolder extends RecyclerView.ViewHolder {
146        final CheckBox mCheckBox;
147        Item mBoundItem;
148        public TodoViewHolder(View itemView) {
149            super(itemView);
150            mCheckBox = (CheckBox) itemView;
151            mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
152                @Override
153                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
154                    if (mBoundItem != null && isChecked != mBoundItem.mIsDone) {
155                        onDoneChanged(isChecked);
156                    }
157                }
158            });
159        }
160
161        public void bindTo(Item item) {
162            mBoundItem = item;
163            mCheckBox.setText(item.mText);
164            mCheckBox.setChecked(item.mIsDone);
165        }
166
167        abstract void onDoneChanged(boolean isChecked);
168    }
169
170    private static class Item {
171        String mText;
172        boolean mIsDone = false;
173        final public int id;
174        private static int idCounter = 0;
175
176        public Item(String text) {
177            id = idCounter ++;
178            this.mText = text;
179        }
180    }
181}
182