diff options
Diffstat (limited to 'android/app/slice/views/LargeSliceAdapter.java')
-rw-r--r-- | android/app/slice/views/LargeSliceAdapter.java | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/android/app/slice/views/LargeSliceAdapter.java b/android/app/slice/views/LargeSliceAdapter.java new file mode 100644 index 00000000..6794ff98 --- /dev/null +++ b/android/app/slice/views/LargeSliceAdapter.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.slice.views; + +import android.app.slice.Slice; +import android.app.slice.SliceItem; +import android.app.slice.SliceQuery; +import android.app.slice.views.LargeSliceAdapter.SliceViewHolder; +import android.content.Context; +import android.util.ArrayMap; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.FrameLayout; + +import com.android.internal.R; +import com.android.internal.widget.RecyclerView; +import com.android.internal.widget.RecyclerView.ViewHolder; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @hide + */ +public class LargeSliceAdapter extends RecyclerView.Adapter<SliceViewHolder> { + + public static final int TYPE_DEFAULT = 1; + public static final int TYPE_HEADER = 2; + public static final int TYPE_GRID = 3; + public static final int TYPE_MESSAGE = 4; + public static final int TYPE_MESSAGE_LOCAL = 5; + public static final int TYPE_REMOTE_VIEWS = 6; + + private final IdGenerator mIdGen = new IdGenerator(); + private final Context mContext; + private List<SliceWrapper> mSlices = new ArrayList<>(); + private SliceItem mColor; + + public LargeSliceAdapter(Context context) { + mContext = context; + setHasStableIds(true); + } + + /** + * Set the {@link SliceItem}'s to be displayed in the adapter and the accent color. + */ + public void setSliceItems(List<SliceItem> slices, SliceItem color) { + mColor = color; + mIdGen.resetUsage(); + mSlices = slices.stream().map(s -> new SliceWrapper(s, mIdGen)) + .collect(Collectors.toList()); + notifyDataSetChanged(); + } + + @Override + public SliceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = inflateforType(viewType); + v.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + return new SliceViewHolder(v); + } + + @Override + public int getItemViewType(int position) { + return mSlices.get(position).mType; + } + + @Override + public long getItemId(int position) { + return mSlices.get(position).mId; + } + + @Override + public int getItemCount() { + return mSlices.size(); + } + + @Override + public void onBindViewHolder(SliceViewHolder holder, int position) { + SliceWrapper slice = mSlices.get(position); + if (holder.mSliceView != null) { + holder.mSliceView.setColor(mColor); + holder.mSliceView.setSliceItem(slice.mItem); + } else if (slice.mType == TYPE_REMOTE_VIEWS) { + FrameLayout frame = (FrameLayout) holder.itemView; + frame.removeAllViews(); + frame.addView(slice.mItem.getRemoteView().apply(mContext, frame)); + } + } + + private View inflateforType(int viewType) { + switch (viewType) { + case TYPE_REMOTE_VIEWS: + return new FrameLayout(mContext); + case TYPE_GRID: + return LayoutInflater.from(mContext).inflate(R.layout.slice_grid, null); + case TYPE_MESSAGE: + return LayoutInflater.from(mContext).inflate(R.layout.slice_message, null); + case TYPE_MESSAGE_LOCAL: + return LayoutInflater.from(mContext).inflate(R.layout.slice_message_local, null); + } + return new SmallTemplateView(mContext); + } + + protected static class SliceWrapper { + private final SliceItem mItem; + private final int mType; + private final long mId; + + public SliceWrapper(SliceItem item, IdGenerator idGen) { + mItem = item; + mType = getType(item); + mId = idGen.getId(item); + } + + public static int getType(SliceItem item) { + if (item.getType() == SliceItem.TYPE_REMOTE_VIEW) { + return TYPE_REMOTE_VIEWS; + } + if (item.hasHint(Slice.HINT_MESSAGE)) { + // TODO: Better way to determine me or not? Something more like Messaging style. + if (SliceQuery.find(item, -1, Slice.HINT_SOURCE, null) != null) { + return TYPE_MESSAGE; + } else { + return TYPE_MESSAGE_LOCAL; + } + } + if (item.hasHint(Slice.HINT_HORIZONTAL)) { + return TYPE_GRID; + } + return TYPE_DEFAULT; + } + } + + /** + * A {@link ViewHolder} for presenting slices in {@link LargeSliceAdapter}. + */ + public static class SliceViewHolder extends ViewHolder { + public final SliceListView mSliceView; + + public SliceViewHolder(View itemView) { + super(itemView); + mSliceView = itemView instanceof SliceListView ? (SliceListView) itemView : null; + } + } + + /** + * View slices being displayed in {@link LargeSliceAdapter}. + */ + public interface SliceListView { + /** + * Set the slice item for this view. + */ + void setSliceItem(SliceItem slice); + + /** + * Set the color for the items in this view. + */ + default void setColor(SliceItem color) { + + } + } + + private static class IdGenerator { + private long mNextLong = 0; + private final ArrayMap<String, Long> mCurrentIds = new ArrayMap<>(); + private final ArrayMap<String, Integer> mUsedIds = new ArrayMap<>(); + + public long getId(SliceItem item) { + String str = genString(item); + if (!mCurrentIds.containsKey(str)) { + mCurrentIds.put(str, mNextLong++); + } + long id = mCurrentIds.get(str); + int index = mUsedIds.getOrDefault(str, 0); + mUsedIds.put(str, index + 1); + return id + index * 10000; + } + + private String genString(SliceItem item) { + StringBuilder builder = new StringBuilder(); + SliceQuery.stream(item).forEach(i -> { + builder.append(i.getType()); + i.removeHint(Slice.HINT_SELECTED); + builder.append(i.getHints()); + switch (i.getType()) { + case SliceItem.TYPE_REMOTE_VIEW: + builder.append(i.getRemoteView()); + break; + case SliceItem.TYPE_IMAGE: + builder.append(i.getIcon()); + break; + case SliceItem.TYPE_TEXT: + builder.append(i.getText()); + break; + case SliceItem.TYPE_COLOR: + builder.append(i.getColor()); + break; + } + }); + return builder.toString(); + } + + public void resetUsage() { + mUsedIds.clear(); + } + } +} |