当前位置: 首页 > 编程日记 > 正文

[纪录]仿IOS滚轮效果(竖直滑动选择器)

今天想做一个类似这样的一个效果,可是UI的模板是参考IOS做的,于是就各种百度各种搜,最后让我找到了一个仿IOS滚轮的一个Demo,稍微研究了一下,发上来,大家一起学习,以后也方便我查看,就不用再去百度了,嘿嘿!

仿IOS滚轮效果

首先是一个类,继承了ScrollView

public class WheelView extends ScrollView {public static final String TAG = WheelView.class.getSimpleName();public static class OnWheelViewListener {public void onSelected(int selectedIndex, String item) {}
}private Context context;private LinearLayout views;public WheelView(Context context) {super(context);init(context);
}public WheelView(Context context, AttributeSet attrs) {super(context, attrs);init(context);
}public WheelView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);
}//    String[] items;
List<String> items;private List<String> getItems() {return items;
}public void setItems(List<String> list) {if (null == items) {items = new ArrayList<String>();}items.clear();items.addAll(list);// 前面和后面补全for (int i = 0; i < offset; i++) {items.add(0, "");items.add("");}initData();}public static final int OFF_SET_DEFAULT = 1;
int offset = OFF_SET_DEFAULT; // 偏移量(需要在最前面和最后面补全)public int getOffset() {return offset;
}public void setOffset(int offset) {this.offset = offset;
}int displayItemCount; // 每页显示的数量int selectedIndex = 1;private void init(Context context) {this.context = context;Log.d(TAG, "parent: " + this.getParent());this.setVerticalScrollBarEnabled(false);views = new LinearLayout(context);views.setOrientation(LinearLayout.VERTICAL);this.addView(views);scrollerTask = new Runnable() {public void run() {int newY = getScrollY();if (initialY - newY == 0) { // stoppedfinal int remainder = initialY % itemHeight;final int divided = initialY / itemHeight;if (remainder == 0) {selectedIndex = divided + offset;onSeletedCallBack();} else {if (remainder > itemHeight / 2) {WheelView.this.post(new Runnable() {@Overridepublic void run() {WheelView.this.smoothScrollTo(0, initialY - remainder + itemHeight);selectedIndex = divided + offset + 1;onSeletedCallBack();}});} else {WheelView.this.post(new Runnable() {@Overridepublic void run() {WheelView.this.smoothScrollTo(0, initialY - remainder);selectedIndex = divided + offset;onSeletedCallBack();}});}}} else {initialY = getScrollY();WheelView.this.postDelayed(scrollerTask, newCheck);}}};}int initialY;Runnable scrollerTask;
int newCheck = 50;public void startScrollerTask() {initialY = getScrollY();this.postDelayed(scrollerTask, newCheck);
}private void initData() {displayItemCount = offset * 2 + 1;for (String item : items) {views.addView(createView(item));}refreshItemView(0);
}int itemHeight = 0;
/*** 这里可以设置字体的属性 大小啦,边距啦,什么东西都可以在这里设置;*/
private TextView createView(String item) {TextView tv = new TextView(context);tv.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));tv.setSingleLine(true);// 设置字体大小为20sptv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);// 设置文字内容
    tv.setText(item);// 设置文字居中
    tv.setGravity(Gravity.CENTER);// 设置内边距int padding = dip2px(15);tv.setPadding(padding, padding, padding, padding);if (0 == itemHeight) {itemHeight = getViewMeasuredHeight(tv);Log.d(TAG, "itemHeight: " + itemHeight);views.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight * displayItemCount));LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) this.getLayoutParams();this.setLayoutParams(new LinearLayout.LayoutParams(lp.width, itemHeight * displayItemCount));}return tv;
}@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);refreshItemView(t);if (t > oldt) {Log.d(TAG, "向下滚动");scrollDirection = SCROLL_DIRECTION_DOWN;} else {Log.d(TAG, "向上滚动");scrollDirection = SCROLL_DIRECTION_UP;}}private void refreshItemView(int y) {int position = y / itemHeight + offset;int remainder = y % itemHeight;int divided = y / itemHeight;if (remainder == 0) {position = divided + offset;} else {if (remainder > itemHeight / 2) {position = divided + offset + 1;}}int childSize = views.getChildCount();for (int i = 0; i < childSize; i++) {TextView itemView = (TextView) views.getChildAt(i);if (null == itemView) {return;}if (position == i) {itemView.setTextColor(Color.parseColor("#0288ce"));} else {itemView.setTextColor(Color.parseColor("#bbbbbb"));}}
}/*** 获取选中区域的边界*/
int[] selectedAreaBorder;private int[] obtainSelectedAreaBorder() {if (null == selectedAreaBorder) {selectedAreaBorder = new int[2];selectedAreaBorder[0] = itemHeight * offset;selectedAreaBorder[1] = itemHeight * (offset + 1);}return selectedAreaBorder;
}private int scrollDirection = -1;
private static final int SCROLL_DIRECTION_UP = 0;
private static final int SCROLL_DIRECTION_DOWN = 1;Paint paint;
int viewWidth;@Override
public void setBackgroundDrawable(Drawable background) {if (viewWidth == 0) {viewWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();Log.d(TAG, "viewWidth: " + viewWidth);}if (null == paint) {paint = new Paint();paint.setColor(Color.parseColor("#83cde6"));paint.setStrokeWidth(dip2px(1f));}background = new Drawable() {@Overridepublic void draw(Canvas canvas) {canvas.drawLine(viewWidth * 1 / 6, obtainSelectedAreaBorder()[0], viewWidth * 5 / 6, obtainSelectedAreaBorder()[0], paint);canvas.drawLine(viewWidth * 1 / 6, obtainSelectedAreaBorder()[1], viewWidth * 5 / 6, obtainSelectedAreaBorder()[1], paint);}@Overridepublic void setAlpha(int alpha) {}@Overridepublic void setColorFilter(ColorFilter cf) {}@Overridepublic int getOpacity() {return 0;}};super.setBackgroundDrawable(background);}@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);Log.d(TAG, "w: " + w + ", h: " + h + ", oldw: " + oldw + ", oldh: " + oldh);viewWidth = w;setBackgroundDrawable(null);
}/*** 选中回调*/
private void onSeletedCallBack() {if (null != onWheelViewListener) {onWheelViewListener.onSelected(selectedIndex, items.get(selectedIndex));}}public void setSeletion(int position) {final int p = position;selectedIndex = p + offset;this.post(new Runnable() {@Overridepublic void run() {WheelView.this.smoothScrollTo(0, p * itemHeight);}});}public String getSeletedItem() {return items.get(selectedIndex);
}public int getSeletedIndex() {return selectedIndex - offset;
}@Override
public void fling(int velocityY) {super.fling(velocityY / 3);
}@Override
public boolean onTouchEvent(MotionEvent ev) {if (ev.getAction() == MotionEvent.ACTION_UP) {startScrollerTask();}return super.onTouchEvent(ev);
}private OnWheelViewListener onWheelViewListener;public OnWheelViewListener getOnWheelViewListener() {return onWheelViewListener;
}public void setOnWheelViewListener(OnWheelViewListener onWheelViewListener) {this.onWheelViewListener = onWheelViewListener;
}private int dip2px(float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);
}private int getViewMeasuredHeight(View view) {int width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);view.measure(width, expandSpec);return view.getMeasuredHeight();
}}

