笔记:MaterialDesign(二)--控/组件简单使用

2018-05-10  本文已影响52人  RoJacKing

MaterialDesign学习笔记,学习共勉
MaterialDesign笔记(一)--控/组件简单使用
MaterialDesign笔记(二)--控/组件简单使用

一、ItemTouchHelper的简单使用

1、MainActivity.java

public class MainActivity extends AppCompatActivity implements ItemDragListener {

    private List<String> mData = new ArrayList<>();
    private RecyclerView mRv;
    private ItemTouchHelperAdapter mAdapter;//adapter
    private MyItemTouchHelperCallback mCallback;//自定义触摸回调
    private ItemTouchHelper mItemTouchHelper;//系统的

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRv = (RecyclerView) findViewById(R.id.rv);

        initData();
//        initDecoration();//初始化修饰布局(首字母提示)
        initRecyclerView();

    }

    //初始化修饰布局(首字母提示),效果不友好所以注释了,没有加pinyin4j包就不要打开注释
    //如果要打开就加这段依赖compile 'com.github.open-android:pinyin4j:2.5.0'
//    private void initDecoration() {
//        MyDecorationThree decorationThree = new MyDecorationThree(this, mData);
//        mRv.addItemDecoration(decorationThree);
//    }

    //初始化数据
    private void initData() {

        for (int i = 0; i < Cheeses.NAMES.length; i++) {
            mData.add(Cheeses.NAMES[i]);
        }
    }

    //初始化recyclerview,关联adapter
    private void initRecyclerView() {
        //普通的   recyclerview与adapter关联

        //因为mainactivity实现了ItemDragListener接口,所以可以传this,代表ItemDragListener
        mAdapter = new ItemTouchHelperAdapter(mData,this);
        mRv.setLayoutManager(new LinearLayoutManager(this));
        mRv.setAdapter(mAdapter);

        //给recyclerview.adapter设置触摸回调ItemTouchHelper.Callback
        // (这个是我们自定义的MyItemTouchHelperCallback)
        mCallback = new MyItemTouchHelperCallback(mAdapter);
        mItemTouchHelper = new ItemTouchHelper(mCallback);
        mItemTouchHelper.attachToRecyclerView(mRv);//绑定触摸回调

    }

    /**
     * imageview的触摸回调
     *
     * 示例:ItemTouchHelper.startDrag()   只是示例,不要可去除这个方法
     * 功能:  按下imageview就可以实现拖拽功能
     * 说明:实现这个回调方法----执行ItemTouchHelper.startDrag()---就会
     *            执行ItemTouchHelper.Callback----就会执行我们自定义的MyItemTouchHelperCallback)
     *
     * @param viewHolder
     */
    @Override
    public void onStartDrags(RecyclerView.ViewHolder viewHolder) {
        mItemTouchHelper.startDrag(viewHolder);//系统方法ItemTouchHelper.startDrag()
    }
}

2、activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


</LinearLayout>

3、Adapter--ItemTouchHelperAdapter.java

/**
 * Created by ${chenyuexueer} 
 *
 * 说明:普通的 RecyclerView.Adapter  只是在里面添加了几个触摸回调的方法
 */

public class ItemTouchHelperAdapter extends  RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder> implements ItemMoveListener {

    private List<String> mData;//数据

    private ItemDragListener mItemDragListener;//imageview的触摸回调

    //构造方法,初始化数据等
    public ItemTouchHelperAdapter(List<String> mData, ItemDragListener mItemDragListener) {
        this.mData = mData;
        this.mItemDragListener = mItemDragListener;
    }

