安卓BottomSheet实现——类定义
item类的定义
上一节我们定义了样式,现在我们开始进行类编写。首先我们知道整个BottomSheet是由一个个item组成的,而我们也是使用了recyclerview来显示出所有的item,所以我们先创建一个 BottomSheetItem.java
interface BottomSheetItem {
String getTitle();
}这里定义了一个接口,因为item的种类有很多,除了可点击传统的item以外,我们还有分隔符与标题,所以这个接口来使他们都统一的行为。只有一个函数用来返回item的title。
然后我们来实现传统的可点击的item,创建一个 BottomSheetMenuitem.java
class BottomSheetMenuItem implements BottomSheetItem {
@ColorInt
private int mTextColor;
@ColorInt
private int mTintColor;
private Drawable mIcon;
private String mTitle;
private int mId;
private MenuItem mMenuItem;
@DrawableRes
private int mBackground;
public BottomSheetMenuItem(MenuItem item,@ColorInt int textColor, @DrawableRes int background,
@ColorInt int tintColor) {
mMenuItem = item;
mIcon = item.getIcon();
mId = item.getItemId();
mTitle = item.getTitle().toString();
mTextColor = textColor;
mBackground = background;
mTintColor = tintColor;
if (mTintColor != -1) {
mIcon = DrawableCompat.wrap(mIcon);
DrawableCompat.setTint(mIcon, mTintColor);
}
}
public Drawable getIcon() {
return mIcon;
}
public MenuItem getMenuItem() {
return mMenuItem;
}
@DrawableRes
public int getBackground() {
return mBackground;
}
public int getId() {
return mId;
}
@ColorInt
public int getTextColor() {
return mTextColor;
}
@Override
public String getTitle() {
return mTitle;
}
}很简单,一个图标,一个标题,一个id,和一个目录项,还有三个可能看起来比较奇怪的东西,但是看名字也明白是用来定义样式的,字体颜色,背景等等。对于整个BottomSheet,我们的处理是定义menu文件,然后在menu里读取一个个MenuItem,处理后作为我们的item。由于是在menu文件中编写,所以我们也只需要get函数,而不需要set函数了。
标题类型的item与分隔符的item非常简单,这里就不再说明。
BottomSheetHeader.java
class BottomSheetHeader implements BottomSheetItem {
private String mTitle;
@ColorInt
private int mTextColor;
public BottomSheetHeader(String title, @ColorInt int color) {
mTitle = title;
mTextColor = color;
}
@ColorInt
public int getTextColor() {
return mTextColor;
}
@Override
public String getTitle() {
return mTitle;
}
}BottomSheetDivider.java
class BottomSheetDivider implements BottomSheetItem {
@DrawableRes
private int mBackgroundDrawable;
public BottomSheetDivider(@DrawableRes int background) {
mBackgroundDrawable = background;
}
@DrawableRes
public int getBackground() {
return mBackgroundDrawable;
}
@Override
public String getTitle() {
return "";
}
}这样的话,我们就定义完了所有类型的item类。
item点击事件
对于传统的可点击的item,我们定义一个接口来处理它的点击操作。
BottomSheetItemClickListener.java
public interface BottomSheetItemClickListener {
void onBottomSheetItemClick(MenuItem item);
}这样的处理大家应该也非常熟悉。定义完了item接下来的动作就是在recyclerview里面建立item了,所以我们还需要编写一个适配器。
RecyclerView中的适配器
对于recyclerview中的适配器编写大家肯定已经非常熟悉了,这里需要注意的点无非是item类型的判断以及还需要知道BottomSheet是什么类型的。
BottomSheetItemAdapter.java
class BottomSheetItemAdapter extends RecyclerView.Adapter<BottomSheetItemAdapter.ViewHolder> {
public static final int TYPE_ITEM = 0;
public static final int TYPE_HEADER = 1;
public static final int TYPE_DIVIDER = 2;
private List<BottomSheetItem> mItems;
BottomSheetItemClickListener mListener;
private int mMode;
private int mItemWidth;
public BottomSheetItemAdapter(List<BottomSheetItem> items, int mode,
BottomSheetItemClickListener listener) {
mMode = mode;
mItems = items;
mListener = listener;
}
public void setItemWidth(int width) {
mItemWidth = width;
}
public void setListener(BottomSheetItemClickListener listener) {
mListener = listener;
}
@Override
public int getItemViewType(int position) {
BottomSheetItem item = mItems.get(position);
if (item instanceof BottomSheetMenuItem) {
return TYPE_ITEM;
} else if (item instanceof BottomSheetDivider) {
return TYPE_DIVIDER;
} else if (item instanceof BottomSheetHeader) {
return TYPE_HEADER;
}
return super.getItemViewType(position);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mMode == BottomSheetBuilder.MODE_GRID) {
View layout = LayoutInflater.from(parent.getContext())
.inflate(R.layout.bottomsheetbuilder_grid_adapter, parent, false);
ViewGroup.LayoutParams layoutParams = layout.getLayoutParams();
layoutParams.width = mItemWidth;
layout.setLayoutParams(layoutParams);
return new ItemViewHolder(layout);
}
if (mMode == BottomSheetBuilder.MODE_LIST) {
if (viewType == TYPE_HEADER) {
return new HeaderViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.bottomsheetbuilder_list_header, parent, false));
}
if (viewType == TYPE_ITEM) {
return new ItemViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.bottomsheetbuilder_list_adapter, parent, false));
}
if (viewType == TYPE_DIVIDER) {
return new DividerViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.bottomsheetbuilder_list_divider, parent, false));
}
}
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.bottomsheetbuilder_list_adapter, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
BottomSheetItem item = mItems.get(position);
if (mMode == BottomSheetBuilder.MODE_LIST) {
if (holder.getItemViewType() == TYPE_ITEM) {
((ItemViewHolder) holder).setData((BottomSheetMenuItem) item);
} else if (holder.getItemViewType() == TYPE_HEADER) {
((HeaderViewHolder) holder).setData((BottomSheetHeader) item);
} else if (holder.getItemViewType() == TYPE_DIVIDER) {
((DividerViewHolder) holder).setData((BottomSheetDivider) item);
}
} else {
((ItemViewHolder) holder).setData((BottomSheetMenuItem) item);
}
}
@Override
public int getItemCount() {
return mItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
public class DividerViewHolder extends ViewHolder {
public View divider;
public DividerViewHolder(View itemView) {
super(itemView);
divider = itemView;
}
public void setData(BottomSheetDivider item) {
int background = item.getBackground();
if (background != 0) {
divider.setBackgroundResource(background);
}
}
}
public class HeaderViewHolder extends ViewHolder {
public TextView textView;
public HeaderViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(.textView);
}
public void setData(BottomSheetHeader item) {
textView.setText(item.getTitle());
int color = item.getTextColor();
if (color != 0) {
textView.setTextColor(color);
}
}
}
public class ItemViewHolder extends ViewHolder implements View.OnClickListener {
public AppCompatImageView imageView;
public TextView textView;
public ItemViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
imageView = (AppCompatImageView) itemView.findViewById(.imageView);
textView = (TextView) itemView.findViewById(.textView);
}
public void setData(BottomSheetMenuItem item) {
imageView.setImageDrawable(item.getIcon());
textView.setText(item.getTitle());
int color = item.getTextColor();
int background = item.getBackground();
if (color != 0) {
textView.setTextColor(color);
}
if (background != 0) {
itemView.setBackgroundResource(background);
}
}
@Override
public void onClick(View v) {
BottomSheetMenuItem item = (BottomSheetMenuItem) mItems.get(getLayoutPosition());
if (mListener != null) {
mListener.onBottomSheetItemClick(item.getMenuItem());
}
}
}
}可以看到,首先我们定义三个常量来代表三种类型的item,并使用了一个mMode变量来得知BottomSheet的类型。对于item类型的判断,我们重载了 getItemViewType() 函数,来对于item 进行类型判断。并为不同的item类型构建了不同类型的ViewHolder,内部都定义了一个 setData() 函数来对于类进行赋值。对于传统的item我们还实现了 View.OnClickListener 来监听点击事件。
而在 onCreateViewHolder() 我们首先对BottomSheet的类型进行判断,这一步的主要原因是,在grid类型的BottomSheet中我们是没有标题与分隔符类型的item,所以可以少很多判断,并要加载相应的布局样式文件。在 onBindViewHolder() 的判断越是同理。
这样的话,我们就编写完了适配器。
前期的准备工作基本完成了,下面就可以开始来构建视图了。
