好的 类的源码就是这些,对于这个类 我并没有看懂,但是还是会使用的,大家什么地方也不用关注,只需要关注那个createView方法即可

之后就是我们的需要在你的xml中配置这么一段语句,就是调用这个View啦

<你的包名+WheelViewandroid:id="@+id/wv"android:layout_width="match_parent"android:layout_height="wrap_content" />

之后在关联着这个布局的java文件中findViewByID得到它

 // 初始化仿IOS滚轮效果的数据// 在这里可以设置滚轮的偏移量 mWheelView.setOffset(2);//设置每一个Item中的数据 mArrayList中装着的是一堆String字符串
        mWheelView.setItems(mArrayList);mWheelView.setOnWheelViewListener(new WheelView.OnWheelViewListener() {@Overridepublic void onSelected(int selectedIndex, String item) {//selectedIndex当前高亮的位置//item当前高亮的位置的内容
        }});

然后 这样 这个仿IOS的滚轮效果就实现了...最后附上我查阅到这个仿IOS滚轮效果的原地址

http://www.cnblogs.com/tiantianbyconan/p/3819304.html

转载于:https://www.cnblogs.com/redwolf/p/5295392.html

相关文章:

win7如何设置wifi热点_xp系统怎么设置无线网络热点(电脑设置wifi热点步骤)

