美文网首页
笔记:MaterialDesign(一)--控/组件简单使用

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

作者: RoJacKing | 来源:发表于2018-05-09 16:28 被阅读214次

    忘了贴图 copy代码运行看效果

    一、TabLayout+ViewPager+Fragment

    1.1、MainActivity.java中使用
    public class MainActivity extends AppCompatActivity {
    
        private TabLayout mTabLayout;
        private ViewPager mViewPager;
        private LinearLayout mLinearLayout;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mTabLayout = (TabLayout) findViewById(R.id.tabLayout);
            mViewPager = (ViewPager) findViewById(R.id.viewPager);
            /**
             * 将TabLayout与ViewPager结合
             *
             */
            //步骤一:给VIewPager设置Adapter(FragmentPagerAdapter)
            MyViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager());
            mViewPager.setAdapter(adapter);
    
            /**
             * 步骤二(到了步骤二可以看效果了,后面步骤是设置indicator属性等代码)
             *
             * 很牛逼的一个方法
             *
             * 关联TabLayout与ViewPager,互相绑定,且适配器必须重写getPageTitle()方法
             *
             * 这个方法三个作用
             *                               1、从ViewPager中获取TabLayout的Title----getPageTitle()
             *                               2、ViewPager滑动时,设置TabLayout的Title和indicator
             *                               3、点击TabLayout时,ViewPager相应变化
             */
            mTabLayout.setupWithViewPager(mViewPager);
    
            //步骤三   设置分割线:参考https://www.jianshu.com/p/bbefb97cccdd
            mLinearLayout = (LinearLayout) mTabLayout.getChildAt(0);
            // 在所有子控件的中间显示分割线(还可 只显示顶部、尾部和不显示分割线)
            mLinearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
            // 设置分割线的距离本身(LinearLayout)的内间距
            mLinearLayout.setDividerPadding(50);
            // 设置分割线的样式
            mLinearLayout.setDividerDrawable(ContextCompat.getDrawable(this, R.drawable.divider_vertical));
            mLinearLayout.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
    
    
            //步骤四   设置指示器的长度(本来是不可设置的),这里是通过Tab外间距的方式
            // 自定义指示器(Indicator)的“长度”的两种方法,会有跳动的bug情况未解决,不推荐使用只做为一种示例
            // 方法一:反射
    //                setIndicator(mTabLayout,10,10);
            // 方法二:查找子控件
            int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, Resources.getSystem().getDisplayMetrics());
            int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, Resources.getSystem().getDisplayMetrics());
            for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
                View tabView = mLinearLayout.getChildAt(i);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
                params.leftMargin = left;
                params.rightMargin = right;
                tabView.setLayoutParams(params);
            }
        }
    
    
        public void setIndicator(TabLayout tabs, int leftDip, int rightDip) {
            Class<?> tabLayout = tabs.getClass();
            Field tabStrip = null;//java.lang.reflect.Field
            try {
                tabStrip = tabLayout.getDeclaredField("mTabStrip");
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
    
            tabStrip.setAccessible(true);
            LinearLayout llTab = null;
            try {
                llTab = (LinearLayout) tabStrip.get(tabs);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
            int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
            int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());
    
            for (int i = 0; i < llTab.getChildCount(); i++) {
                View child = llTab.getChildAt(i);
                child.setPadding(0, 0, 0, 0);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
                params.leftMargin = left;
                params.rightMargin = right;
                child.setLayoutParams(params);
                child.invalidate();
            }
        }
    
    
        //步骤一(1)
        private class MyViewPagerAdapter extends FragmentPagerAdapter {
    
            //步骤一(1)、②  数据
            private final String[] title = new String[]{
                    "推荐", "热点", "视频", "图片", "新闻",
                    "汽车", "科技","财经", "游戏", "广州","旅游"};
    
    
            public MyViewPagerAdapter(FragmentManager fm) {
                super(fm);
            }
    
            @Override
            public Fragment getItem(int position) {
                //步骤一(1)、③  实例化fragment
    
                Fragment fragment = new TextFragment();
                //给fragment传数据
                Bundle bundle = new Bundle();
                bundle.putString("title", title[position]);
                fragment.setArguments(bundle);
                return fragment;
            }
    
            @Override
            public int getCount() {
                return title.length;
            }
    
            //步骤一(1)、①  实例化fragment
            @Override
            public CharSequence getPageTitle(int position) {
                return title[position];
            }
        }
    }
    
    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.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabBackground="@color/colorPrimaryDark"
            app:tabMode="scrollable"
            app:tabSelectedTextColor="@android:color/white"
            app:tabTextColor="@android:color/darker_gray"/>
    
        <!--
            app:tabBackground="@color/colorPrimaryDark"整个tablayout的背景颜色
            app:tabMode="scrollable"超出屏幕tablayout可滚动
            app:tabSelectedTextColor="@android:color/white"被选中的颜色
            app:tabTextColor="@android:color/darker_gray"非选中的颜色
         -->
    
        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    
    </LinearLayout>
    

    二、ListPopupWindow

    2.1、在MainActivity.java中
    public class MainActivity extends AppCompatActivity {
    
        private ListPopupWindow mListPopupWindow;
        private ArrayAdapter<String> mAdapter;
        private String[] mItemArr;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mItemArr = new String[]{"test 1", "test 2", "test 3", "test 4", "test 5", "test 6", "test 7", "test 8"};
            mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mItemArr);
    
        }
    
        public void showPopupWindow(View view){
            if (mListPopupWindow == null)
                mListPopupWindow = new ListPopupWindow(this);
            //应该是 设置 ListPopupWindow 的数据适配器
            mListPopupWindow.setAdapter(mAdapter);
            //应该是 设置 ListPopupWindow 的显示位置(在指定控件下方)
            mListPopupWindow.setAnchorView(view);
            //应该是 设置上下边距的距离
            mListPopupWindow.setVerticalOffset(10);
            //应该是 设置 ListPopupWindow 的宽度
            mListPopupWindow.setWidth(300);
            //应该是 设置 ListPopupWindow 的高度
            mListPopupWindow.setHeight(600);
            //应该是 设置 ListPopupWindow 的条目点击事件(必须在show方法前设置,否则无效)
            mListPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(getApplicationContext(), mItemArr[position], Toast.LENGTH_SHORT).show();
                    mListPopupWindow.dismiss();
                }
            });
            mListPopupWindow.show();
        }
    
    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">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="showPopupWindow"
            android:text="listPoppupWindow测试"/>
    
    </LinearLayout>
    

    三、PopupMenu的简单使用

    3.1、在MainActivity.java中
     public void showPopupMenu(View view) throws NoSuchFieldException, IllegalAccessException {
            PopupMenu popupMenu = new PopupMenu(this, view);
            //设置 PopupMenu 的显示菜单项
            popupMenu.inflate(R.menu.main);
            // popupMenu.getMenuInflater().inflate(R.menu.main, popupMenu.getMenu());//上一行与这一行效果一样
            //默认 PopupMenu 不显示条目icon,可以通过反射来强制使其显示icon
            Field field = popupMenu.getClass().getDeclaredField("mPopup");
            field.setAccessible(true);
            MenuPopupHelper mHelper = (MenuPopupHelper) field.get(popupMenu);
            mHelper.setForceShowIcon(true);
            //设置 PopupMenu 的条目点击事件(点击后会自动dismiss)
            popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    Toast.makeText(getApplicationContext(), item.getTitle(), Toast.LENGTH_SHORT).show();
                    return false;
                }
            });
            //显示 PopupMenu
            popupMenu.show();
        }
    
    3.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">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="showPopupMenu"
            android:text="PopupMenu测试"/>
    
    </LinearLayout>
    
    3.3、main.xml 资源(res/menu/main.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">
        <item
            android:icon="@mipmap/ic_launcher"
            android:orderInCategory="100"
            android:title="test 1"
            app:showAsAction="withText"/>
        <item
            android:icon="@mipmap/ic_launcher"
            android:orderInCategory="101"
            android:title="test 2"
            app:showAsAction="withText"
            />
        <item
            android:icon="@mipmap/ic_launcher"
            android:orderInCategory="103"
            android:title="test 3"
            app:showAsAction="withText"
            />
    </menu>
    
    

    四、LinearLayoutCompat的简单使用

    4.1、在MainActivity.java中
    
    public class MainActivity extends AppCompatActivity {
    
        private LinearLayoutCompat linearLayoutCompat;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            linearLayoutCompat = (LinearLayoutCompat) findViewById(R.id.linearLayoutCompat);
        }
    
        //布局的前面一个分割线
        public void beginning(View view) {
            linearLayoutCompat.setShowDividers(LinearLayoutCompat.SHOW_DIVIDER_BEGINNING);
        }
        //布局的除了前面和后面没有分割线,中间控件之间都有分割线
        public void middle(View view) {
            linearLayoutCompat.setShowDividers(LinearLayoutCompat.SHOW_DIVIDER_MIDDLE);
        }
        //布局的尾部一个分割线
        public void end(View view) {
            linearLayoutCompat.setShowDividers(LinearLayoutCompat.SHOW_DIVIDER_END);
        }
        //布局的除了尾部没有分割线,其他有(前面和中间)
        public void beginning_middle(View view) {
            linearLayoutCompat.setShowDividers(LinearLayoutCompat.SHOW_DIVIDER_BEGINNING | LinearLayoutCompat.SHOW_DIVIDER_MIDDLE);
    
        }
        //布局的除了前面没有分割线,其他有(中间和后面)
        public void end_middle(View view) {
            linearLayoutCompat.setShowDividers(LinearLayoutCompat.SHOW_DIVIDER_MIDDLE | LinearLayoutCompat.SHOW_DIVIDER_END);
        }
    
    }
    
    4.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">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="beginning"
                android:text="beginning"
                android:textAllCaps="false"/>
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="middle"
                android:text="middle"
                android:textAllCaps="false"/>
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="end"
                android:text="end"
                android:textAllCaps="false"/>
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="beginning_middle"
                android:text="beginning|middle"
                android:textAllCaps="false"/>
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="end_middle"
                android:text="end|middle"
                android:textAllCaps="false"/>
    
    
        </LinearLayout>
    
        <android.support.v7.widget.LinearLayoutCompat
            android:id="@+id/linearLayoutCompat"
            android:layout_marginTop="10dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:orientation="vertical"
            app:divider="@drawable/line"
            app:showDividers="beginning">
    
            <android.support.v7.widget.AppCompatEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="AppCompatEditText"/>
    
            <android.support.v7.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="AppCompatTextView"/>
    
            <android.support.v7.widget.AppCompatButton
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="AppCompatButton"/>
    
            <android.support.v7.widget.AppCompatCheckBox
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="这个AppCompatCheckBox\n下面的一排五星是AppCompatRatingBar控件"/>
    
            <android.support.v7.widget.AppCompatRatingBar
                android:layout_marginTop="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
    
        </android.support.v7.widget.LinearLayoutCompat>
    </LinearLayout>
    

    五、RecyclerView.ItemDecoration 条目item装饰 的简单使用

    ①、水平/垂直分割线
    ②、网格布局分割线
    ③、侧边字母提示样式
    ④、悬浮头布局样式

    5.1、水平/垂直 分割线 装饰

    5.1.1、在MainActivity.java中
    public class MainActivity extends AppCompatActivity {
    
        private List<String> mData = new ArrayList<>();
        private RecyclerView mRv;
        private MyAdapter mMyAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mRv = (RecyclerView) findViewById(R.id.rv);
    
            initDecoration();
            initData();
            initRecyclerView();
    
        }
    
        //初始化修饰布局(分割线)
        private void initDecoration() {
            MyDecorationOne decorationOne = new MyDecorationOne(this, LinearLayoutManager.VERTICAL);
            mRv.addItemDecoration(decorationOne);
        }
    
        //初始化数据
        private void initData() {
            for (int i = 0; i < 100; i++) {
                mData.add("item " + i);
            }
        }
    
        //初始化recyclerview,关联adapter
        private void initRecyclerView() {
            mMyAdapter = new MyAdapter(mData);
            mRv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
            mRv.setAdapter(mMyAdapter);
        }
    
    }
    
    5.1.2、在activity_main.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>
    
    5.1.3、自定义装饰 MyDecorationOne.java
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Rect;
    import android.graphics.drawable.Drawable;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * Created by ${chenyuexueer} on 2018/5/9.
     * <p>
     * 说明:自定义recyclerview的自定义条目装饰(分割线,当然它不仅仅可以作为分割线)
     *
     * 1、继承RecyclerView.ItemDecoration,
     * 重写 public void onDraw()和 public void getItemOffsets()方法(并不是必须,可不要)
     *
     * 2、构造方法,初始化属性等
     *
     * 3、设计绘图方法
     */
    
    public class MyDecorationOne extends RecyclerView.ItemDecoration {
    
        int orientation = RecyclerView.VERTICAL;//默认垂直
        private final Drawable mDivider;
    
        public MyDecorationOne(Context context, int orientation) {
            this.orientation = orientation;//初始化recyclerview布局方向,activity传过来的recyclerview的布局方向
            int[] attrs = new int[]{android.R.attr.listDivider};//系统提供的属性
            TypedArray a = context.obtainStyledAttributes(attrs);//属性组
            mDivider = a.getDrawable(0);//取组中第一个
            a.recycle();//回收
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);
    
            int childCount = parent.getChildCount();//recyclerview的子item的条数
    
            if (orientation == RecyclerView.HORIZONTAL) {//activity那边设置是水平布局,则绘制一个个垂直()装饰
                drawVertical(c, parent,childCount);
            } else if (orientation == RecyclerView.VERTICAL) {//activity那边设置是水平布局,则绘制一个个垂直装饰
                drawHorizontal(c, parent,childCount);
            }
        }
    
        //绘制垂直装饰
        private void drawVertical(Canvas c, RecyclerView parent,  int childCount) {
    
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);//第i条item的view对象
                //第i条item的view对象的布局参数
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                //计算装饰(分割线)的绘制参数(边距)
                int left = child.getRight() + params.rightMargin;
                int top = child.getTop() - params.topMargin;
                int right = left + mDivider.getIntrinsicWidth();
                int bottom = child.getBottom() + params.bottomMargin;
                //设置装饰(分割线)边距
                mDivider.setBounds(left, top, right, bottom);
                //开始绘制
                mDivider.draw(c);
            }
        }
    
        //绘制水平装饰
        private void drawHorizontal(Canvas c, RecyclerView parent,  int childCount) {
    
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                int left = child.getLeft() - params.leftMargin;
                int top = child.getBottom() + params.bottomMargin;
                int right = child.getRight() + params.rightMargin;
                int bottom = top + mDivider.getIntrinsicHeight();
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(c);
            }
        }
    
        /**
         * 设置条目周边的偏移量(即偏移分割线的大小距离)
         */
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            if (orientation == RecyclerView.HORIZONTAL) {
                //画垂直线
                outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
            } else if (orientation == RecyclerView.VERTICAL) {
                //画水平线
                outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
            }
        }
    
    5.1.4、MyAdapter.java
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import java.util.List;
    
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    
        private List<String> mData;
    
        public MyAdapter(List<String> data) {
            mData = data;
        }
    
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, null);
            itemView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            return new MyViewHolder(itemView);
        }
    
        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.mTv.setText(mData.get(position));
        }
    
        @Override
        public int getItemCount() {
            return mData.size();
        }
    
        class MyViewHolder extends RecyclerView.ViewHolder {
    
            TextView mTv;
    
            public MyViewHolder(View itemView) {
                super(itemView);
                mTv = (TextView) itemView.findViewById(android.R.id.text1);
            }
        }
    
    }
    

    5.2、网格分割 装饰

    5.2.1、MainActivity.java
    public class MainActivity extends AppCompatActivity {
    
        private List<String> mData = new ArrayList<>();
        private RecyclerView mRv;
        private MyAdapter mMyAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mRv = (RecyclerView) findViewById(R.id.rv);
    
            initDecoration();
            initData();
            initRecyclerView();
    
        }
    
        //初始化修饰布局(分割线)
        private void initDecoration() {
            MyDecorationTwo decorationTwo = new MyDecorationTwo(this);
            mRv.addItemDecoration(decorationTwo);
        }
    
        //初始化数据
        private void initData() {
            for (int i = 0; i < 100; i++) {
                mData.add("item " + i);
            }
        }
    
        //初始化recyclerview,关联adapter,这里使用GridLayoutManager表格布局
        private void initRecyclerView() {
            mMyAdapter = new MyAdapter(mData);
            mRv.setLayoutManager(new GridLayoutManager(this, 4));
            mRv.setAdapter(mMyAdapter);
        }
    
    }
    
    5.2.2、activity_main.xml

    具体代码----同上(5.1.2、activity_main.xml)

    5.2.3、 MyAdapter.java

    具体代码----同上(5.1.4、MyAdapter.java)

    5.2.4、自定义装饰 MyDecorationTwo.java
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Rect;
    import android.graphics.drawable.Drawable;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * Created by ${chenyuexueer} on 2018/5/9.
     * <p>
     * 说明:自定义recyclerview的自定义条目装饰(网格分割)
     *
     * 1、构造方法,初始化属性等
     *
     * 2、继承RecyclerView.ItemDecoration,
     * 重写 public void onDraw()和 public void getItemOffsets()方法
     * public void getItemOffsets()方法并不是必须,可不用(没有节点),可以注释掉这个方法看效果
     *
     * 3、设计绘图方法
     */
    
    public class MyDecorationTwo extends RecyclerView.ItemDecoration {
    
        private final Drawable mDivider;
    
        public MyDecorationTwo(Context context) {//构造方法初始化数据
    
            //与MyDecorationOne相比,这里是自定义的资源文件,MyDecorationOne是系统提供的资源文件
            mDivider = context.getResources().getDrawable(R.drawable.divider);
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);
    
            int childCount = parent.getChildCount();//recyclerview的子item的条数
    
            //水平垂直都要绘制分割线,这样才能形成网格
            drawVertical(c, parent,childCount);
            drawHorizontal(c, parent,childCount);
        }
    
        //绘制垂直装饰
        private void drawVertical(Canvas c, RecyclerView parent, int childCount) {
    
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);//第i条item的view对象
                //第i条item的view对象的布局参数
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                //计算装饰(分割线)的绘制参数(边距)
                int left = child.getRight() + params.rightMargin;
                int top = child.getTop() - params.topMargin;
                int right = left + mDivider.getIntrinsicWidth();
                int bottom = child.getBottom() + params.bottomMargin;
                //设置装饰(分割线)边距
                mDivider.setBounds(left, top, right, bottom);
                //开始绘制
                mDivider.draw(c);
            }
        }
    
        //绘制水平装饰
        private void drawHorizontal(Canvas c, RecyclerView parent, int childCount) {
    
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                int left = child.getLeft() - params.leftMargin;
                int top = child.getBottom() + params.bottomMargin;
                int right = child.getRight() + params.rightMargin;
                int bottom = top + mDivider.getIntrinsicHeight();
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(c);
            }
        }
    
        /**
         * 设置条目右下边的偏移量(效果:右下边有一个空白的小正方形节点)
         */
        @Override
        public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
            super.getItemOffsets(outRect, itemPosition, parent);
    
            //getIntrinsicWidth()/getIntrinsicHeight()与getWidth()/getHeight()区别具体请自行百度谷歌
            int right = mDivider.getIntrinsicWidth();
            int bottom = mDivider.getIntrinsicHeight();
    
            //第itemPosition个条目item的最后一列,即正方形的下边,则不需要绘制右边
            if (isLastSpan(itemPosition, parent)) {
                right = 0;
            }
    
            //第itemPosition个条目item的最后一行,即正方形的右边,则不需要绘制底部
            if (isLastRow(itemPosition, parent)) {
                bottom = 0;
            }
            outRect.set(0, 0, right, bottom);
        }
    
        public boolean isLastRow(int itemPosition, RecyclerView parent) {
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof GridLayoutManager) {
                int spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
                int itemCount = parent.getAdapter().getItemCount();
                if ((itemCount - itemPosition - 1) < spanCount)//则不需要底部
                    return true;
            }
            return false;
        }
    
        public boolean isLastSpan(int itemPosition, RecyclerView parent) {
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof GridLayoutManager) {
                int spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
                if ((itemPosition + 1) % spanCount == 0)//则不需要绘制右边
                    return true;
            }
            return false;
        }
    }
    
    5.2.4、divider.xml 资源文件 res/drawable/divider.xml
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
           android:shape="rectangle">
    
        <solid android:color="#f00"/>
        <size
            android:width="2dp"
            android:height="2dp"/>
    
    </shape>
    

    5.3、侧边字母提示 装饰

    需要依赖 拼音工具包
    sourceforge 开源项目jar包
    Github 依赖

    5.3.1、MainActivity.java
    public class MainActivity extends AppCompatActivity {
    
        private List<String> mData = new ArrayList<>();
        private RecyclerView mRv;
        private MyAdapter mMyAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mRv = (RecyclerView) findViewById(R.id.rv);
    
            initData();
            initDecoration();
            initRecyclerView();
    
        }
    
        //初始化修饰布局(首字母提示)
        private void initDecoration() {
            MyDecorationThree decorationThree = new MyDecorationThree(this, mData);
            mRv.addItemDecoration(decorationThree);
        }
    
        //初始化数据
        private void initData() {
            mData = Arrays.asList(Cheeses.NAMES);
            //系统方法     排序
            Collections.sort(mData, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return PinyinUtils.getPinyin(o1).compareTo(PinyinUtils.getPinyin(o2));
                }
            });
        }
    
        //初始化recyclerview,关联adapter
        private void initRecyclerView() {
            mMyAdapter = new MyAdapter(mData);
            mRv.setLayoutManager(new LinearLayoutManager(this));
            mRv.setAdapter(mMyAdapter);
        }
    
    }
    
    5.3.2、拼音工具 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();
        }
    
    }
    
    5.3.3、自定义修饰类 MyDecorationThree .java
    /**
     * Created by ${chenyuexueer} 
     * <p>
     * 说明:
     */
    
    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;
        }
    }
    
    5.3.4、名字数组数据类Cheeses.java
    
    /**
     * Created by ${chenyuexueer}
     * 说明:姓名数据
     */
    
    public class Cheeses {
    
        public static final String[] NAMES = new String[] { "宋江", "卢俊义", "吴用",
                "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
                "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
                "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
                " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
                "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
                "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
                "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
                "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
                "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
                "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
                "时迁", "段景柱" };
    
    }
    
    5.3.5、activity_main.xml

    具体代码----同上(5.1.2、activity_main.xml)

    5.3.6、 MyAdapter.java

    具体代码----同上(5.1.4、MyAdapter.java)

    5.4、悬浮头布局(使用ItemDecoration)

    懒得写,将就着看这个吧,这个结合几个效果一起使用《Android二级联动》

    MaterialDesign笔记(二)--控/组件简单使用
    参考自

    相关文章

      网友评论

          本文标题:笔记:MaterialDesign(一)--控/组件简单使用

          本文链接:https://www.haomeiwen.com/subject/sfcwrftx.html