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<T> extends Adapter<ItemsAdapter.Holder> {
|
private OnRvItemClickListener mItemClickListener;
|
private Context mContext;
|
private List<T> 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<T>) 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());
|
}
|
}
|
}
|