package com.mylhyl.circledialog.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.TextView; import com.mylhyl.circledialog.internal.BackgroundHelper; import com.mylhyl.circledialog.internal.Controller; import com.mylhyl.circledialog.callback.CircleItemLabel; import com.mylhyl.circledialog.callback.CircleItemViewBinder; import com.mylhyl.circledialog.params.DialogParams; import com.mylhyl.circledialog.params.ItemsParams; import com.mylhyl.circledialog.res.drawable.CircleDrawableSelector; import com.mylhyl.circledialog.res.values.CircleColor; import com.mylhyl.circledialog.view.listener.ItemsView; import com.mylhyl.circledialog.view.listener.OnRvItemClickListener; import java.util.Arrays; import java.util.List; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; /** * Created by hupei on 2018/4/18. */ class BodyRecyclerView extends RecyclerView implements ItemsView { protected DialogParams mDialogParams; private ItemsParams mItemsParams; private Adapter mAdapter; private LayoutManager mLayoutManager; private Context mContext; public BodyRecyclerView(Context context, ItemsParams itemsParams, DialogParams dialogParams) { super(context); mContext = context; this.mItemsParams = itemsParams; this.mDialogParams = dialogParams; init(); } @Override public void refreshItems() { mAdapter.notifyDataSetChanged(); } @Override public void regOnItemClickListener(AdapterView.OnItemClickListener listener) { } @Override public void regOnItemClickListener(OnRvItemClickListener listener) { if (mAdapter != null && mAdapter instanceof ItemsAdapter) { ((ItemsAdapter) mAdapter).setOnItemClickListener(listener); } } @Override public View getView() { return this; } private void init() { configBackground(); createLayoutManager(); createItemDecoration(); createAdapter(); } private void configBackground() { //如果没有背景色,则使用默认色 int backgroundColor = mItemsParams.backgroundColor != 0 ? mItemsParams.backgroundColor : mDialogParams.backgroundColor; setBackgroundColor(backgroundColor); } private void createLayoutManager() { if (mItemsParams.layoutManager == null) { mLayoutManager = new LinearLayoutManager(mContext, mItemsParams.linearLayoutManagerOrientation, false); } else if (mItemsParams.layoutManager instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) mItemsParams.layoutManager; mLayoutManager = new StaggeredGridLayoutManagerWrapper(staggeredGridLayoutManager); } else if (mItemsParams.layoutManager instanceof GridLayoutManager) { GridLayoutManager gridLayoutManager = (GridLayoutManager) mItemsParams.layoutManager; if (gridLayoutManager.getSpanCount() == 1) { mLayoutManager = new LinearLayoutManager(mContext, mItemsParams.linearLayoutManagerOrientation, false); } else { mLayoutManager = new GridLayoutManagerWrapper(mContext, gridLayoutManager); } } else if (mItemsParams.layoutManager instanceof LinearLayoutManager) { LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mItemsParams.layoutManager; mLayoutManager = new LinearLayoutManagerWrapper(mContext, linearLayoutManager); } else { mLayoutManager = mItemsParams.layoutManager; } setLayoutManager(mLayoutManager); setHasFixedSize(true); } private void createItemDecoration() { if (mItemsParams.dividerHeight > 0 && (mLayoutManager instanceof LayoutManager)) { if (mLayoutManager instanceof GridLayoutManager && mItemsParams.itemDecoration == null) { mItemsParams.itemDecoration = new GridItemDecoration(new ColorDrawable(CircleColor.divider), Controller.dp2px(mContext, mItemsParams.dividerHeight)); } else if (mLayoutManager instanceof LinearLayoutManager && mItemsParams.itemDecoration == null) { int orientation = ((LinearLayoutManager) mLayoutManager).getOrientation(); mItemsParams.itemDecoration = new LinearItemDecoration(new ColorDrawable(CircleColor.divider), Controller.dp2px(mContext, mItemsParams.dividerHeight), orientation); } addItemDecoration(mItemsParams.itemDecoration); } } private void createAdapter() { mAdapter = mItemsParams.adapterRv; if (mAdapter == null) { mAdapter = new ItemsAdapter(mContext, mItemsParams, mDialogParams, mLayoutManager); if (mLayoutManager instanceof GridLayoutManager) { final GridLayoutManager gridLayoutManager = (GridLayoutManager) mLayoutManager; if (gridLayoutManager.getSpanSizeLookup() instanceof GridLayoutManager.DefaultSpanSizeLookup) { gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int itemCount = mAdapter.getItemCount(); int spanCount = gridLayoutManager.getSpanCount(); int mod = itemCount % spanCount; if (mod == 0 || position < itemCount - 1) { return 1; } else { return spanCount - mod + 1; } } }); } } } setAdapter(mAdapter); } static class ItemsAdapter extends Adapter { private OnRvItemClickListener mItemClickListener; private Context mContext; private List mItems; private ItemsParams mItemsParams; private int mBackgroundColorPress; private LayoutManager mLayoutManager; public ItemsAdapter(Context context, ItemsParams itemsParams, DialogParams dialogParams, LayoutManager layoutManager) { this.mContext = context; this.mItemsParams = itemsParams; this.mLayoutManager = layoutManager; mBackgroundColorPress = itemsParams.backgroundColorPress != 0 ? itemsParams.backgroundColorPress : dialogParams.backgroundColorPress; Object entity = itemsParams.items; if (entity != null && entity instanceof Iterable) { this.mItems = (List) entity; } else if (entity != null && entity.getClass().isArray()) { this.mItems = Arrays.asList((T[]) entity); } else if (entity != null) { throw new IllegalArgumentException("entity must be an Array or an Iterable."); } } @Override public Holder onCreateViewHolder(ViewGroup parent, int viewType) { TextView textView = new TextView(mContext); textView.setGravity(Gravity.CENTER); if (mLayoutManager instanceof LinearLayoutManager) { LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mLayoutManager; if (linearLayoutManager.getOrientation() == LinearLayoutManager.HORIZONTAL) { textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); if (mItemsParams.padding != null) { textView.setPadding(Controller.dp2px(mContext, mItemsParams.padding[0]), Controller.dp2px(mContext, mItemsParams.padding[1]), Controller.dp2px(mContext, mItemsParams.padding[2]), Controller.dp2px(mContext, mItemsParams.padding[3])); } else { textView.setPadding(10, 0, 10, 0); } } else { if (mItemsParams.padding != null) { textView.setPadding(Controller.dp2px(mContext, mItemsParams.padding[0]), Controller.dp2px(mContext, mItemsParams.padding[1]), Controller.dp2px(mContext, mItemsParams.padding[2]), Controller.dp2px(mContext, mItemsParams.padding[3])); } textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); } } else if (mLayoutManager instanceof StaggeredGridLayoutManager || mLayoutManager instanceof GridLayoutManager) { textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); } else { textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } textView.setTextSize(mItemsParams.textSize); textView.setTextColor(mItemsParams.textColor); if (mItemsParams.textGravity != Gravity.NO_GRAVITY) { textView.setGravity(mItemsParams.textGravity); } textView.setHeight(Controller.dp2px(mContext, mItemsParams.itemHeight)); Holder holder = new Holder(textView, mItemClickListener); return holder; } @Override public void onBindViewHolder(Holder holder, int position) { CircleDrawableSelector circleDrawableSelector = new CircleDrawableSelector(Color.TRANSPARENT, mBackgroundColorPress); BackgroundHelper.handleBackground(holder.item, circleDrawableSelector); String label; T item = mItems.get(position); if (item instanceof CircleItemLabel) { label = ((CircleItemLabel) item).getItemLabel(); } else { label = item.toString(); } holder.item.setText(String.valueOf(label)); CircleItemViewBinder viewBinder = mItemsParams.viewBinder; if (viewBinder != null) { viewBinder.onBinder(holder.item, item, position); } } @Override public int getItemCount() { return mItems == null ? 0 : mItems.size(); } public void setOnItemClickListener(OnRvItemClickListener listener) { this.mItemClickListener = listener; } static class Holder extends RecyclerView.ViewHolder implements OnClickListener { OnRvItemClickListener mOnRvItemClickListener; TextView item; public Holder(TextView itemView, OnRvItemClickListener listener) { super(itemView); item = itemView; mOnRvItemClickListener = listener; itemView.setOnClickListener(this); } @Override public void onClick(View v) { if (mOnRvItemClickListener != null) { mOnRvItemClickListener.onItemClick(v, getAdapterPosition()); } } } } static class GridItemDecoration extends RecyclerView.ItemDecoration { private Drawable mDivider; private int mDividerHeight; public GridItemDecoration(Drawable divider, int dividerHeight) { mDivider = divider; mDividerHeight = dividerHeight; } private static boolean isLastColumn(RecyclerView parent, int pos, int spanCount, int childCount) { LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { // 如果是最后一列,则不需要绘制右边 if ((pos + 1) % spanCount == 0) { return true; } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL) { // 如果是最后一列,则不需要绘制右边 if ((pos + 1) % spanCount == 0) { return true; } } else { childCount = childCount - childCount % spanCount; // 如果是最后一列,则不需要绘制右边 if (pos >= childCount) { return true; } } } return false; } private static boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) { LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { childCount = childCount - childCount % spanCount; // 如果是最后一行,则不需要绘制底部 if (pos >= childCount) { return true; } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation(); // StaggeredGridLayoutManager 且纵向滚动 if (orientation == StaggeredGridLayoutManager.VERTICAL) { childCount = childCount - childCount % spanCount; // 如果是最后一行,则不需要绘制底部 if (pos >= childCount) { return true; } } // StaggeredGridLayoutManager 且横向滚动 else { // 如果是最后一行,则不需要绘制底部 if ((pos + 1) % spanCount == 0) { return true; } } } return false; } private static int getSpanCount(RecyclerView parent) { // 列数 int spanCount; LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); } else if (layoutManager instanceof StaggeredGridLayoutManager) { spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount(); } else { spanCount = layoutManager.getItemCount(); } return spanCount; } @Override public void onDraw(Canvas c, RecyclerView parent, State state) { drawHorizontal(c, parent); drawVertical(c, parent); } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { int spanCount = getSpanCount(parent); int childCount = parent.getAdapter().getItemCount(); // 如果是最后一行,则不需要绘制底部 if (isLastRaw(parent, itemPosition, spanCount, childCount)) { outRect.set(0, 0, mDividerHeight, 0); } // 如果是最后一列,则不需要绘制右边 else if (isLastColumn(parent, itemPosition, spanCount, childCount)) { outRect.set(0, 0, 0, mDividerHeight); } else { outRect.set(0, 0, mDividerHeight, mDividerHeight); } } private void drawHorizontal(Canvas c, RecyclerView parent) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getLeft() - params.leftMargin; final int top = child.getBottom() + params.bottomMargin; final int right = child.getRight() + params.rightMargin + mDividerHeight; final int bottom = top + mDividerHeight; mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private void drawVertical(Canvas c, RecyclerView parent) { final int childCount = parent.getChildCount() - 1; for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int top = child.getTop() - params.topMargin; final int right = left + mDividerHeight; final int bottom = child.getBottom() + params.bottomMargin; mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } } static class LinearItemDecoration extends RecyclerView.ItemDecoration { private Drawable mDivider; private int mDividerHeight; private int mOrientation; public LinearItemDecoration(Drawable divider, int dividerHeight, int orientation) { this.mDivider = divider; this.mDividerHeight = dividerHeight; this.mOrientation = orientation; } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mOrientation == LinearLayoutManager.VERTICAL) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == LinearLayoutManager.VERTICAL) outRect.set(0, 0, 0, mDividerHeight); else { //最后一列不画 if (itemPosition != parent.getAdapter().getItemCount() - 1) { outRect.set(0, 0, mDividerHeight, 0); } } } private void drawVertical(Canvas c, RecyclerView parent) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int childCount = parent.getChildCount() - 1; for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); LayoutParams params = (LayoutParams) child.getLayoutParams(); int top = child.getBottom() + params.bottomMargin; int bottom = top + mDividerHeight; mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDividerHeight; mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } } static class LinearLayoutManagerWrapper extends LinearLayoutManager { public LinearLayoutManagerWrapper(Context context, LinearLayoutManager layoutManager) { super(context, layoutManager.getOrientation(), layoutManager.getReverseLayout()); } } static class GridLayoutManagerWrapper extends GridLayoutManager { public GridLayoutManagerWrapper(Context context, GridLayoutManager layoutManager) { super(context, layoutManager.getSpanCount(), layoutManager.getOrientation(), layoutManager.getReverseLayout()); } } static class StaggeredGridLayoutManagerWrapper extends StaggeredGridLayoutManager { public StaggeredGridLayoutManagerWrapper(StaggeredGridLayoutManager layoutManager) { super(layoutManager.getSpanCount(), layoutManager.getOrientation()); } } }