18a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk/* 28a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Copyright 2017 The Android Open Source Project 38a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * 48a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 58a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * you may not use this file except in compliance with the License. 68a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * You may obtain a copy of the License at 78a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * 88a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 98a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * 108a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Unless required by applicable law or agreed to in writing, software 118a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 128a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * See the License for the specific language governing permissions and 148a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * limitations under the License. 158a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk */ 168a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 1785ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikaspackage androidx.slice.widget; 188a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 19dcb5e2f13fa8471f62a7f4625b4dc6e449358cbdJason Monkimport static android.app.slice.Slice.HINT_HORIZONTAL; 200929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellorimport static android.app.slice.Slice.HINT_SUMMARY; 210c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monkimport static android.app.slice.Slice.SUBTYPE_MESSAGE; 220c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monkimport static android.app.slice.Slice.SUBTYPE_SOURCE; 2398ae4f80b7244070c20d5c3a16245df5cd0c5df8Jason Monkimport static android.app.slice.SliceItem.FORMAT_INT; 240c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monkimport static android.app.slice.SliceItem.FORMAT_TEXT; 250c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk 2685ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport static androidx.slice.widget.SliceView.MODE_LARGE; 277c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor 28c1334184900d93f73e879d02a32715a5579aa55fMady Mellorimport android.app.slice.Slice; 298a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkimport android.content.Context; 30dc05204762b444dde1db9029aed2819fd72476f7Mady Mellorimport android.util.AttributeSet; 318a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkimport android.view.LayoutInflater; 326975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellorimport android.view.MotionEvent; 338a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkimport android.view.View; 348a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkimport android.view.ViewGroup; 358a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkimport android.view.ViewGroup.LayoutParams; 368a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 3763fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport androidx.annotation.RestrictTo; 38f68dde011de8fb4d616a09292524869f56d94110Jason Monkimport androidx.collection.ArrayMap; 3963fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport androidx.recyclerview.widget.RecyclerView; 4085ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.SliceItem; 4185ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.core.SliceQuery; 4285ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.view.R; 438a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 4463fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport java.util.ArrayList; 45f68dde011de8fb4d616a09292524869f56d94110Jason Monkimport java.util.Iterator; 4663fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport java.util.List; 4763fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor 488a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk/** 498a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * @hide 508a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk */ 518a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk@RestrictTo(RestrictTo.Scope.LIBRARY) 528a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monkpublic class LargeSliceAdapter extends RecyclerView.Adapter<LargeSliceAdapter.SliceViewHolder> { 538a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 54dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor static final int TYPE_DEFAULT = 1; 55dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor static final int TYPE_HEADER = 2; // TODO: headers shouldn't scroll off 56dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor static final int TYPE_GRID = 3; 57dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor static final int TYPE_MESSAGE = 4; 58dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor static final int TYPE_MESSAGE_LOCAL = 5; 598a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 6063fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor static final int HEADER_INDEX = 0; 6163fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor 628a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final IdGenerator mIdGen = new IdGenerator(); 638a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final Context mContext; 648a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private List<SliceWrapper> mSlices = new ArrayList<>(); 65abd7ffd938056760f750af041b0e6f02d2cb6e1eMady Mellor private SliceView.OnSliceActionListener mSliceObserver; 66dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor private int mColor; 67dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor private AttributeSet mAttrs; 6877d3fe9d9b671c0b3853fec6bc21b91d8418afc9Mady Mellor private int mDefStyleAttr; 6977d3fe9d9b671c0b3853fec6bc21b91d8418afc9Mady Mellor private int mDefStyleRes; 70b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor private List<SliceItem> mSliceActions; 7163fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor private boolean mShowLastUpdated; 7263fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor private long mLastUpdated; 736975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor private SliceView mParent; 746975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor private LargeTemplateView mTemplateView; 758a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 768a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public LargeSliceAdapter(Context context) { 778a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk mContext = context; 788a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk setHasStableIds(true); 798a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 808a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 816975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor /** 826975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * Sets the SliceView parent and the template parent. 836975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor */ 846975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor public void setParents(SliceView parent, LargeTemplateView templateView) { 856975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mParent = parent; 866975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mTemplateView = templateView; 876975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 886975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor 896975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor /** 906975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * Sets the observer to pass down to child views. 916975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor */ 92abd7ffd938056760f750af041b0e6f02d2cb6e1eMady Mellor public void setSliceObserver(SliceView.OnSliceActionListener observer) { 93238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor mSliceObserver = observer; 94238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor } 95238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor 968a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk /** 97b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor * Sets the actions to display for this slice, this adjusts what's displayed in the header item. 98b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor */ 99b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor public void setSliceActions(List<SliceItem> actions) { 100b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor mSliceActions = actions; 10163fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor notifyHeaderChanged(); 102b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor } 103b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor 104b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor /** 1058a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * Set the {@link SliceItem}'s to be displayed in the adapter and the accent color. 1068a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk */ 1070929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor public void setSliceItems(List<SliceItem> slices, int color, int mode) { 108df26970a23ca28c8582178e3dd0e5502d4030293Mady Mellor if (slices == null) { 109df26970a23ca28c8582178e3dd0e5502d4030293Mady Mellor mSlices.clear(); 110df26970a23ca28c8582178e3dd0e5502d4030293Mady Mellor } else { 111df26970a23ca28c8582178e3dd0e5502d4030293Mady Mellor mIdGen.resetUsage(); 11206ab4aa38f82b8e2d9af769f7c777253f2497f93Jake Wharton mSlices = new ArrayList<>(slices.size()); 11306ab4aa38f82b8e2d9af769f7c777253f2497f93Jake Wharton for (SliceItem s : slices) { 1140929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor mSlices.add(new SliceWrapper(s, mIdGen, mode)); 11506ab4aa38f82b8e2d9af769f7c777253f2497f93Jake Wharton } 116df26970a23ca28c8582178e3dd0e5502d4030293Mady Mellor } 1178a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk mColor = color; 1188a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk notifyDataSetChanged(); 1198a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1208a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 121dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor /** 122dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor * Sets the attribute set to use for views in the list. 123dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor */ 12477d3fe9d9b671c0b3853fec6bc21b91d8418afc9Mady Mellor public void setStyle(AttributeSet attrs, int defStyleAttr, int defStyleRes) { 125dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor mAttrs = attrs; 12677d3fe9d9b671c0b3853fec6bc21b91d8418afc9Mady Mellor mDefStyleAttr = defStyleAttr; 12777d3fe9d9b671c0b3853fec6bc21b91d8418afc9Mady Mellor mDefStyleRes = defStyleRes; 128dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor notifyDataSetChanged(); 129dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor } 130dc05204762b444dde1db9029aed2819fd72476f7Mady Mellor 13163fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor /** 13263fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor * Sets whether the last updated time should be shown on the slice. 13363fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor */ 13463fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor public void setShowLastUpdated(boolean showLastUpdated) { 13563fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor mShowLastUpdated = showLastUpdated; 13663fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor notifyHeaderChanged(); 13763fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor } 13863fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor 13963fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor /** 14063fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor * Sets when the slice was last updated. 14163fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor */ 14263fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor public void setLastUpdated(long lastUpdated) { 14363fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor mLastUpdated = lastUpdated; 14463fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor notifyHeaderChanged(); 14563fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor } 14663fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor 1478a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk @Override 1488a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public SliceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 1498a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk View v = inflateForType(viewType); 1508a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk v.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 1518a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return new SliceViewHolder(v); 1528a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1538a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 1548a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk @Override 1558a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public int getItemViewType(int position) { 1568a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return mSlices.get(position).mType; 1578a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1588a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 1598a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk @Override 1608a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public long getItemId(int position) { 1618a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return mSlices.get(position).mId; 1628a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1638a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 1648a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk @Override 1658a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public int getItemCount() { 1668a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return mSlices.size(); 1678a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1688a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 1698a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk @Override 1708a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public void onBindViewHolder(SliceViewHolder holder, int position) { 1718a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk SliceWrapper slice = mSlices.get(position); 1726975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor holder.bind(slice.mItem, position); 1738a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1748a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 17563fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor private void notifyHeaderChanged() { 17663fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor if (getItemCount() > 0) { 17763fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor notifyItemChanged(HEADER_INDEX); 17863fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor } 17963fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor } 18063fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor 1818a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private View inflateForType(int viewType) { 1827c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor View v = new RowView(mContext); 1838a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk switch (viewType) { 1848a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk case TYPE_GRID: 1857c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor v = LayoutInflater.from(mContext).inflate(R.layout.abc_slice_grid, null); 1867c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor break; 1878a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk case TYPE_MESSAGE: 1887c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor v = LayoutInflater.from(mContext).inflate(R.layout.abc_slice_message, null); 1897c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor break; 1908a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk case TYPE_MESSAGE_LOCAL: 1917c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor v = LayoutInflater.from(mContext).inflate(R.layout.abc_slice_message_local, 1928a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk null); 1937c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor break; 1948a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1957c19f268c4f3b016861816c350a13e7aa5743fc6Mady Mellor return v; 1968a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 1978a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 1988a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk protected static class SliceWrapper { 1998a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final SliceItem mItem; 2008a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final int mType; 2018a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final long mId; 2028a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 2030929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor public SliceWrapper(SliceItem item, IdGenerator idGen, int mode) { 2048a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk mItem = item; 2050c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk mType = getFormat(item); 2060929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor mId = idGen.getId(item, mode); 2078a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2088a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 2090c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk public static int getFormat(SliceItem item) { 2100c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk if (SUBTYPE_MESSAGE.equals(item.getSubType())) { 2118a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk // TODO: Better way to determine me or not? Something more like Messaging style. 2120c76d3038c814e26f15b16ce2e09e28bcbcedcc6Jason Monk if (SliceQuery.findSubtype(item, null, SUBTYPE_SOURCE) != null) { 2138a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return TYPE_MESSAGE; 2148a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } else { 2158a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return TYPE_MESSAGE_LOCAL; 2168a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2178a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 218dcb5e2f13fa8471f62a7f4625b4dc6e449358cbdJason Monk if (item.hasHint(HINT_HORIZONTAL)) { 2198a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return TYPE_GRID; 2208a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 221c1334184900d93f73e879d02a32715a5579aa55fMady Mellor if (!item.hasHint(Slice.HINT_LIST_ITEM)) { 222c1334184900d93f73e879d02a32715a5579aa55fMady Mellor return TYPE_HEADER; 223c1334184900d93f73e879d02a32715a5579aa55fMady Mellor } 2248a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return TYPE_DEFAULT; 2258a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2268a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2278a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 2288a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk /** 2298a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk * A {@link RecyclerView.ViewHolder} for presenting slices in {@link LargeSliceAdapter}. 2308a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk */ 2316975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor public class SliceViewHolder extends RecyclerView.ViewHolder implements View.OnTouchListener, 2326975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor View.OnClickListener { 2336975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor public final SliceChildView mSliceChildView; 2348a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 2358a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public SliceViewHolder(View itemView) { 2368a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk super(itemView); 2376975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mSliceChildView = itemView instanceof SliceChildView ? (SliceChildView) itemView : null; 2386975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2396975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor 2406975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor void bind(SliceItem item, int position) { 2416975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor if (mSliceChildView == null || item == null) { 2426975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor return; 2436975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2446975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor // Click listener used to pipe click events to parent 2456975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mSliceChildView.setOnClickListener(this); 2466975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor // Touch listener used to pipe events to touch feedback drawable 2476975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mSliceChildView.setOnTouchListener(this); 2486975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor 2496975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor final boolean isHeader = position == HEADER_INDEX; 250432265f1922d8d6bf208825855b2d16160599199Mady Mellor int mode = mParent != null ? mParent.getMode() : MODE_LARGE; 251432265f1922d8d6bf208825855b2d16160599199Mady Mellor mSliceChildView.setMode(mode); 2526975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mSliceChildView.setTint(mColor); 25377d3fe9d9b671c0b3853fec6bc21b91d8418afc9Mady Mellor mSliceChildView.setStyle(mAttrs, mDefStyleAttr, mDefStyleRes); 25465d77ea1ec28f1a623a1a7f8e624cf08c27d5faeMady Mellor mSliceChildView.setSliceItem(item, isHeader, position, getItemCount(), mSliceObserver); 2550929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor mSliceChildView.setSliceActions(isHeader ? mSliceActions : null); 2560929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor mSliceChildView.setLastUpdated(isHeader ? mLastUpdated : -1); 2570929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor mSliceChildView.setShowLastUpdated(isHeader && mShowLastUpdated); 2580929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor if (mSliceChildView instanceof RowView) { 259ba2ea6ccfa7239f89ed0a301d0c24afb46036976Mady Mellor ((RowView) mSliceChildView).setSingleItem(getItemCount() == 1); 2606975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2616975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor int[] info = new int[2]; 2626975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor info[0] = ListContent.getRowType(mContext, item, isHeader, mSliceActions); 2636975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor info[1] = position; 2646975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mSliceChildView.setTag(info); 2656975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2666975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor 2676975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor @Override 2686975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor public void onClick(View v) { 2696975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor if (mParent != null) { 2706975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mParent.setClickInfo((int[]) v.getTag()); 2716975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mParent.performClick(); 2726975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2736975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2746975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor 2756975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor @Override 2766975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor public boolean onTouch(View v, MotionEvent event) { 2776975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor if (mTemplateView != null) { 2786975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor mTemplateView.onForegroundActivated(event); 2796975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2806975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor return false; 2818a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2828a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2838a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 2848a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private static class IdGenerator { 2858a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private long mNextLong = 0; 2868a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final ArrayMap<String, Long> mCurrentIds = new ArrayMap<>(); 2878a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private final ArrayMap<String, Integer> mUsedIds = new ArrayMap<>(); 2888a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 2890929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor public long getId(SliceItem item, int mode) { 2908a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk String str = genString(item); 2910929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor SliceItem summary = SliceQuery.find(item, null, HINT_SUMMARY, null); 2920929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor if (summary != null) { 2930929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor str += mode; // mode matters 2940929cbe8a1ad88cb18e0cd3b50abba21840bc592Mady Mellor } 2958a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk if (!mCurrentIds.containsKey(str)) { 2968a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk mCurrentIds.put(str, mNextLong++); 2978a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 2988a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk long id = mCurrentIds.get(str); 29906ab4aa38f82b8e2d9af769f7c777253f2497f93Jake Wharton Integer usedIdIndex = mUsedIds.get(str); 30006ab4aa38f82b8e2d9af769f7c777253f2497f93Jake Wharton int index = usedIdIndex != null ? usedIdIndex : 0; 3018a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk mUsedIds.put(str, index + 1); 3028a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return id + index * 10000; 3038a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 3048a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 3058a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk private String genString(SliceItem item) { 3062a7d0fcd09ed39bbeda29e024c47fca617050094Jason Monk final StringBuilder builder = new StringBuilder(); 307f68dde011de8fb4d616a09292524869f56d94110Jason Monk Iterator<SliceItem> items = SliceQuery.stream(item); 308f68dde011de8fb4d616a09292524869f56d94110Jason Monk while (items.hasNext()) { 309f68dde011de8fb4d616a09292524869f56d94110Jason Monk SliceItem i = items.next(); 310f68dde011de8fb4d616a09292524869f56d94110Jason Monk builder.append(i.getFormat()); 311f68dde011de8fb4d616a09292524869f56d94110Jason Monk builder.append(i.getHints()); 312f68dde011de8fb4d616a09292524869f56d94110Jason Monk switch (i.getFormat()) { 313f68dde011de8fb4d616a09292524869f56d94110Jason Monk case FORMAT_TEXT: 314f68dde011de8fb4d616a09292524869f56d94110Jason Monk builder.append(i.getText()); 315f68dde011de8fb4d616a09292524869f56d94110Jason Monk break; 316f68dde011de8fb4d616a09292524869f56d94110Jason Monk case FORMAT_INT: 317f68dde011de8fb4d616a09292524869f56d94110Jason Monk builder.append(i.getInt()); 318f68dde011de8fb4d616a09292524869f56d94110Jason Monk break; 3198a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 320f68dde011de8fb4d616a09292524869f56d94110Jason Monk } 3218a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk return builder.toString(); 3228a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 3238a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk 3248a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk public void resetUsage() { 3258a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk mUsedIds.clear(); 3268a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 3278a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk } 3288a452e96e2308fe9515aa91b8e5b369eeefc25e7Jason Monk} 329