使用ListView实现滚筒选择器效果

news/2024/12/15 11:55:28/

转载请注明出处http://blog.csdn.net/u011453163/article/details/52960329

Android和ios应用开发虽然大同小异,但是对于原生sdk提供的组件来说,ios要相对美观点,但是Android 的组件也是可以高度自定义的,基本上ios有的Android都能自定义达到相同的效果。
今天通过对listview做一点点小修改实现一个wheelview的效果(滚筒选择器) 虽然网上已经有很多这样的效果,但有时候我只想实现一个比较简单的效果并不想去引入太多的类。。
先看效果图
这里写图片描述

这个选择器效果我只是在原来的listview上做了一些小修改,也踩了一些坑。
有两个点

1.数据循环   
2.滑动后的回弹居中

第一点我用的是取余的方法,这个在循环的viewpager里应该很多人都用过了。

第二点回弹居中的效果 我用的是属性动画(ValueAnimator)而没用Scroller

关于第一点就不多说了,处理适配器的两个方法就可以了

  @Overridepublic int getCount() {return datas!=null?2000:0;}@Overridepublic String getItem(int position) {return datas!=null?datas.get(position%datas.size()):null;}
关于第二点回弹居中的效果
回弹居中效果,虽然listview有提供好几个平滑滚动的方法 
smoothScrollToPosition(int position)
smoothScrollByOffset(int offset) 基本上带smooth的方法都是带有平滑效果的,但是都不是很理想,都有不能被接受的准确性,就是偏移了。
但是有一个方法是非常准确的
@Overridepublic void setSelection(int position) {setSelectionFromTop(position, 0);}

这个方法一点也不陌生,就是滚到指定位置的。虽然不知道为什么这个不会偏差,然后找到里面的

 public void setSelectionFromTop(int position, int y)

很好,这个方法是可以直接用的。这个方法的效果是 滚动到指定的位置 偏移头的量,setSelectionFromTop(position, 0),就是setSelection(int position);
所以想到利用这个偏移量来达到回弹居中的效果 想法大概是这样的
这里写图片描述

因为listview的复用 ,所以保证listview的高是item的奇数倍数就好了,所以只要监听listview的滚动就可以了

@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if(scrollState==SCROLL_STATE_IDLE){if(view instanceof ListView){View v = view.getChildAt(0);int position= view.getFirstVisiblePosition();if(-v.getTop()>v.getHeight()/2){ScrollAnim((ListView) view,position, v.getTop(),-v.getHeight());selectPosition=position+1;}else {ScrollAnim((ListView) view,position, v.getTop(),0);selectPosition=position;}}}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {if(view instanceof ListView){for (int i = 0; i < view.getChildCount(); i++) {View v=view.getChildAt(i);if(v instanceof TextView){if(v.getY()+v.getHeight()/2>view.getHeight()/3&&v.getY()+v.getHeight()/2<view.getHeight()/3*2){((TextView) v).setTextColor(selectColor);((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP,selectTextSize);}else {((TextView) v).setTextColor(defColor);((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP,defTextSize);}}}}}

onScrollStateChanged里做的事是在滑动停止以后做回弹居中的效果
onScroll里是做了滑动过程中的一些选中变化,这里是做了字体颜色和大小的变化。

if(scrollState==SCROLL_STATE_IDLE){if(view instanceof ListView){View v = view.getChildAt(0);int position= view.getFirstVisiblePosition();if(-v.getTop()>v.getHeight()/2){ScrollAnim((ListView) view,position, v.getTop(),-v.getHeight());selectPosition=position+1;}else {ScrollAnim((ListView) view,position, v.getTop(),0);selectPosition=position;}}}

停止以后 计算第一个显示的item的偏移量 以决定是向上滚动或者向下滚动,平滑滚动是用的属性动画api ValueAnimator

 private void ScrollAnim(final ListView v, final int position, int y1, int y2){ValueAnimator valueAnimator= ValueAnimator.ofInt(y1,y2);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {v.setSelectionFromTop(position,((Integer) animation.getAnimatedValue()).intValue());}});valueAnimator.setDuration(150);valueAnimator.start();}