现在手机基本都是可以开启wifi热点功能&#xff0c;但有时候因为各种原因&#xff0c;比如没有无线或者路由器有问题等情况&#xff0c;手机又需要使用网络&#xff0c;这个时候需要用电脑设置wifi热点。那么&#xff0c;怎么用电脑设置wifi热点呢&#xff1f;下面分别用win10系…

汇编语言第二课作业-实验1

Debug命令-摘自百度百科A 汇编命令 功能&#xff1a; 将指令直接汇编成机器码输入到内存中。说明&#xff1a; 用于小段程序的汇编及修改目标程序&#xff0c;所有输入的数字均采用十六进制&#xff0c; 用户装入内存的汇编语句是连续存放的&#xff0c;若没有指定地址&#xf…

C++、嵌入式软开之数据结构

总结&#xff1a; 1.二叉树搜索树是需要进行比较大小&#xff0c;满足传递性才可&#xff1b; 刷题总结&#xff1a; 1.&#xff08;二叉树遍历&#xff09;已知某二叉树的后序遍历序列是dabec&#xff0c;中序遍历序列是debac&#xff0c;它的前序遍历是&#xff08;&#xf…

3dsMax插件V-Ray渲染与合成学习课程 3ds Max: Rendering for Compositing in V-Ray Next

使用渲染元素&#xff0c;3ds Max的V-Ray Next对创建高质量合成所需的参数(如反射、阴影、遮罩等)提供了精细的控制。在本课程中&#xff0c;布莱恩布拉德利展示了如何在Photoshop和After Effects等应用程序中使用V-Ray Next为后期制作工作流专门创建渲染。探索渲染元素用户界面…

对找数程序的理解

经过几个小时的思考&#xff0c;总算是对老师出的这个程序题有了一定的了解。该C#程序是一个对数字进行查找的程序。程序清单如下&#xff1a; using System; using System.Collections.Generic; using System.Text; namespace FindTheNumber {  class Program  {    s…

win10鼠标灵敏度怎么调_和平精英最稳压枪灵敏度怎么调教程,适合所有段位以及适合国际版PUBG手游压枪...

和平精英(原刺激战场)主播最稳压枪灵敏度怎么调&#xff1f;不妨看看花了五个小时调试的最稳和平精英压枪灵敏度吧。废话不多&#xff0c;上图按照调。保证你满意&#xff0c;你离主播只差点意识此和平精英压枪灵敏度适合所有段位 也适合PUBG(和平精英国际版)-------分割线---…

C++基本知识点集锦(2022秋招)

&#xff08;1&#xff09;构造函数是一种特殊的类成员函数&#xff0c;是当创建一个类的对象时&#xff0c;它被调用来对类的数据成员进行初始化和分配内存。&#xff08;构造函数的命名必须和类名完全相同&#xff09; &#xff08;2&#xff09;C的空类&#xff0c;编译器会…

Sketchup插件Vray户外场景设计渲染教程 Vray Next For Sketchup Exterior

Sketchup户外场景设计的Vray Next 你会学到什么 渲染白天和夜晚场景 后期制作 Sketchup的Vray Next 中级sketchup用户 大小解压后&#xff1a;3.83G 1280X720 mp4 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 大家好&#xff0c; 我是…

实验四:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

贺邦原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的&#xff1a; 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用&#xff0c;理解系统调用的工作机制。 实验过程&#xff1a; 本文实验选择24号…