    //recyclerview adapter 的方法 得到item布局对象
    @Override
    public ItemTouchHelperViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        // LayoutInflater.from()像充气球一样充入一个view
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_touch_helper, parent, false);
        return new ItemTouchHelperViewHolder(itemView);
    }

    //recyclerview adapter 的方法 绑定数据
    @Override
    public void onBindViewHolder(final ItemTouchHelperViewHolder holder, int position) {

        holder.mTvStr.setText(mData.get(position));//TextView 绑定数据

        /**
         *  imagview添加触摸监听,点下这个imageview执行回调,这个回调是执行
         *  ItemTouchHelper.startDrag(viewHolder);系统的代码     从而我们自定义的
         *  ItemTouchHelper.CallBack()代码,实现可拖拽效果
         */
        holder.mIvDrag.setOnTouchListener(new View.OnTouchListener() {
            /**
             *
             * @param view  view添加触摸监听的view对象
             *
             * @param motionEvent  触摸事件
             *
             * MotionEvent.ACTION_DOWN 表示用户的手指刚接触到屏幕
             * MotionEvent.ACTION_MOVE 表示用户的手指正在移动
             * MotionEvent.ACTION_UP 表示用户的手指从屏幕上抬起
             * Cancel   事件取消
             *
             * @return  返回值true/false
             *
             * 返回值为false的时候,只会执行down方法,不会执行move和up.
             * 只有在true的时候,三个都会执行,可打开注释
             * 注释这个mItemDragListener.onStartDrags(viewHolder);
             * 看一下效果,不过可能看不太清(左右移动(上下移动被接手了)
             * 最好自己写一个
             *
             */

            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                /**
                 * 执行触摸回调,这个回调方法在activity那边实现了
                 * (在这里实现也行,不过要改代码,这里就不示例了)
                 */
                mItemDragListener.onStartDrags(holder);
//                switch (motionEvent.getAction()) {
//                    case MotionEvent.ACTION_DOWN:
//                        Log.e("TAG==","ACTION_DOWN");
//                        break;
//                    case MotionEvent.ACTION_MOVE:
//                        Log.e("TAG==","ACTION_MOVE");
//                        break;
//                    case MotionEvent.ACTION_UP:
//                        Log.e("TAG==","ACTION_UP");
//                        break;
//                }

                return false;
            }
        });

    }

    //实现ItemMoveListener接口的回调方法
    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        //系统提供的方法   交换数据
        Collections.swap(mData, fromPosition, toPosition);
        //RecyclerView.Adapter刷新
        notifyItemMoved(fromPosition, toPosition);
        return true;
    }

    //实现ItemMoveListener接口的回调方法
    @Override
    public boolean onItemRemove(int position) {
        //删除数据
        mData.remove(position);
        //RecyclerView.Adapter提供的  移除方法  并  刷新
        notifyItemRemoved(position);
        return true;
    }

    //recyclerview adapter 的方法 返回item条数
    @Override
    public int getItemCount() {
        return mData.size()>0?mData.size():0;
    }

    //普通的    RecyclerView.ViewHolder
    class ItemTouchHelperViewHolder extends RecyclerView.ViewHolder {

        TextView mTvStr;
        ImageView mIvDrag;

        public ItemTouchHelperViewHolder(View itemView) {
            super(itemView);
            mTvStr = (TextView) itemView.findViewById(R.id.tvStr);
            mIvDrag = (ImageView) itemView.findViewById(R.id.ivDrag);
        }
    }
}

4、自定义ItemTouchHelper.Callback------MyItemTouchHelperCallback.java


/**
 * Created by ${chenyuexueer} 
 *
 * 说明:自定义触摸回调
 *
 * 1、继承 ItemTouchHelper.Callback实现重写getMovementFlags、onMove、onSwiped这三个方法
 * 2、初始化ItemMoveListener(由于ItemTouchHelperAdapter实现了这
 *      个接口并实例化了方法,所以可以直接赋值,具体请自行百度)-----看  关注①
 * 3、开启item长按拖拽功能
 *      到了这一步已经可以实现了我们想要的,后面是实现一些动画效果等
 * 4、拖拽时添加动画和视觉效果onSelectedChanged,clearView,onChildDraw
 *       onSelectedChanged,clearView这两个方法要一起用,否则...(你可以试着注释clearView看看)
 *
 */