这里就是用到了setSelectionFromTop(position,y)这个方法;

最后是划线的,上下蒙层效果

 @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawLine(20,getHeight()/3,getWidth()-20,getHeight()/3,paintLine);canvas.drawLine(20,getHeight()/3*2,getWidth()-20,getHeight()/3*2,paintLine);}@Overridepublic void draw(Canvas canvas) {initFirst();canvas.saveLayer(0,0,this.getWidth(),this.getHeight(),null,Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);super.draw(canvas);paintShader.setShader(shaderTop);canvas.drawRect(0, 0, this.getWidth(), 100,paintShader);paintShader.setShader(shaderButtom);canvas.drawRect(0, this.getHeight()-100,this.getWidth(), this.getHeight(),paintShader);}

详细的看代码。

package com.weizhenbin.show.widget;import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.TextView;/*** Created by weizhenbin on 2016/10/26.*/
public class WheelListView extends ListView implements AbsListView.OnScrollListener {private Paint paintLine,paintShader;private int selectColor= Color.BLUE;//选择字体颜色private int defColor= Color.BLACK;//默认字体颜色private int selectTextSize=20;//选择字体大小  单位spprivate int defTextSize=15;//默认字体大小  单位spprivate LinearGradient shaderTop;private LinearGradient shaderButtom;private boolean hasInit=false;public int selectPosition;public WheelListView(Context context) {this(context,null);}public WheelListView(Context context, AttributeSet attrs) {this(context, attrs,0);}public WheelListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setOnScrollListener(this);paintLine=new Paint();paintLine.setStrokeWidth(2);paintLine.setColor(selectColor);}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if(scrollState==SCROLL_STATE_IDLE){if(view instanceof ListView){View v = view.getChildAt(0);int position= view.getFirstVisiblePosition();if(-v.getTop()>v.getHeight()/2){ScrollAnim((ListView) view,position, v.getTop(),-v.getHeight());selectPosition=position+1;}else {ScrollAnim((ListView) view,position, v.getTop(),0);selectPosition=position;}}}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {if(view instanceof ListView){for (int i = 0; i < view.getChildCount(); i++) {View v=view.getChildAt(i);if(v instanceof TextView){if(v.getY()+v.getHeight()/2>view.getHeight()/3&&v.getY()+v.getHeight()/2<view.getHeight()/3*2){((TextView) v).setTextColor(selectColor);((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP,selectTextSize);}else {((TextView) v).setTextColor(defColor);((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP,defTextSize);}}}}}private void initFirst() {if(!hasInit){paintShader =new Paint();paintShader.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));shaderTop=new LinearGradient(0, 0, 0, 100, 0xFF000000, 0,Shader.TileMode.CLAMP);shaderButtom=new LinearGradient(0, this.getHeight()-100, 0, this.getHeight(), 0, 0xFF000000,Shader.TileMode.CLAMP);hasInit=true;}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawLine(20,getHeight()/3,getWidth()-20,getHeight()/3,paintLine);canvas.drawLine(20,getHeight()/3*2,getWidth()-20,getHeight()/3*2,paintLine);}@Overridepublic void draw(Canvas canvas) {initFirst();canvas.saveLayer(0,0,this.getWidth(),this.getHeight(),null,Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);super.draw(canvas);paintShader.setShader(shaderTop);canvas.drawRect(0, 0, this.getWidth(), 100,paintShader);paintShader.setShader(shaderButtom);canvas.drawRect(0, this.getHeight()-100,this.getWidth(), this.getHeight(),paintShader);}/*** 平滑滚动* */private void ScrollAnim(final ListView v, final int position, int y1, int y2){ValueAnimator valueAnimator= ValueAnimator.ofInt(y1,y2);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {v.setSelectionFromTop(position,((Integer) animation.getAnimatedValue()).intValue());}});valueAnimator.setDuration(150);valueAnimator.start();}public void setSelectColor(int selectColor) {this.selectColor = selectColor;}public void setDefColor(int defColor) {this.defColor = defColor;}public void setSelectTextSize(int selectTextSize) {this.selectTextSize = selectTextSize;}public void setDefTextSize(int defTextSize) {this.defTextSize = defTextSize;}
}

