java中没有design,笔记:MaterialDesign(一)--控/组件简单使用

忘了贴图 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中

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

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"/>

android:id="@+id/viewPager"

android:layout_width="match_parent"

android:layout_height="match_parent" />

二、ListPopupWindow

2.1、在MainActivity.java中

public class MainActivity extends AppCompatActivity {

private ListPopupWindow mListPopupWindow;

private ArrayAdapter 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 中

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="showPopupWindow"

android:text="listPoppupWindow测试"/>

三、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 中

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="showPopupMenu"

android:text="PopupMenu测试"/>

3.3、main.xml 资源(res/menu/main.xml)

xmlns:app="http://schemas.android.com/apk/res-auto">

android:icon="@mipmap/ic_launcher"

android:orderInCategory="100"

android:title="test 1"

app:showAsAction="withText"/>

android:icon="@mipmap/ic_launcher"

android:orderInCategory="101"

android:title="test 2"

app:showAsAction="withText"

/>

android:icon="@mipmap/ic_launcher"

android:orderInCategory="103"

android:title="test 3"

app:showAsAction="withText"

/>

四、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 中

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:orientation="horizontal">

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:onClick="beginning"

android:text="beginning"

android:textAllCaps="false"/>

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:onClick="middle"

android:text="middle"

android:textAllCaps="false"/>

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:onClick="end"

android:text="end"

android:textAllCaps="false"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:orientation="horizontal">

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:onClick="beginning_middle"

android:text="beginning|middle"

android:textAllCaps="false"/>

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:onClick="end_middle"

android:text="end|middle"

android:textAllCaps="false"/>

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:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:text="AppCompatEditText"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:text="AppCompatTextView"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:text="AppCompatButton"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:text="这个AppCompatCheckBox\n下面的一排五星是AppCompatRatingBar控件"/>

android:layout_marginTop="10dp"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

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

①、水平/垂直分割线

②、网格布局分割线

③、侧边字母提示样式

④、悬浮头布局样式

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

5.1.1、在MainActivity.java中

public class MainActivity extends AppCompatActivity {

private List 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中

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/rv"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

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.

*

* 说明:自定义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 {

private List mData;

public MyAdapter(List 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 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.

*

* 说明:自定义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

android:shape="rectangle">

android:width="2dp"

android:height="2dp"/>

5.3、侧边字母提示 装饰

5.3.1、MainActivity.java

public class MainActivity extends AppCompatActivity {

private List 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() {

@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}

*

* 说明:

*/

public class MyDecorationThree extends RecyclerView.ItemDecoration {

Context mContext;

List mData;

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//画笔

public MyDecorationThree(Context context, List 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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值