public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {

    ItemMoveListener mItemMoveListener;

    //2、初始化ItemMoveListener
    public MyItemTouchHelperCallback(ItemTouchHelperAdapter mAdapter) {//构造方法,初始化数据等
        mItemMoveListener = mAdapter;//初始化ItemMoveListener---------关注①
    }

    /**
     * 1.1、重写getMovementFlags
     *
     * 获取动作标识
     * 动作标识分:dragFlags和swipeFlags
     * dragFlags:列表滚动方向的动作标识(如竖直列表就是上和下,水平列表就是左和右)
     * wipeFlags:与列表滚动方向垂直的动作标识(如竖直列表就是左和右,水平列表就是上和下)
     */
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        int flags = makeMovementFlags(dragFlags, swipeFlags);//系统方法,返回动作标记
        return flags;
    }

    /**
     *
     * 1.2、onMove
     *
     * 当item拖拽移动时触发----执行回调
     *
     * @param recyclerView
     * @param viewHolder       当前被拖拽的item的viewHolder
     * @param target 当前被拖拽的item下方的另一个item的viewHolder,
     *                           这个值会跟着你拖拽的位置变化而变化,简单的说就是
     *                           替换到了目的viewHolder位置(不知道这么说准不准确,反正就是这个意思)
     * @return
     */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        Log.e("TAG","当前拖拽的viewholder=="+viewHolder+"拖到了这个位置的target=="+target);
        return mItemMoveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    }

    /**
     * 1.3、onSwiped
     *
     * 当item侧滑出去时触发(竖直列表是侧滑,水平列表是竖滑)
     *
     * @param viewHolder
     * @param direction  滑动的方向
     * 可以打开注释看一下效果,不过这里只能看到向左右的情况,
     *                   要看上下的自己写代码实现哈!!
     */
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        //1--UP     2--DOWN     4--LEFT     8--RIGHT
//        Log.e("TAG","滑动的方向数字值=="+direction);
//        switch (direction){
//            case 1:
//                Log.e("TAG","滑动的方向=="+direction+"--UP向上");
//                break;
//            case 2:
//                Log.e("TAG","滑动的方向=="+direction+"--DOWN向下");
//                break;
//            case 4:
//                Log.e("TAG","滑动的方向=="+direction+"--LEFT向左");
//                break;
//            case 8:
//                Log.e("TAG","滑动的方向=="+direction+"--RIGHT向右");
//                break;
//        }

        mItemMoveListener.onItemRemove(viewHolder.getAdapterPosition());
    }

    /**
     * 是否开启item长按拖拽功能
     */
    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

//=====================下面是实现动画视觉效果等=============
    /**
     * 当item被拖拽或侧滑时触发,背景颜色变灰
     *
     * @param viewHolder
     * @param actionState 当前item的状态
     */
    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        super.onSelectedChanged(viewHolder, actionState);
        //不管是拖拽或是侧滑,背景色都要变化
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)
            viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.darker_gray));
    }

    /**
     * 当item的交互动画结束时触发,背景颜色变回白色
     *
     * @param recyclerView
     * @param viewHolder
     */
    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.white));

        viewHolder.itemView.setAlpha(1);
        viewHolder.itemView.setScaleY(1);
    }

    /**
     * 侧滑时触发,视觉效果----item像是被压扁的视觉效果
     *
     * @param c
     * @param recyclerView
     * @param viewHolder
     * @param dX
     * @param dY
     * @param actionState
     * @param isCurrentlyActive
     */
    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            float value = 1 - Math.abs(dX) / viewHolder.itemView.getWidth();
            viewHolder.itemView.setAlpha(value);
            viewHolder.itemView.setScaleY(value);
        }
    }
}

5.1、ItemMoveListener自定义接口

/**
 * Created by ${chenyuexueer}
 *
 * 说明:整个item条目的触摸监听回调
 */

public interface ItemMoveListener {

    //整个item条目的触摸移动事件回调,主要是用于 交换数据 、 刷新数据
    boolean onItemMove(int fromPosition, int toPosition);