好到此就分享完了,这里只是给一个思路而已,如果有幸被使用,注意的是 WheelListView的高度是item的三倍最好,还没很完善的做好适配。


http://www.ppmy.cn/news/376703.html

相关文章

css透明喷漆,纯CSS实现的油漆滚筒

CSS 语言: CSSSCSS 确定 body {margin: 0; padding: 0; } .container {position: absolute; top: 0; left: 50%; transform: translateX(-50%); } .paint {position: relative; width: 100px; height: 150px; background: #FB9B9C; } .paint:before {display: block; content:…

2022年全球市场滚筒筛总体规模、主要生产商、主要地区、产品和应用细分研究报告

本文研究全球市场、主要地区和主要国家滚筒筛的销量、销售收入等&#xff0c;同时也重点分析全球范围内主要厂商&#xff08;品牌&#xff09;竞争态势&#xff0c;滚筒筛销量、价格、收入和市场份额等。全球市场主要滚筒筛生产商包括Erimaki、Heilig Mixing Technology、Allga…

如何保证数据库分布式事务的强一致性

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 针对分布式数据库&#xff0c;如何保证分布式事务的强一致性&#xff0c;是分布式数据库的关键。分布式事务的强一致性方案这里介绍两种&#xff0c;一种是GTM(global transaction manager),另一种是基于XA协议的两阶…

腾讯安全发布“数字安全免疫力”模型框架,建设发展驱动安全新范式

随着数字化进程加快&#xff0c;企业数字化体系的边界在不断拓展&#xff0c;安全风险和挑战不断增加&#xff0c;传统被动防御的安全应对常显疲态&#xff0c;数字安全时代亟待建立全新的安全范式。 6月13日&#xff0c;腾讯安全联合IDC在北京发布“数字安全免疫力”模型框架…

【C语言】VScode中配置C语言/C++运行环境(保姆级图文)

目录 省流助手1. 下载安装VScode2. 下载编译器MinGW并解压3. 将MinGW添加至环境变量4. 安装vscode的插件5. 运行代码6. 调整和优化&#xff08;这部分转自零流火星动力猿 2022.4.12&#xff09;总结 欢迎关注 『C语言』 系列&#xff0c;持续更新中 欢迎关注 『C语言』 系列&am…

微星主板更新BIOS能识别U盘但读取不到BIOS文件

记录一次BIOS的更新问题&#xff0c;问题比较尴尬。 本来是更新驱动想着顺便把BIOS也更新一下&#xff0c;就去微星官网下载了BIOS文件&#xff0c;将文件解压到U盘后重启按delete进入BIOS用M-FLASH更新&#xff0c;自动重启后进入U盘选文件界面。 这时候问题来了&#xff0c…

bios 微星click_微星主板CLICK BIOS II BIOS设置软件下载_微星主板CLICK BIOS II BIOS设置软件官方下载-太平洋下载中心...

微星科技独家ClickBIOS II&#xff0c;不但是全球第一个整合UEFI BIOS跟Windows应用程式的系统工具&#xff0c;可以分别在不同的环境下&#xff0c;透过滑鼠甚至是触控面板来调校系统设定&#xff0c;相对于往常产品只能提供UEFI BIOS或者Windows应用程式&#xff0c;ClickBIO…

十代主板改win7_微星(MSI)z490主板装win7系统及bios设置教程(支持10代usb驱动)

[文章导读]我们知道自从z490主板发布后,有很多使用微星主板的网友问,微星z490主板其搭载intel 酷睿10代cpu可以安装安装win7吗?微星z490主板预装的是win10系统,用户还是喜欢win7系统,该微星z490主板可以采用的第十代酷睿i5-10400 CPU安装win7,在安装WIN7过程中USB设备不能…