Android MaterialDesign控件使用以及RecyclerView,ItemDecoration的基本使用
来源:互联网 发布:算法工程师的基本要求 编辑:程序博客网 时间:2024/05/02 02:33
在谷歌给我们提供的appcompat包中有很多为兼容而生的控件,这样就可以做到高低版本和不同的ROM之间体验一致!还可以配合appcompat的主题使用达到体验一致性。
appcompat控件以及样式
- 文本 AppCompatTextView
- 按钮 AppCompatButton
- 提示框 android.support.v7.app.AlertDialog`
- 文本输入框 AppCompatEditText
- 下拉刷新 SwipeRefreshLayout
- 进度条样式 style=”@style/Widget.AppCompat.ProgressBar.Horizontal”
- 列表Popup框 ListPopupWindow
- 菜单Popup框 PopupMenu
- 列表间隔线 LinearLayoutCompat
- RecyclerView android.support.v7.widget.RecyclerView
接下来让我们来看一下这些控件的一些基本使用方法。
AppCompatTextView
<android.support.v7.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:text="Hello World" />
AppCompatButton
<android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:onClick="showDialog" android:text="对话框" />
ProgressBarStyle
<ProgressBar style="@style/Widget.AppCompat.ProgressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginBottom="5dp" android:layout_marginTop="16dp" />
AppCompatEditText
<android.support.v7.widget.AppCompatEditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:text="呵呵" />
显示效果如图:
可以看到整个界面都是MD的一个风格
android.support.v7.app.AlertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("XY的提示框");builder.setMessage("给XY一个女朋友");builder.setPositiveButton("好的", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { }});builder.setNegativeButton("不行", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { }});builder.show();
ListPopupwindow
public void showListPopupwindow(View view){ String[] datas = {"条目0","条目1","条目2","条目3","条目4"}; ListAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,datas); ListPopupWindow listPopupWindow = new ListPopupWindow(this); listPopupWindow.setAdapter(adapter); listPopupWindow.setAnchorView(view); listPopupWindow.show(); }
PopupMenu
public void showPopupmenuwindow(View view){ PopupMenu popupMenu = new PopupMenu(this,view); popupMenu.getMenuInflater().inflate(R.menu.main,popupMenu.getMenu()); popupMenu.show();}
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <item android:id="@+id/action_settings" android:orderInCategory="100" android:icon="@android:drawable/ic_menu_set_as" android:title="设置"/> <item android:id="@+id/action_share" android:orderInCategory="101" android:icon="@android:drawable/ic_menu_share" android:title="分享"/> <item android:id="@+id/action_new" android:orderInCategory="102" android:icon="@android:drawable/ic_menu_add" android:title="添加"/></menu>
LinearLayoutCompat
<android.support.v7.widget.LinearLayoutCompat android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" app:divider="@drawable/abc_list_divider_mtrl_alpha" app:showDividers="beginning|middle"> <android.support.v7.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:text="Hello World" /> <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:onClick="showDialog" android:text="对话框" /> <ProgressBar style="@style/Widget.AppCompat.ProgressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginBottom="5dp" android:layout_marginTop="16dp" /> <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:onClick="showListPopupwindow" android:text="显示ListPopupwindow" /> <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:onClick="showPopupmenuwindow" android:text="显示showPopupmenuwindow" /> <android.support.v7.widget.AppCompatEditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="5dp" android:text="呵呵" /> <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:onClick="toRecyclerView" android:layout_marginBottom="5dp" android:text="RecyclerView" /> <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:onClick="toHeaderRecyclerView" android:layout_marginBottom="5dp" android:text="带headerView以及footerView的RecyclerView" /> </android.support.v7.widget.LinearLayoutCompat>
可以看到每一个childView之间都有一根间隔线
app:showDividers=”beginning|middle”的意思就是第一个子view上有间隔线以及每一个子view之间也有间隔线
下面要说到最重要的一个控件RecyclerView了,可以说是ListView和GridView的增强升级版,但是RecyclerView比这两个哥们要牛逼的多,话不多说,直接上代码
public class RecyclerViewActivity extends AppCompatActivity{ private Handler handler = new Handler(); private RecyclerView rv; private List<String> items; private XYAdapter xyAdapter; private RecyclerView.ItemDecoration dividerItemDecoration; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recyclerview); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); items = new ArrayList<>(); for (int i = 0; i < 90; i++) { items.add("条目" + i); } rv = (RecyclerView) findViewById(R.id.recyclerview); xyAdapter = new XYAdapter(items); xyAdapter.setOnItemClickListener(new XYBaseAdapter.OnItemClickListener() { @Override public void OnItemClick(View v, int position) { Toast.makeText(RecyclerViewActivity.this, "点击" + position, Toast.LENGTH_SHORT).show(); } }); rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); rv.setAdapter(xyAdapter); rv.setItemAnimator(new DefaultItemAnimator()); /** * 添加条目间隔线 */ dividerItemDecoration = new DividerItemDecoration(this,LinearLayoutManager.VERTICAL); rv.addItemDecoration(dividerItemDecoration); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new XYItemTouchHelperCallBack(xyAdapter)); itemTouchHelper.attachToRecyclerView(rv); } /** * 添加一个item * @param view */ public void addItem(View view){ xyAdapter.addData("add item",3); } /** * 删除一个item * @param view */ public void removeItem(View view){ xyAdapter.removeData(3); }}
重点在这两行代码:
rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));rv.setAdapter(xyAdapter);
recyclerView设置LayoutManager来管理布局,设置Adapter来绑定数据,来看一下Adapter如何实现
import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.HashMap;import java.util.List;import java.util.Map;public abstract class XYBaseAdapter<T> extends RecyclerView.Adapter<XYBaseAdapter<T>.XYViewHolder> { protected List<T> mItems; private OnItemClickListener mOnItemClickListener; public XYBaseAdapter(List<T> items) { mItems = items; } public void setOnItemClickListener(OnItemClickListener listener) { mOnItemClickListener = listener; } @Override public XYViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View root = LayoutInflater.from(parent.getContext()).inflate(getContentLayoutId(), parent, false); XYViewHolder viewHolder = new XYViewHolder(root); return viewHolder; } @Override public void onBindViewHolder(XYViewHolder holder, int position) { ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); lp.height = 100; holder.itemView.setOnClickListener(new XYOnItemClickListener(holder.getLayoutPosition())); bindData(holder, position); } protected abstract int getContentLayoutId(); protected abstract void bindData(XYViewHolder holder, int position); @Override public int getItemCount() { return mItems.size(); } /** * 刷新数据 * @param datas */ public void refresh(List<T> datas){ this.mItems.clear(); this.mItems.addAll(datas); notifyDataSetChanged(); } /** * 添加数据 * @param datas */ public void addData(List<T> datas){ this.mItems.addAll(datas); notifyDataSetChanged(); } public void addData(T t,int position){ this.mItems.add(position,t); notifyItemInserted(position); } public void removeData(int position){ this.mItems.remove(position); notifyItemRemoved(position); } public void removeData(){ this.mItems.clear(); notifyDataSetChanged(); } class XYViewHolder extends RecyclerView.ViewHolder { private Map<Integer, View> mCache = new HashMap<>(); public XYViewHolder(View itemView) { super(itemView); } public View findView(int res) { if (mCache.get(res) == null) { mCache.put(res, itemView.findViewById(res)); } return mCache.get(res); } } public interface OnItemClickListener { void OnItemClick(View v, int position); } public class XYOnItemClickListener implements View.OnClickListener { int mPosition; public XYOnItemClickListener(int position) { mPosition = position; } @Override public void onClick(View v) { if (mOnItemClickListener != null) mOnItemClickListener.OnItemClick(v, mPosition); } }}
方法onCreateViewHolder中创建返回ViewHolder,在onBindViewHolder方法中绑定相关数据,此处抽象优化出来让子类继承实现bindData方法,getContentLayoutId方法实现类返回item的局部id,看一下XYBaseAdapter的实现类
public class XYAdapter extends XYBaseAdapter<String> implements XYMoveListener { public XYAdapter(List<String> items) { super(items); } @Override protected int getContentLayoutId() { return R.layout.recyclerview_item; } @Override protected void bindData(XYViewHolder holder, int position) { TextView tv = (TextView) holder.findView(R.id.content); tv.setText(mItems.get(position) + ""); }}
看一下效果
图中每一个item之间都有一条间隔线,这个要怎么做到呢?我们需要用到ItemDecoration类了,代码撸起来
public class DividerItemDecoration extends RecyclerView.ItemDecoration { private int[] attrs = new int[]{android.R.attr.listDivider}; private Drawable dividerDrawable; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { TypedArray ta = context.obtainStyledAttributes(attrs); dividerDrawable = ta.getDrawable(0); ta.recycle(); setOrientation(orientation); } private void setOrientation(int orientation) { if (orientation != LinearLayoutManager.HORIZONTAL && orientation != LinearLayoutManager.VERTICAL) { throw new IllegalArgumentException("布局参数错误"); } this.mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mOrientation == LinearLayoutManager.HORIZONTAL) { drawVerticalDivider(c, parent); } else if (mOrientation == LinearLayoutManager.VERTICAL) { drawHorizontalDivider(c, parent); } } private void drawVerticalDivider(Canvas c, RecyclerView parent) { int top = parent.getPaddingTop(); for (int i = 0; i < parent.getChildCount(); i++) { View childView = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) childView.getLayoutParams(); int bottom = childView.getBottom() + params.bottomMargin; int left = childView.getRight() + params.rightMargin; int right = left + dividerDrawable.getIntrinsicWidth(); dividerDrawable.setBounds(left, top, right, bottom); dividerDrawable.draw(c); } } private void drawHorizontalDivider(Canvas c, RecyclerView parent) { int left = parent.getLeft() + parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); for (int i = 0; i < parent.getChildCount(); i++) { View childView = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) childView.getLayoutParams(); int top = childView.getBottom() + params.topMargin + Math.round(ViewCompat.getTranslationY(childView)); int bottom = top + dividerDrawable.getIntrinsicHeight(); dividerDrawable.setBounds(left, top, right, bottom); dividerDrawable.draw(c); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == LinearLayoutManager.HORIZONTAL) { outRect.set(0, 0, dividerDrawable.getIntrinsicWidth(), 0); } else if (mOrientation == LinearLayoutManager.VERTICAL) { outRect.set(0, 0, 0, dividerDrawable.getIntrinsicHeight()); } }}
首先我们来看getItemOffsets方法,这个方法的意思就是需要我们返回一个Rect的偏移区域来展现divider,outRect.set(left,top,right,bottom);设置左上右下的偏移区域;
再来看onDraw方法,这个方法就是具体实现divider分隔线的地方了,循环遍历所有子view,通过计算left,top,right,bottom来确定每一条分隔线的位置。
如果我们需要添加条目,需要在数据集合中添加一条数据,并且调用方法notifyItemInserted(position);
如果我们需要删除一个条目,需要在数据集合中删除一条数据,并且调用方法notifyItemRemoved(position);
添加删除条目时如需要一些动画效果可以在recyclerview中添加Animator,这里我们添加一个默认的Animator,rv.setItemAnimator(new DefaultItemAnimator());
下面我们再来看一下布局变换如何实现
public boolean onOptionsItemSelected(MenuItem item) { rv.removeItemDecoration(dividerItemDecoration); switch (item.getItemId()) { case R.id.action_LinearLayoutManager_HORIZATOAL: xyAdapter.setStaggerLayout(false); dividerItemDecoration = new DividerItemDecoration(this,LinearLayoutManager.HORIZONTAL); rv.addItemDecoration(dividerItemDecoration); rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); break; case R.id.action_LinearLayoutManager_VERTICAL: xyAdapter.setStaggerLayout(false); dividerItemDecoration = new DividerItemDecoration(this,LinearLayoutManager.VERTICAL); rv.addItemDecoration(dividerItemDecoration); rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); break; case R.id.action_GridLayoutManager: xyAdapter.setStaggerLayout(false); dividerItemDecoration = new GridItemDecoration(this); rv.addItemDecoration(dividerItemDecoration); rv.setLayoutManager(new GridLayoutManager(this, 3)); break; case R.id.action_StaagerLayoutManager: xyAdapter.setStaggerLayout(true); rv.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)); break; } return super.onOptionsItemSelected(item); }
效果图:
最后奉上源码地址:
XYMaterialDesign
- Android MaterialDesign控件使用以及RecyclerView,ItemDecoration的基本使用
- RecyclerView.ItemDecoration的使用
- RecyclerView.ItemDecoration 使用总结
- RecyclerView,ItemDecoration进阶使用!!!
- Android控件之RecyclerView的基本使用
- Android 控件 RecyclerView 的基本使用
- Android MaterialDesign库的使用
- Android MaterialDesign概述样式以及使用
- Android-使用RecyclerView的ItemDecoration 实现炫酷的 吸顶效果
- Android RecyclerView的基本使用
- Android RecyclerView 的基本使用
- Android RecyclerView 的基本使用
- 使用ItemDecoration自定义RecyclerView的分割线实现头布局
- 使用RecyclerView的ItemDecoration实现StickyHeader效果(笔记)
- FloatingActionButtonPlus,一款使用简单的MaterialDesign控件。
- materialdesign下拉刷新控件MaterialRefreshLayout的使用
- 使用ItemDecoration为RecyclerView添加header
- 使用ItemDecoration给RecyclerView 添加水印
- 用大白菜重装电脑系统
- 对php-fpm的理解重述
- 造成DELPHI程序的稳定性原因及解决方法
- Oracle之只有数据文件恢复数据库
- 游戏编程入门(15):开发 MeteorDefense(抵御流星)游戏
- Android MaterialDesign控件使用以及RecyclerView,ItemDecoration的基本使用
- iOS工作小结
- 第三章 C++与数据抽象
- Bootstrap3 导航条之个人学习笔记
- 人工智能全面战胜人类?下一步是取代人类?
- 获取通讯录
- oracle 如何恢复数据删除并且提交(Submit)了的数据表
- 接收到推送消息处理方法
- 生成树和最小生成树