    //整个item条目的触摸删除事件回调,主要是用于  刷新数据
    boolean onItemRemove(int position);
}

5.2、ItemDragListener自定义接口

/**
 * Created by ${chenyuexueer}
 *
 * 说明:imageview的触摸回调,按下imageview,实现拖拽功能
 *            接口回调,只是示例,可以不要这个功能
 */

public interface ItemDragListener {
    //按下回调
    void onStartDrags(RecyclerView.ViewHolder viewHolder);
}

6、数据Cheeses.java----NAMES[]


/**
 * Created by ${chenyuexueer} on 2018/5/9.
 * 说明:姓名数据
 */

public class Cheeses {

    public static final String[] NAMES = new String[] { "宋江", "卢俊义", "吴用",
            "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
            "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
            "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
            " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
            "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
            "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
            "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
            "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
            "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
            "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
            "时迁", "段景柱" };

}
示例1.gif

额外示例 可以结合Decoration实现各种效果,其一比如下图

(效果不太友好,算是bug吗,有待优化,这里只是示例)

示例2.gif

实现上图效果,代码如下:

①、把上面的MainActivity.java中的 注释 初始化修饰布局(首字母提示)方法打开注释,算了,我还是把代码全部贴上吧
②、结合RecyclerView.ItemDecoration

1.1、MainActivity.java

public class MainActivity extends AppCompatActivity implements ItemDragListener {

    private List<String> mData = new ArrayList<>();
    private RecyclerView mRv;
    private ItemTouchHelperAdapter mAdapter;//adapter
    private MyItemTouchHelperCallback mCallback;//自定义触摸回调
    private ItemTouchHelper mItemTouchHelper;//系统的

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRv = (RecyclerView) findViewById(R.id.rv);

        initData();
        initDecoration();//初始化修饰布局(首字母提示)
        initRecyclerView();

    }

    //初始化修饰布局(首字母提示),效果不友好所以注释了,没有加pinyin4j包就不要打开注释
    //如果要打开就加这段依赖compile 'com.github.open-android:pinyin4j:2.5.0'
    private void initDecoration() {
        MyDecorationThree decorationThree = new MyDecorationThree(this, mData);
        mRv.addItemDecoration(decorationThree);
    }

    //初始化数据
    private void initData() {

        for (int i = 0; i < Cheeses.NAMES.length; i++) {
            mData.add(Cheeses.NAMES[i]);
        }
    }

    //初始化recyclerview,关联adapter
    private void initRecyclerView() {
        //普通的   recyclerview与adapter关联

        //因为mainactivity实现了ItemDragListener接口,所以可以传this,代表ItemDragListener
        mAdapter = new ItemTouchHelperAdapter(mData,this);
        mRv.setLayoutManager(new LinearLayoutManager(this));
        mRv.setAdapter(mAdapter);

        //给recyclerview.adapter设置触摸回调ItemTouchHelper.Callback
        // (这个是我们自定义的MyItemTouchHelperCallback)
        mCallback = new MyItemTouchHelperCallback(mAdapter);
        mItemTouchHelper = new ItemTouchHelper(mCallback);
        mItemTouchHelper.attachToRecyclerView(mRv);//绑定触摸回调

    }

    /**
     * imageview的触摸回调
     *
     * 示例:ItemTouchHelper.startDrag()   只是示例,不要可去除这个方法
     * 功能:  按下imageview就可以实现拖拽功能
     * 说明:实现这个回调方法----执行ItemTouchHelper.startDrag()---就会
     *            执行ItemTouchHelper.Callback----就会执行我们自定义的MyItemTouchHelperCallback)
     *
     * @param viewHolder
     */
    @Override
    public void onStartDrags(RecyclerView.ViewHolder viewHolder) {
        mItemTouchHelper.startDrag(viewHolder);//系统方法ItemTouchHelper.startDrag()
    }
}
1.2、MyDecorationThree.java
public class MyDecorationThree extends RecyclerView.ItemDecoration {

    Context mContext;
    List<String> mData;
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//画笔

