Android 实现 WheelView
我们都知道,在iOS里面有一种控件------滚筒控件(Wheel View),这通常用于设置时间/日期,非常方便,但Android SDK并没有提供类似的控件。这里介绍一下如何Android实现WheelView。
先来看一看iOS中的WheelView的效果图:
这个效果不错吧,我们应该如何实现呢?
那在Android如果也要实现这样一个效果,应该怎么做呢?
1.Android WheelView效果图
2.网上的开源代码
我们从网上找到了一个开源的代码,它也实现了这样的效果,而且效果也不错,大家可以用SVN来checkout:
http://android-wheel.googlecode.com/svn/trunk
它这个Demo最本质是自己写布局,好像是利用一个LinearLayout来布局child,然后调用LinearLayout.draw(canvas)方法,把child绘制在指定的canvas上面。它同时还提供了类似AdapterView的访问方式,用户可以设置Adapter来提供数据。我在这里主要不是讲解这个Demo的结构,如果大家感兴趣,可以自己下载代码研究。
3.实现思路
由于我之前修改过Gallery的源代码,可以使其循环滚动,并且第一个child可以排列在最左端,所以,我在想,如果我能把Gallery修改成竖的(垂直排列),那这个不就是OK了吗?基于这样的想法,我就准备修改代码了。
我们这里需要把Gallery的源码复制到我们的工程中,然后修改,保证能编译通过。
与Gallery相关的的几个文件如下所示,它们都是放在widget文件夹和res/value文件夹下面。
- AbsSpinner.java
- AdapterView.java
- Gallery.java
- attr.xml
修改的过程比较麻烦,我这里不详细说明(要细说的话,内容太多了),在修改之后,我们的Gallery提供了一个方法:setOrientation(int),你可以让这个Gallery水平滑动,也可以垂直滑动。
我们还应该提供以下几个核心方法:
- setOnEndFlingListener ------ 当Gallery停止滑动时的回调用,这样调用者可以在停止滑动时来得到当前选中的项。
- setOrientation(int) ------ 支持布局方向:HORIZONTAL和VERTICAL。
- setScrollCycle(boolean) ------ 是否支持循环滑动。
- setSlotInCenter(boolean) ------ 是否让Gallery选中的项居中。
4. 扩展Gallery
- package com.nj1s.lib.widget;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Rect;
- import android.graphics.drawable.Drawable;
- import android.graphics.drawable.GradientDrawable;
- import android.graphics.drawable.GradientDrawable.Orientation;
- import android.util.AttributeSet;
- import android.view.Gravity;
- import android.view.View;
- import com.nj1s.lib.R;
- public class WheelView extends TosGallery
- {
- private Drawable mSelectorDrawable = null;
- private Rect mSelectorBound = new Rect();
- private GradientDrawable mTopShadow = null;
- private GradientDrawable mBottomShadow = null;
- private static final int[] SHADOWS_COLORS =
- {
- 0xFF111111,
- 0x00AAAAAA,
- 0x00AAAAAA
- };
- public WheelView(Context context)
- {
- super(context);
- initialize(context);
- }
- public WheelView(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- initialize(context);
- }
- public WheelView(Context context, AttributeSet attrs, int defStyle)
- {
- super(context, attrs, defStyle);
- initialize(context);
- }
- private void initialize(Context context)
- {
- this.setVerticalScrollBarEnabled(false);
- this.setSlotInCenter(true);
- this.setOrientation(TosGallery.VERTICAL);
- this.setGravity(Gravity.CENTER_HORIZONTAL);
- this.setUnselectedAlpha(1.0f);
- // This lead the onDraw() will be called.
- this.setWillNotDraw(false);
- // The selector rectangle drawable.
- this.mSelectorDrawable =
- getContext().getResources().getDrawable(R.drawable.wheel_val);
- this.mTopShadow =
- new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
- this.mBottomShadow =
- new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
- // The default background.
- this.setBackgroundResource(R.drawable.wheel_bg);
- }
- @Override
- protected void dispatchDraw(Canvas canvas)
- {
- super.dispatchDraw(canvas);
- // After draw child, we do the following things:
- // +1, Draw the center rectangle.
- // +2, Draw the shadows on the top and bottom.
- drawCenterRect(canvas);
- drawShadows(canvas);
- }
- /**
- * setOrientation
- */
- @Override
- public void setOrientation(int orientation)
- {
- if (TosGallery.HORIZONTAL == orientation)
- {
- throw new IllegalArgumentException("The orientation must be VERTICAL");
- }
- super.setOrientation(orientation);
- }
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b)
- {
- super.onLayout(changed, l, t, r, b);
- int galleryCenter = getCenterOfGallery();
- View v = this.getChildAt(0);
- int height = (null != v) ? v.getMeasuredHeight() : 50;
- int top = galleryCenter - height / 2;
- int bottom = top + height;
- mSelectorBound.set(
- getPaddingLeft(),
- top,
- getWidth() - getPaddingRight(),
- bottom);
- }
- private void drawCenterRect(Canvas canvas)
- {
- if (null != mSelectorDrawable)
- {
- mSelectorDrawable.setBounds(mSelectorBound);
- mSelectorDrawable.draw(canvas);
- }
- }
- private void drawShadows(Canvas canvas)
- {
- int height = (int)(2.0 * mSelectorBound.height());
- mTopShadow.setBounds(0, 0, getWidth(), height);
- mTopShadow.draw(canvas);
- mBottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());
- mBottomShadow.draw(canvas);
- }
- }
上面代码没有什么特别的东西,只是有几点需要注意:
5. 如何使用
- // 设置listener
- mDateWheel.setOnEndFlingListener(mListener);
- // 设置滑动时的声音
- mDateWheel.setSoundEffectsEnabled(true);
- // 设置adapter
- mDateWheel.setAdapter(new WheelTextAdapter(this));
- // Adapter的实现
- protected class WheelTextAdapter extends BaseAdapter
- {
- ArrayList<TextInfo> mData = null;
- int mWidth = ViewGroup.LayoutParams.MATCH_PARENT;
- int mHeight = 50;
- Context mContext = null;
- public WheelTextAdapter(Context context)
- {
- mContext = context;
- }
- public void setData(ArrayList<TextInfo> data)
- {
- mData = data;
- this.notifyDataSetChanged();
- }
- public void setItemSize(int width, int height)
- {
- mWidth = width;
- mHeight = height;
- }
- @Override
- public int getCount()
- {
- return (null != mData) ? mData.size() : 0;
- }
- @Override
- public Object getItem(int position)
- {
- return null;
- }
- @Override
- public long getItemId(int position)
- {
- return 0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent)
- {
- TextView textView = null;
- if (null == convertView)
- {
- convertView = new TextView(mContext);
- convertView.setLayoutParams(new TosGallery.LayoutParams(mWidth, mHeight));
- textView = (TextView)convertView;
- textView.setGravity(Gravity.CENTER);
- textView.setTextSize(26);
- textView.setTextColor(Color.BLACK);
- }
- if (null == textView)
- {
- textView = (TextView)convertView;
- }
- TextInfo info = mData.get(position);
- textView.setText(info.mText);
- textView.setTextColor(info.mColor);
- return convertView;
- }
- }
Android 实现 WheelView的更多相关文章
- android: WheelView组件(滑轮组件)的应用!
android前段组件中, 填表单,选择条目 的样式有很多, WheelView滚动组件为其中一种,如下图所示: 前两 ...
- 揭破android中的闹钟app 二
· 这节,我们通过wheelview来模仿一个简易的正点闹钟. 我这里不说wheelview来龙去脉,只阐述几个简单的方法,如果,想看一看具体wheelview的内容,请看下面两篇文章: androi ...
- android 时间控件概述
android的自带时间选择控件,是一个让用户既能输入的又能选择的样子.这本来没有太大的问题了. 但是,坑爹的android是开源的.自带的时间控件在某些机型上,早已经是面目全非了,在用以一个普通用户 ...
- VLC For Android Ubuntu14.04编译环境搭建
VLC多媒体播放器(英语:VLC media player,最初为VideoLAN Client.是VideoLAN计划的开放源码多媒体播放器.)支持众多音频与视频解码器及文件格式,并支持DVD影音光 ...
- 7.Android开源项目WheelView的时间和地址联动选择对话框
类似WheelView的时间和地址联动选择对话框在现在App经常看到,今天小结下. 主布局界面: <LinearLayout xmlns:android="http://schemas ...
- 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件
博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...
- Android自己定义实现循环滚轮控件WheelView
首先呈上效果图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/d ...
- [Android]竖直滑动选择器WheelView的实现
以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3819304.html 公司项目中有这么一个需求,所以需要自己实现下.效 ...
- android wheelview实现三级城市选择
很早之前看淘宝就有了ios那种的城市选择控件,当时也看到网友有分享,不过那个写的很烂,后来(大概是去年吧),我们公司有这么一个项目,当时用的还是网上比较流行的那个黑框的那个,感觉特别的丑,然后我在那个 ...
随机推荐
- Oracle EBS OPM convert dtl reservation
--convert_dtl_reservation --created by jenrry DECLARE l_reservation_rec mtl_reservations%ROWTYPE; l_ ...
- Oracle EBS SLA取值
-- 从GL总账追溯到 => 子分类账SLA => 子模块AP.AR等 SELECT xep.name, -- 法人主体 xep.legal_entity_identifier, -- 法 ...
- jmeter函数简介
1._char:把一组数字转化成Unicode字符. 2._counter:记录线程的迭代次数. 3._CSVRead:可以从文件中指定列的值. 4.${_CSVRead(D:\test.txt,0, ...
- Jmeter之HTTP Cookie 管理器
Jmeter所支持的Cookie标准有很多,同时jmeter也提供两组程序实现这些cookie标准,分别是httpclient3与httpclient4.http cookie 管理器中的Implem ...
- 【Linq】常用语法汇总
语言继承查询(Language Integrated Query, LINQ),在C#编程语言中集成了查询语法,可以用相同的语法访问不同的数据源,LINQ提供了不同数据源的抽象层,所以可以使用相同语法 ...
- Linux之添加交换分区
Linux下的交换分区我们可以随意改变大小,如果说日常生活中分区不够用,今天我们来举个例子如何添加. 1.首先是使用dd命令创建一个空文件,这个空文件的大小就是你要继续添加的swap的大小,比如我这里 ...
- 安装和配置Apache服务器(下)
Apache的配置文档:http://httpd.apache.org/docs/current/. 1.监听端口: 默认的端口号为80端口,如果端口号冲突改为8080端口. 注:每改一次httpd. ...
- Java AWT
AWT是抽象窗口工具包,是API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,AWT可用于Java的applet和applications中. ...
- 《面向对象程序设计》c++第六次作业___calculator SE
c++第五次作业 Calculator SE 代码 PS:这次作业延迟了很久,人要是迷茫啊----唉------ 新增GUI界面,使用Qt creator编写,纯代码生成控件.写坐标. 感觉Qt cr ...
- NOIP模板总结
NOIP模板总结 进考场先打一份缺省源: # include <cstdio> # include <iostream> # include <cstring> # ...