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

阅读全文
0 0
原创粉丝点击