    public MyDecorationThree(Context context, List<String> data) {
        mContext = context;
        mData = data;
        //画笔字体大小与颜色
        paint.setTextSize(sp2px(16));
        paint.setColor(Color.RED);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        drawLetterToItemLeft(c, parent);
    }

    /**
     * 绘制方法
     * @param c     画布
     * @param parent    RecyclerView
     */
    private void drawLetterToItemLeft(Canvas c, RecyclerView parent) {

        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (!(layoutManager instanceof LinearLayoutManager)){
            return;
        }

        int childCount = parent.getChildCount();

        for (int i = 0; i < childCount; i++) {
            int position = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition() + i;
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            float left = 0;
            float top = child.getTop() - params.topMargin;
            float right = child.getLeft() - params.leftMargin;
            float bottom = child.getBottom() + params.bottomMargin;
            float width = right - left;
            float height = bottom - (bottom - top) / 2;
            //当前名字拼音的第一个字母
            String letter = PinyinUtils.getPinyin(mData.get(position)).charAt(0) + "";
            if (position == 0) {
                drawLetter(letter, width, height, c, parent);
            } else {
                String preLetter = PinyinUtils.getPinyin(mData.get(position - 1)).charAt(0) + "";
                if (!letter.equalsIgnoreCase(preLetter)) {
                    drawLetter(letter, width, height, c, parent);
                }
            }
        }
    }

    private void drawLetter(String letter, float width, float height, Canvas c, RecyclerView parent) {
        float fontLength = getFontLength(paint, letter);
        float fontHeight = getFontHeight(paint);
        float tx = (width - fontLength) / 2;
        float ty = height - fontHeight / 2 + getFontLeading(paint);
        c.drawText(letter, tx, ty, paint);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        outRect.set(dip2px(40), 0, 0, 0);
    }

    private int dip2px(int dip) {
        float density = mContext.getResources().getDisplayMetrics().density;
        int px = (int) (dip * density + 0.5f);
        return px;
    }

    public int sp2px(int sp) {
        return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, mContext.getResources().getDisplayMetrics()) + 0.5f);
    }


    /**
     * 返回指定笔和指定字符串的长度
     */
    private float getFontLength(Paint paint, String str) {
        return paint.measureText(str);
    }

    /**
     * 返回指定笔的文字高度
     */
    private float getFontHeight(Paint paint) {
        Paint.FontMetrics fm = paint.getFontMetrics();
        return fm.descent - fm.ascent;
    }


    /**
     * 返回指定笔离文字顶部的基准距离
     */
    private float getFontLeading(Paint paint) {
        Paint.FontMetrics fm = paint.getFontMetrics();
        return fm.leading - fm.ascent;
    }
}
1.3、PinyinUtils.java
/**
 * Created by ${chenyuexueer}
 * 
 * 说明:拼音工具(需要依赖或者导入pinyin4j-2.5.0.jar)
 */

public class PinyinUtils {

    /**
     * 根据传入的字符串(包含汉字),得到拼音
     * 如:
     *
     * 好学 -> HAOXUE
     * 好 学*& -> HAOXUE
     * 好学y2 -> HAOXUE
     *
     * @param str 字符串
     * @return
     */
    public static String getPinyin(String str) {

        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

        StringBuilder sb = new StringBuilder();

        char[] charArray = str.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            char c = charArray[i];
            // 如果是空格, 跳过
            if (Character.isWhitespace(c)) {
                continue;
            }
            if (c >= -127 && c < 128 || !(c >= 0x4E00 && c <= 0x9FA5)) {
                // 满足条件 ,则肯定不是汉字
                sb.append(c);
            } else {
                String s = "";
                try {
                    // 通过char得到拼音集合. 单 -> dan, shan
                    s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
                    sb.append(s);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                    sb.append(s);
                }
            }
        }

        return sb.toString();
    }

}
如果缺代码就从一、(1-6)找,不确定全部文件有没有贴上,没检查(懒癌晚期)