三菱plc232数据线驱动下载_三菱PLC与西门子PLC有什么区别?

三菱PLC与西门子PLC有什么区别&#xff1f;分别有什么优点和缺点&#xff1f;该如何选择&#xff1f;学习哪种品牌&#xff1f;首先它们的编程理念不同&#xff0c;三菱PLC是日系品牌&#xff0c;编程直观易懂&#xff0c;学习起来会比较轻松&#xff0c;西门子PLC是德国品牌&a…

Github 树形菜单插件

ajax显示gitlab的&#xff0c;很像mac的树形展示。 直接在左侧做了一个ajax的树&#xff0c;每次访问gitlab自动加载。非常方便呢&#xff0c;在国内网速这么慢的情况下更显得好用了。 下载地址&#xff1a; https://github.com/buunguyen/octotree/tree/master/dist chrome安装…

C/C++、嵌入式秋招之SQL篇

⭐⭐1.选取最大&#xff08;小&#xff09;值 SELECT * FROM employees order by hire_date desc limit 0,1解释&#xff1a; 知识点 ORDER BY 根据指定的列对结果集进行排序&#xff0c;默认按照升序&#xff0c;降序 ORDER BY DESCLIMIT(m, n) 从第 m 1 行开始取 n 条记录…

C4D样条曲线建模大师班 Cinema 4D MasterClass: Master Modelling using Splines

通过本课程&#xff0c;快速学习使用样条曲线建模的基础知识&#xff0c;并将您的技能提升到一个新的水平 你会学到什么 能够使用样条线对整个对象进行建模 三维建模和UV展开 能够找到模拟复杂形状的最佳方法 无数的提示和技巧 在项目中应用蓝图的真实尺寸 对Uv制图有更好的理…

从头到尾彻底解析Hash表算法

从头到尾彻底解析Hash表算法 发布时间: 2013-10-02 10:26 阅读: 25156 次 推荐: 14 原文链接 [收藏] 作者&#xff1a;July、wuliming、pkuoliver 说明&#xff1a;本文分为三部分内容&#xff0c; 第一部分为一道百度面试题Top K算法的详解&#xff1b;第二部分为关于H…

ftp windows无法访问此文件夹请确保输入的文件名_企业实战|企业FTP搭建

安装Vsftpd提前关闭selinux 和firewalld防火墙1.安装vsftp软件包 $ yum -y install vsftpd*2.启动vsftpd服务器 $ systemctl restart vsftpd $ systemctl enable vsftpd3.检查服务是否正常启动 $ ps -ef|grep vsftp && netstat -tunlp|grep 21至此 匿名用户的ft…

C++、嵌入式软开之指针

1.(指针数据)int* pa[5]; 描述: pa是一个具有5个元素的指针数组,每个元素是一个int类型的指针; 2.(二级指针)以下程序的输出结果是: #include <iostream> using namespace std; void func(char **m){++m;cout

3dsMax插件V-Ray建筑可视化三维渲染细节技术学习教程

通过学习可用于相机放置、建模、修整等的策略&#xff0c;生成令人印象深刻且逼真的建筑三维渲染。了解如何将您的3D渲染场景提升到一个新的水平&#xff0c;以使您的图像引人入胜、有趣且讨人喜欢。在本课程中&#xff0c;讲师Verena Tatiana首先讨论了不同的细节处理方法&…

所有表单对象_Laravel 表单方法伪造与 CSRF 攻击防护

1、表单方法伪造有时候&#xff0c;我们可能需要手动定义发送表单数据所使用的 HTTP 请求方式&#xff0c;而 HTML 表单仅支持 GET 和 POST 两种方式&#xff0c;如果要使用其他的方式&#xff0c;则需要自己来定义实现。HTTP 请求方式概述最常见的 HTTP 请求方式自然是 GET 和…

使用按钮控制HTML5背景音乐开关

<!DOCTYPE HTML> <html> <head> <meta charset"utf-8"> <meta name"viewport" content"widthdevice-width; initial-scale1.0"> <title>演示&#xff1a;使用按钮控制HTML5背景音乐开关</title></…

