android之省市区三级联动,recyclerview首字母悬浮列表
2018-01-31 21:20
393 查看
什么都是假的,先看效果图
三级联动
首先感谢这两个作者
https://github.com/venshine/WheelView https://github.com/wulianghuan/Cascade_Master
这个效果我只是搬运工,整合了这两个作者的东西,弄出来的,也没啥好说的,就是一个popupwin,后面我会放源码,大家自行下载观看(不要积分,给个start就行)
recyclerview首字母悬浮效果
思路主要分为三点:
1、首先拿到数据的拼音的首字母,排序
2、在adapter里面检查首字母第一次出现的位置,从而控制显示隐藏
3、首字母出现的位置设置tag,跟主页面的字母进行动画替换(重点)
4、点击侧边的字母进行联动
我们先通过 android源码的HanziToPinyin这个类,把我们的数据转成拼音,然后截取首字母
/**
* 比较器,比较拼音的首字母
*/
public class PinYinComparator implements Comparator<PinYinComparator.CityBean> {
@Override
public int compare(CityBean lhs, CityBean rhs) {
return lhs.getSortLetter().compareTo(rhs.getSortLetter());
}
/**
* 实体类,用来存储,汉字,和对应的首字母的拼音
*/
public static class CityBean {
private String name;
private String sortLetter;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSortLetter() {
return sortLetter;
}
public void setSortLetter(String sortLetter) {
this.sortLetter = sortLetter;
}
}
/**
* 汉字转拼音
* @param input 传入的汉字
* @return
*/
public static String getPinYin(String input) {
ArrayList tokens = HanziToPinyin.getInstance().get(input);
StringBuilder sb = new StringBuilder();
if (tokens != null && tokens.size() > 0) {
Iterator iterator = tokens.iterator();
while (iterator.hasNext()) {
HanziToPinyin.Token token = (HanziToPinyin.Token) iterator.next();
if (2 == token.type) {
sb.append(token.target);
} else {
sb.append(token.source);
}
}
}
return sb.toString().toUpperCase();
}
} 后面拿到数据,循环调用上面的getPinYin就能得到字母,然后截取第一个,在存到上面的实体类里面,然后使用比较器进行排序Collections.sort(mCityList,
new
PinYinComparator());
到这里我们的第一步就搞定了。
下面我们来看,控制首字母的显示和隐藏,我们来看adapter的onBindViewHolder
方法,我们先拿到实体类,然后拿首字母,通过getPositionForSelect得到这个字母在排序中的位置,而我们的recyclerview的position到达这个位置时就显示首字母和设置tag,否则的话就隐藏,这里设置tag是为了下一步的进行。
PinYinComparator.CityBean info = mData.get(position);
holder.name.setText(info.getName());
char selection = info.getSortLetter().charAt(0);
int letterPosition = getPositionForSelection(selection);
if (letterPosition == position) {
holder.letter_tv.setText(info.getSortLetter());
holder.letter_tv.setVisibility(View.VISIBLE);
holder.itemView.setTag(HAS_STICKY_VIEW);
} else {
holder.letter_tv.setVisibility(View.GONE);
holder.itemView.setTag(NONE_STICKY_VIEW);
} 动画替换
在主页面,我们用一个和字母一样的布局跟recyclerview嵌套在一起,其实那个悬浮头就是在主页面里的布局,
而不是item的那个字母头,我们只是监听滑动,到了我们上面设置tag的地方,就让他滑动他自身的高度,就是下面的
mLetterText
{
View letterView = mRecyclerView.findChildViewUnder(mLetterText.getMeasuredWidth() / 2, 3);
if (letterView != null && letterView.getContentDescription() != null) {
mLetterText.setText(String.valueOf(letterView.getContentDescription()));
}
View recyclerItem = mRecyclerView.findChildViewUnder(mLetterText.getMeasuredWidth() / 2,
mLetterText.getMeasuredHeight() + 1);
if (recyclerItem != null && recyclerItem.getTag() != null) {
//这个recycleritem其实是和mLetterText一样的
//但是滑动recyclerview他的top会改变,此时,我们就让mLetterText跟着改变
int deltaY = recyclerItem.getTop() - mLetterText.getMeasuredHeight();
if ((int) recyclerItem.getTag() == mCityAdapter.HAS_STICKY_VIEW) {
if (recyclerItem.getTop() > 0) {
mLetterText.setTranslationY(deltaY);
} else {
mLetterText.setTranslationY(0);
}
} else if ((int) recyclerItem.getTag() == mCityAdapter.NONE_STICKY_VIEW) {
mLetterText.setTranslationY(0);
}
}
}
绘制导航字母条
这里难度不大,只是我们绘制的时候要知道,每个字母的x和y坐标应该怎么定,y坐标是计算空件自身的高度,然后除于27(还有一个#)
这样就得到每个字母的y坐标了,x就是控件自身的宽度的一般减去字母的宽度的一半。如何知道我们点击了哪个字母呢?
看下我们的公式就明白了:点击的字母/27=点击的y坐标/总高度
而我们求:点击的字母=(27*点击的y坐标)/总高度
/**
* 字母导航控件
*/
public class NavigationView extends View {
private Paint mPaint;
private String[] mDate = new String[]{"A", "B", "C", "D", "E", "F",
"G", "H", "I", "J", "K", "L", "N", "M", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
private int position = -1;
private int mHeight;
public NavigationView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(23);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
public NavigationView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mHeight = getHeight();
int width = getWidth();
int simpleHeight = mHeight / mDate.length;
for (int i = 0; i < mDate.length; i++) {
mPaint.setColor(Color.BLUE);
if (i == position) {
mPaint.setColor(Color.RED);
}
float x = (width - mPaint.measureText(mDate[i])) / 2.0f;
float y = simpleHeight * (i + 1);
canvas.drawText(mDate[i], x, y, mPaint);
}
}
@SuppressLint("NewApi")
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
int oldPosition = position;
int c = (y * mDate.length) / mHeight;
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
setBackground(new ColorDrawable(0));
if (mDialog != null) {
mDialog.setVisibility(View.GONE);
}
position = -1;
break;
default:
setBackgroundColor(Color.parseColor("#EEE5DE"));
if (c >= 0 && c < mDate.length && c != oldPosition) {
if (mOnTouchItemListener != null) {
mOnTouchItemListener.onTouch(mDate[c]);
Log.e("------", "onTouchEvent: "+mDate[c] );
}
if (mDialog != null) {
mDialog.setText(mDate[c]);
mDialog.setVisibility(View.VISIBLE);
}
}
position = c;
invalidate();
break;
}
return true;
}
private TextView mDialog;
public void setDialog(TextView dialog) {
mDialog = dialog;
}
private OnTouchItemListener mOnTouchItemListener;
public void setOnTouchItemListener(OnTouchItemListener onTouchItemListener) {
mOnTouchItemListener = onTouchItemListener;
}
public interface OnTouchItemListener {
void onTouch(String var1);
}
}大功告成,github地址:https://github.com/WoBuShuo/SelectUtil
三级联动
首先感谢这两个作者
https://github.com/venshine/WheelView https://github.com/wulianghuan/Cascade_Master
这个效果我只是搬运工,整合了这两个作者的东西,弄出来的,也没啥好说的,就是一个popupwin,后面我会放源码,大家自行下载观看(不要积分,给个start就行)
recyclerview首字母悬浮效果
思路主要分为三点:
1、首先拿到数据的拼音的首字母,排序
2、在adapter里面检查首字母第一次出现的位置,从而控制显示隐藏
3、首字母出现的位置设置tag,跟主页面的字母进行动画替换(重点)
4、点击侧边的字母进行联动
我们先通过 android源码的HanziToPinyin这个类,把我们的数据转成拼音,然后截取首字母
/**
* 比较器,比较拼音的首字母
*/
public class PinYinComparator implements Comparator<PinYinComparator.CityBean> {
@Override
public int compare(CityBean lhs, CityBean rhs) {
return lhs.getSortLetter().compareTo(rhs.getSortLetter());
}
/**
* 实体类,用来存储,汉字,和对应的首字母的拼音
*/
public static class CityBean {
private String name;
private String sortLetter;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSortLetter() {
return sortLetter;
}
public void setSortLetter(String sortLetter) {
this.sortLetter = sortLetter;
}
}
/**
* 汉字转拼音
* @param input 传入的汉字
* @return
*/
public static String getPinYin(String input) {
ArrayList tokens = HanziToPinyin.getInstance().get(input);
StringBuilder sb = new StringBuilder();
if (tokens != null && tokens.size() > 0) {
Iterator iterator = tokens.iterator();
while (iterator.hasNext()) {
HanziToPinyin.Token token = (HanziToPinyin.Token) iterator.next();
if (2 == token.type) {
sb.append(token.target);
} else {
sb.append(token.source);
}
}
}
return sb.toString().toUpperCase();
}
} 后面拿到数据,循环调用上面的getPinYin就能得到字母,然后截取第一个,在存到上面的实体类里面,然后使用比较器进行排序Collections.sort(mCityList,
new
PinYinComparator());
到这里我们的第一步就搞定了。
下面我们来看,控制首字母的显示和隐藏,我们来看adapter的onBindViewHolder
方法,我们先拿到实体类,然后拿首字母,通过getPositionForSelect得到这个字母在排序中的位置,而我们的recyclerview的position到达这个位置时就显示首字母和设置tag,否则的话就隐藏,这里设置tag是为了下一步的进行。
PinYinComparator.CityBean info = mData.get(position);
holder.name.setText(info.getName());
char selection = info.getSortLetter().charAt(0);
int letterPosition = getPositionForSelection(selection);
if (letterPosition == position) {
holder.letter_tv.setText(info.getSortLetter());
holder.letter_tv.setVisibility(View.VISIBLE);
holder.itemView.setTag(HAS_STICKY_VIEW);
} else {
holder.letter_tv.setVisibility(View.GONE);
holder.itemView.setTag(NONE_STICKY_VIEW);
} 动画替换
在主页面,我们用一个和字母一样的布局跟recyclerview嵌套在一起,其实那个悬浮头就是在主页面里的布局,
而不是item的那个字母头,我们只是监听滑动,到了我们上面设置tag的地方,就让他滑动他自身的高度,就是下面的
mLetterText
{
View letterView = mRecyclerView.findChildViewUnder(mLetterText.getMeasuredWidth() / 2, 3);
if (letterView != null && letterView.getContentDescription() != null) {
mLetterText.setText(String.valueOf(letterView.getContentDescription()));
}
View recyclerItem = mRecyclerView.findChildViewUnder(mLetterText.getMeasuredWidth() / 2,
mLetterText.getMeasuredHeight() + 1);
if (recyclerItem != null && recyclerItem.getTag() != null) {
//这个recycleritem其实是和mLetterText一样的
//但是滑动recyclerview他的top会改变,此时,我们就让mLetterText跟着改变
int deltaY = recyclerItem.getTop() - mLetterText.getMeasuredHeight();
if ((int) recyclerItem.getTag() == mCityAdapter.HAS_STICKY_VIEW) {
if (recyclerItem.getTop() > 0) {
mLetterText.setTranslationY(deltaY);
} else {
mLetterText.setTranslationY(0);
}
} else if ((int) recyclerItem.getTag() == mCityAdapter.NONE_STICKY_VIEW) {
mLetterText.setTranslationY(0);
}
}
}
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); letterScroll(); } });
绘制导航字母条
这里难度不大,只是我们绘制的时候要知道,每个字母的x和y坐标应该怎么定,y坐标是计算空件自身的高度,然后除于27(还有一个#)
这样就得到每个字母的y坐标了,x就是控件自身的宽度的一般减去字母的宽度的一半。如何知道我们点击了哪个字母呢?
看下我们的公式就明白了:点击的字母/27=点击的y坐标/总高度
而我们求:点击的字母=(27*点击的y坐标)/总高度
/**
* 字母导航控件
*/
public class NavigationView extends View {
private Paint mPaint;
private String[] mDate = new String[]{"A", "B", "C", "D", "E", "F",
"G", "H", "I", "J", "K", "L", "N", "M", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
private int position = -1;
private int mHeight;
public NavigationView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(23);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
public NavigationView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mHeight = getHeight();
int width = getWidth();
int simpleHeight = mHeight / mDate.length;
for (int i = 0; i < mDate.length; i++) {
mPaint.setColor(Color.BLUE);
if (i == position) {
mPaint.setColor(Color.RED);
}
float x = (width - mPaint.measureText(mDate[i])) / 2.0f;
float y = simpleHeight * (i + 1);
canvas.drawText(mDate[i], x, y, mPaint);
}
}
@SuppressLint("NewApi")
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
int oldPosition = position;
int c = (y * mDate.length) / mHeight;
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
setBackground(new ColorDrawable(0));
if (mDialog != null) {
mDialog.setVisibility(View.GONE);
}
position = -1;
break;
default:
setBackgroundColor(Color.parseColor("#EEE5DE"));
if (c >= 0 && c < mDate.length && c != oldPosition) {
if (mOnTouchItemListener != null) {
mOnTouchItemListener.onTouch(mDate[c]);
Log.e("------", "onTouchEvent: "+mDate[c] );
}
if (mDialog != null) {
mDialog.setText(mDate[c]);
mDialog.setVisibility(View.VISIBLE);
}
}
position = c;
invalidate();
break;
}
return true;
}
private TextView mDialog;
public void setDialog(TextView dialog) {
mDialog = dialog;
}
private OnTouchItemListener mOnTouchItemListener;
public void setOnTouchItemListener(OnTouchItemListener onTouchItemListener) {
mOnTouchItemListener = onTouchItemListener;
}
public interface OnTouchItemListener {
void onTouch(String var1);
}
}大功告成,github地址:https://github.com/WoBuShuo/SelectUtil
相关文章推荐
- 安卓学习笔记---android RecyclerView首字母悬浮在顶部,滑动删除
- RecyclerView 实现省市区三级联动
- 【Android - 控件】之可悬浮列表StickyHeadersRecyclerView
- android RecyclerView首字母悬浮在顶部,滑动删除
- android RecyclerView首字母悬浮在顶部,滑动删除
- 加载本地Xml文件实现省市区三级联动PopupWindows+ RecyclerView
- 基于github 开源框架Android-PickerView-master实现省市三级联动
- 【Android - 框架】之可悬浮列表StickyHeadersRecyclerView
- Android实现三级联动下拉框 下拉列表spinner的实例代码
- Android_全国省市区-三级联动 时间选择器
- android通讯录列表,A~Z字母提示view
- Android-->RecyclerView分组悬浮标题(分割线)
- RecyclerView分组悬浮列表
- Android 仿联系人菜单,带字母索引,顶部挤压动画,recyclerview实现联系人页面
- Android RecyclerView实现下拉列表功能
- Android创建自定义视图列表对话框(数据库中的数据作为数据源,使用RecyclerView作为列表)
- Android自定义View——实现联系人列表字母索引
- Android客户端之“微服私访”App的系统学习(七)XRecyclerView快速实现列表界面+自定义Search输入框,软键盘搜索按钮监听+TextView部分样式改变
- Android实现三级联动下拉框 下拉列表spinner
- Android 省市县 三级联动(android-wheel的使用)