二、TextInputLayout 简单使用

1、MainActivity.java

public class MainActivity extends AppCompatActivity {

    private TextInputLayout mTextInputLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextInputLayout = (TextInputLayout) findViewById(R.id.textInputLayout);

        //开启计数
        mTextInputLayout.setCounterEnabled(true);
        //最大长度6个
        mTextInputLayout.setCounterMaxLength(6);

        //定义错误提示
        mTextInputLayout.getEditText().addTextChangedListener(new MyTextWatch(mTextInputLayout, "长度不能超过6个字符"));

    }
    class MyTextWatch implements TextWatcher {

        TextInputLayout mTextInputLayout;
        String mErrorTip;

        public MyTextWatch(TextInputLayout textInputLayout, String errorTip) {
            mTextInputLayout = textInputLayout;
            mErrorTip = errorTip;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            if (mTextInputLayout.getEditText().getText().toString().trim().length() > 6) {
                mTextInputLayout.setErrorEnabled(true);
                mTextInputLayout.setError(mErrorTip);
            } else {
                mTextInputLayout.setErrorEnabled(false);
            }
        }
    }
}

2、activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.design.widget.TextInputLayout
        android:id="@+id/textInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:errorEnabled="true"
        app:hintAnimationEnabled="true"
        app:hintEnabled="false">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入用户名"/>

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:hintAnimationEnabled="true"
        app:passwordToggleDrawable="@mipmap/ic_launcher"
        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/colorPrimary">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入密码"
            android:inputType="textPassword"/>
    </android.support.design.widget.TextInputLayout>
</LinearLayout>

三、ToolBar 的简单使用

image.png
ToolBar 可以做很多内容,这里只记录SearchView的简单使用

3.1、SearchView

  • 使用过程中遇到错误:
    Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
  • 描述:
    由于Activity已存在ActionBar,所以使用Toolbar进行替换时出错.你可以换主题也可以增加values/styles的 资源文件
  • 解决方案:http://blog.csdn.net/zhaokaiqiang1992/article/details/47442691

3.1.1、MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Toolbar mToolbar;
    private SearchView mSearchView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_view, menu);
        MenuItem item = menu.findItem(R.id.menu_search);
        mSearchView = (SearchView) MenuItemCompat.getActionView(item);

        /*------------------ SearchView有三种默认展开搜索框的设置方式,区别如下: ------------------*/
        //设置搜索框直接展开显示。左侧有放大镜(在搜索框中) 右侧有叉叉 可以关闭搜索框
        mSearchView.setIconified(false);
        //设置搜索框直接展开显示。左侧有放大镜(在搜索框外) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
        mSearchView.setIconifiedByDefault(false);
        //设置搜索框直接展开显示。左侧有无放大镜(在搜索框中) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
        mSearchView.onActionViewExpanded();

        //设置最大宽度
        //        mSearchView.setMaxWidth(500);
        //设置是否显示搜索框展开时的提交按钮
        //        mSearchView.setSubmitButtonEnabled(true);
        //设置输入框提示语
                mSearchView.setQueryHint("hint");

        //搜索框展开时后面叉叉按钮的点击事件
        mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
            @Override
            public boolean onClose() {
                Toast.makeText(getApplicationContext(), "Close", Toast.LENGTH_SHORT).show();
                return false;
            }
        });
        //搜索图标按钮(打开搜索框的按钮)的点击事件
        mSearchView.setOnSearchClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "Open", Toast.LENGTH_SHORT).show();
            }
        });
        //搜索框文字变化监听
        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                Log.e("CSDN_LQR", "TextSubmit : " + s);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String s) {
                Log.e("CSDN_LQR", "TextChange --> " + s);
                return false;
            }
        });

        //        mSearchView.setSuggestionsAdapter();
        return super.onCreateOptionsMenu(menu);
    }

    //右上角的MenuItem的选择事件 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        Log.e("TAG==",item.getTitle().toString());

        return super.onOptionsItemSelected(item);
    }
}