hibernate和struts2实现分页功能

1.DAO层接口的设计&#xff0c;定义一个PersonDAO接口&#xff0c;里面声明了两个方法&#xff1a; public interface PersonDAO {public List<Person> queryByPage(String hql, int offset, int pageSize);public int getAllRowCount(String hql); } 2.DAO层接口的实现类…

Cmake软件编译opencv报错,CMake Warning at cmake/OpenCVDownload.cmake:193 (message): FFMPEG: Download...

当执行如下操作时&#xff1a; 出现下面报错&#xff0c; 在链接ipaddress.com查询raw.githubusercontent.com地址&#xff0c;然后将ip添加至C:\Windows\System32\drivers\etc\hosts中&#xff1a; 保存后&#xff0c;重新在cmake软件中点击“Configure”等待即可。

Blender+SP+UE5游戏艺术工作流程学习

Blender到虚幻引擎5 Blender游戏艺术 Blender for Game Art 你会学到: 如何在Blender中创建三维模型 UV如何展开和布局 如何在Substance Painter中表现肌理 如何使用虚幻引擎5 如何在UE5中点亮室内环境 MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz&…

JQ 全选后获取选中的值_为什么在PBI中还需要切片器之三:Excel切片器之度量值切换...

Excel切片器之度量值切换原创 海峰没想到上篇文章一经发出&#xff0c;很快就过了10个留言&#xff0c;大喜过望&#xff0c;今天立马揭晓切片器之度量切换的应用。切片器之度量切换----参数法创建参数表&#xff0c;如下并导入数据模型创建需要的度量值&#xff0c;利润合计万…

layoutSubviews总结(转)

- (void)setNeedsDisplay- (void)drawRect但是是用initWithFrame 进行初始化时&#xff0c;当rect的值不为CGRectZero时,也会触发 You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want. layoutSubviews, …

PHP日期格式转时间戳

PHP 提供了函数可以方便的将各种形式的日期转换为时间戳&#xff0c;该类函数主要是&#xff1a; strtotime()&#xff1a;将任何英文文本的日期时间描述解析为时间戳。mktime()&#xff1a;从日期取得时间戳。strtotime() strtotime() 函数用于将英文文本字符串表示的日期转换…

TFmini传感器使用

使用激光传感器 打开地面站&#xff0c;Mavlink控制台输入tfmini start --> tfmini status -->显示 current_distance:数字 即可得到距离&#xff1b; 将timini插到口UART&I2C B上面 需要在自启动文件中添加tfmini的自启动&#xff0c;否则出来的数据是0&#xff1b;…

3DsMax渲染插件VRay NEXT完整的视频指南

要求 基本的计算机和三维软件知识 这门课程对初学者和进阶者都有好处 我们确实经历了许多你甚至不知道存在的功能 VRay NEXT for 3Ds Max – Complete Video Guide 欢迎来到V-RAY视频手册 流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:aac&#xff0c;44100 Hz语言…

MyEclipse中运行环境jre、编译级别、tomcat运行环境区别

运行环境JRE SYSTEM LIARARY引入项目中依赖的jdk基础包&#xff0c;在java build path --》library中可以切换 编译级别是项目编译成.class时使用的编译jdk版本&#xff0c;只能向下编译 tomcat运行环境选择jdk版本&#xff0c; 以上三个配置最好一致&#xff0c;如果不一致可以…

食堂就餐刷卡系统源码_智慧食堂重新定义你的食堂管理系统

智慧食堂有着针对于多种业态的适用行解决方案&#xff0c;可以说几乎是满足了所有团餐食堂&#xff0c;从进销存管理到财务系统再到智能硬件&#xff0c;让对食堂有着传统麻木观念的人群有了耳目一新的变化&#xff0c;下面就跟大家说几个智能硬件亮点&#xff0c;从新帮你定义…

2022-2028年全球与中国闪光棉市场研究及前瞻分析报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了全球与中国闪光棉行业市场行业相关概述、全球与中国闪光棉行业市场行业运行环境、分析了全球与…