3.1.2、activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:navigationIcon="@mipmap/ic_launcher"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:title="title"
        app:titleTextColor="@android:color/white"/>

</LinearLayout>

3.1.3、search_view.xml 资源文件res/menu/search_view.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools">
    <item
        android:id="@+id/menu_search"
        android:orderInCategory="100"
        android:title="搜索"
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="always"
        />
    <item
        android:id="@+id/scan_local_music"
        android:icon="@mipmap/ic_launcher"
        android:orderInCategory="100"
        android:title="扫描本地音乐"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/select_sort_way"
        android:icon="@mipmap/ic_launcher_round"
        android:orderInCategory="100"
        android:title="选择排序方式"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/get_cover_lyrics"
        android:icon="@mipmap/ic_launcher"
        android:orderInCategory="100"
        android:title="获取封面歌词"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/imporve_tone_quality"
        android:icon="@mipmap/ic_launcher_round"
        android:orderInCategory="100"
        android:title="升级音质"
        app:showAsAction="never"
        />
</menu>
SearchView.gif

3.2、SearchView仿网易云本地音乐搜索

3.2.1、MainActivity.java
public class MainActivity extends AppCompatActivity {

    private ListView mLv;
    private SearchView mSearchView;
    private SearchView.SearchAutoComplete mSearchAutoComplete;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        //将setSupportActionBar(toolbar)放在setNavigationOnClickListener()之前设置才行
        setSupportActionBar(toolbar);
        //相当于返回键的监听
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSearchAutoComplete.isShown()) {
                    try {
                        mSearchAutoComplete.setText("");
                        //①、利用反射方式,调用收起SearchView的onCloseClicked()方法
                        Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
                        method.setAccessible(true);
                        method.invoke(mSearchView);

                        //②、或者mSearchView.setIconified(true)直接调用onCloseClicked()方法,可自行测试看效果

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    finish();
                }
            }
        });

        mLv = (ListView) findViewById(R.id.lv);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.search_view, menu);//给右上角的MenuItem充入布局菜单
        MenuItem searchItem = menu.findItem(R.id.menu_search);//得到一个MenuItem对象

        //通过MenuItem得到SearchView
        mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        //相当于输入框(不知这样说准不准确)
        mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
        mSearchView.setQueryHint("搜索本地歌曲by code");

        //设置输入框提示文字样式
        mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.darker_gray));
        mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.background_light));
        mSearchAutoComplete.setTextSize(14);
        //设置触发查询的最少字符数(默认2个字符才会触发查询)
        mSearchAutoComplete.setThreshold(1);

        //设置搜索框有字时显示叉叉,无字时隐藏叉叉
        mSearchView.onActionViewExpanded();
        //是否展开状态,也就是是否可以输入编辑
        mSearchView.setIconified(true);

        //放大镜  默认为true在框内,设置false则在框外
//        mSearchView.setIconifiedByDefault(false);
        //是否显示提交按钮,就是有一个向右的三角形
        // 设置默认无内容时的文字提示
//        mSearchView.setQueryHint("情输入歌曲名查找");

        //设置输入框提示文字样式
//        mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.white));//设置提示文字颜色
//        mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.white));//设置内容文字颜色

        //修改搜索框控件间的间隔(这样只是为了更加接近网易云音乐的搜索框)
        // 还有一种方式,res/style里面,请看activity_main.xml
        LinearLayout search_edit_frame = (LinearLayout) mSearchView.findViewById(R.id.search_edit_frame);
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) search_edit_frame.getLayoutParams();
        params.leftMargin = 0;
        params.rightMargin = 0;
        search_edit_frame.setLayoutParams(params);

        //监听SearchView的内容 ,提交按钮的事件监听
        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            //提交按钮的点击事件
            @Override
            public boolean onQueryTextSubmit(String s) {
                return false;
            }
            //当输入框内容改变的时候回调
            @Override
            public boolean onQueryTextChange(String s) {

                Cursor cursor = TextUtils.isEmpty(s) ? null : queryData(s);

                //                if (mSearchView.getSuggestionsAdapter() == null) {
                //                    mSearchView.setSuggestionsAdapter(new SimpleCursorAdapter(SearchViewActivity2.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1}));
                //                } else {
                //                    mSearchView.getSuggestionsAdapter().changeCursor(cursor);
                //                }
                setAdapter(cursor);

                return false;
            }
        });

        return super.onCreateOptionsMenu(menu);
    }

    // 让菜单同时显示图标和文字
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menu != null) {
            if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
                try {
                    //①、反射方式
                    Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    method.setAccessible(true);
                    method.invoke(menu, true);
                    //②、。。。
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }

    //数据库查询
    private Cursor queryData(String key) {
        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(getFilesDir() + "music.db", null);
        Cursor cursor = null;
        try {
            String querySql = "select * from tb_music where name like '%" + key + "%'";
            cursor = db.rawQuery(querySql, null);
            Log.e("CSDN_LQR", "querySql = " + querySql);
        } catch (Exception e) {
            e.printStackTrace();
            String createSql = "create table tb_music (_id integer primary key autoincrement,name varchar(100))";
            db.execSQL(createSql);

            String insertSql = "insert into tb_music values (null,?)";
            for (int i = 0; i < Cheeses.NAMES.length; i++) {
                db.execSQL(insertSql, new String[]{Cheeses.NAMES[i]});
            }

            String querySql = "select * from tb_music where name like '%" + key + "%'";
            cursor = db.rawQuery(querySql, null);

            Log.e("CSDN_LQR", "createSql = " + createSql);
            Log.e("CSDN_LQR", "querySql = " + querySql);
        }
        return cursor;
    }

    //listview的adapter
    private void setAdapter(Cursor cursor) {
        if (mLv.getAdapter() == null) {
            SimpleCursorAdapter adapter = new SimpleCursorAdapter(MainActivity.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1});
            mLv.setAdapter(adapter);
        } else {
            ((SimpleCursorAdapter) mLv.getAdapter()).changeCursor(cursor);
        }
    }
}
3.2.2、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:fillViewport="true"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:navigationIcon="@mipmap/ic_launcher"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:title="本地音乐"
        app:titleTextColor="@android:color/white"/>

    <!--当ScrollView内容不足的时候,设置其height="match_parent"属性,结果还是wrap_content。使用android:fillViewport="true"-->
    <!--NavigationIcon和标题之间的距离-->

    <!--在res/style.xml,写入下面代码,可修改navigationIcon和SearchView之间的距离过大-->
    <!--<style name="ToolbarStyle" parent="Base.Widget.AppCompat.Toolbar">-->
        <!--<item name="contentInsetStart">0dp</item>-->
        <!--<item name="contentInsetStartWithNavigation">0dp</item>-->
    <!--</style>-->
    <!---->
    
    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@android:color/black"
        android:dividerHeight="1dp"></ListView>
    
</LinearLayout>
3.2.3、search_view.xml

同上----3.1.3、search_view.xml 资源文件res/menu/search_view.xml

3.2.4、Adapter的item布局item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
    <!--android:id="@android:id/text1"-->
    <TextView
        android:id="@+id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:textColor="@android:color/black"/>
</LinearLayout>
3.2.5、数据Cheeses.NAMES [ ]
/**
 * Created by ${chenyuexueer} 
 * 说明:数据
 */

public class Cheeses {

    public static final String[] NAMES = new String[] { "宋江", "卢俊义", "吴用",
            "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
            "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
            "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
            " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
            "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
            "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
            "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
            "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
            "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
            "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
            "时迁", "段景柱" };

}
SearchView仿网易云音乐搜索.gif
四、Palette 的简单使用

暂时不记录在笔记中,以后有空记得就补上

image.png
五、CardView卡片效果

暂时不记录在笔记中,以后有空记得就补上

六、FloatingActionButton浮动效果

暂时不记录在笔记中,以后有空记得就补上

上一篇下一篇

猜你喜欢

热点阅读