Android Gallary扩展实现 WheelView(Gallary竖着滑实现时间现实)

来源:互联网 发布:都秀多人视频聊天软件 编辑:程序博客网 时间:2024/05/21 07:51
整理+源码实现
我们都知道,在iOS里面有一种控件------滚筒控件(Wheel View),这通常用于设置时间/日期,非常方便,但Android SDK并没有提供类似的控件。这里介绍一下如何Android实现WheelView。
源码下载:http://download.csdn.net/detail/heng615975867/6521189

先来看一看iOS中的WheelView的效果图:


这个效果不错吧,我们应该如何实现呢?

那在Android如果也要实现这样一个效果,应该怎么做呢?

1.Android WheelView效果图


上图是我实现的DEMO的运行效果图。


2.网上的开源代码

我们从网上找到了一个开源的代码,它也实现了这样的效果,而且效果也不错,大家可以用SVN来checkout:

http://android-wheel.googlecode.com/svn/trunk

它这个Demo最本质是自己写布局,好像是利用一个LinearLayout来布局child,然后调用LinearLayout.draw(canvas)方法,把child绘制在指定的canvas上面。它同时还提供了类似AdapterView的访问方式,用户可以设置Adapter来提供数据。我在这里主要不是讲解这个Demo的结构,如果大家感兴趣,可以自己下载代码研究。


3.实现思路

由于网上的Demo也是提供了类似于AdapterView的访问方式,所以,我在想,我们能不能换一种方式来实现,试想,如果这个滚筒是横着的,那么我们就可以利用Gallery来实现,Gallery的特点跟WheelView有相似之处,比如:选中的项始终在View中间,只不过它是横着布局的。

由于我之前修改过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

在修改完Gallery后,我们就可以来使用它了,还得做一些事情,就是先要扩展Gallery,实现一个WheelView,在这个类里面,我们要去绘制中间选择的矩形、背景图片、上下阴影等。
这个WheelView扩展了Gallery,同时还应该提供设置背景图片,选择矩形的图片和上下阴影的图片等功能。
WheelView的完整实现代码如下:

[java] view plaincopy
  1. package com.nj1s.lib.widget;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Rect;  
  6. import android.graphics.drawable.Drawable;  
  7. import android.graphics.drawable.GradientDrawable;  
  8. import android.graphics.drawable.GradientDrawable.Orientation;  
  9. import android.util.AttributeSet;  
  10. import android.view.Gravity;  
  11. import android.view.View;  
  12.   
  13. import com.nj1s.lib.R;  
  14.   
  15. public class WheelView extends TosGallery  
  16. {  
  17.     private Drawable mSelectorDrawable      = null;  
  18.     private Rect mSelectorBound             = new Rect();  
  19.     private GradientDrawable mTopShadow     = null;  
  20.     private GradientDrawable mBottomShadow  = null;  
  21.     private static final int[] SHADOWS_COLORS =  
  22.     {  
  23.         0xFF111111,  
  24.         0x00AAAAAA,  
  25.         0x00AAAAAA  
  26.     };  
  27.   
  28.     public WheelView(Context context)  
  29.     {  
  30.         super(context);  
  31.   
  32.         initialize(context);  
  33.     }  
  34.   
  35.     public WheelView(Context context, AttributeSet attrs)  
  36.     {  
  37.         super(context, attrs);  
  38.   
  39.         initialize(context);  
  40.     }  
  41.   
  42.     public WheelView(Context context, AttributeSet attrs, int defStyle)  
  43.     {  
  44.         super(context, attrs, defStyle);  
  45.   
  46.         initialize(context);  
  47.     }  
  48.   
  49.     private void initialize(Context context)  
  50.     {  
  51.         this.setVerticalScrollBarEnabled(false);  
  52.         this.setSlotInCenter(true);  
  53.         this.setOrientation(TosGallery.VERTICAL);  
  54.         this.setGravity(Gravity.CENTER_HORIZONTAL);  
  55.         this.setUnselectedAlpha(1.0f);  
  56.   
  57.         // This lead the onDraw() will be called.  
  58.         this.setWillNotDraw(false);  
  59.   
  60.         // The selector rectangle drawable.  
  61.         this.mSelectorDrawable =   
  62.             getContext().getResources().getDrawable(R.drawable.wheel_val);  
  63.         this.mTopShadow    =   
  64.             new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);  
  65.         this.mBottomShadow =   
  66.             new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);  
  67.   
  68.         // The default background.  
  69.         this.setBackgroundResource(R.drawable.wheel_bg);  
  70.     }  
  71.   
  72.     @Override  
  73.     protected void dispatchDraw(Canvas canvas)  
  74.     {  
  75.         super.dispatchDraw(canvas);  
  76.   
  77.         // After draw child, we do the following things:  
  78.         // +1, Draw the center rectangle.  
  79.         // +2, Draw the shadows on the top and bottom.  
  80.   
  81.         drawCenterRect(canvas);  
  82.   
  83.         drawShadows(canvas);  
  84.     }  
  85.   
  86.     /** 
  87.      * setOrientation 
  88.      */  
  89.     @Override  
  90.     public void setOrientation(int orientation)  
  91.     {  
  92.         if (TosGallery.HORIZONTAL == orientation)  
  93.         {  
  94.             throw new IllegalArgumentException("The orientation must be VERTICAL");  
  95.         }  
  96.   
  97.         super.setOrientation(orientation);  
  98.     }  
  99.   
  100.     @Override  
  101.     protected void onLayout(boolean changed, int l, int t, int r, int b)  
  102.     {  
  103.         super.onLayout(changed, l, t, r, b);  
  104.   
  105.         int galleryCenter = getCenterOfGallery();  
  106.         View v = this.getChildAt(0);  
  107.   
  108.         int height = (null != v) ? v.getMeasuredHeight() : 50;  
  109.         int top = galleryCenter - height / 2;  
  110.         int bottom = top + height;  
  111.   
  112.         mSelectorBound.set(  
  113.                 getPaddingLeft(),  
  114.                 top,  
  115.                 getWidth() - getPaddingRight(),  
  116.                 bottom);  
  117.     }  
  118.   
  119.     private void drawCenterRect(Canvas canvas)  
  120.     {  
  121.         if (null != mSelectorDrawable)  
  122.         {  
  123.             mSelectorDrawable.setBounds(mSelectorBound);  
  124.             mSelectorDrawable.draw(canvas);  
  125.         }  
  126.     }  
  127.   
  128.     private void drawShadows(Canvas canvas)  
  129.     {  
  130.         int height = (int)(2.0 * mSelectorBound.height());  
  131.         mTopShadow.setBounds(00, getWidth(), height);  
  132.         mTopShadow.draw(canvas);  
  133.   
  134.         mBottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());  
  135.         mBottomShadow.draw(canvas);  
  136.     }  
  137. }  

上面代码没有什么特别的东西,只是有几点需要注意:

[1] 不要重写onDraw(),为什么呢?因为onDraw()是绘制自己,如果你在onDraw()中来绘制阴影的话,那么最后的效果可能是Child在上面,阴影在下面。因此,我们应该是在绘制完Child之后,再绘制阴影,怎么做呢?请看第二步。

[2] 重写dispatchDraw(),如果对这个方法不明白的话,请自己看文档,这里不解释,总之,这个方法是用来绘制Child的,因此,重写这个方法,先调用super.dispatchDraw()方法,然后再绘制阴影,OK,万事大吉。

[3] 你可以调用#setScrollCycle(boolean)来指定这个WheelView是否可以循环滑动。


5. 如何使用

关于如何使用,其实很简单,就跟使用GridView/ListView一样,通过Adapter来提供View。

[java] view plaincopy
  1. // 设置listener  
  2. mDateWheel.setOnEndFlingListener(mListener);  
  3. // 设置滑动时的声音  
  4. mDateWheel.setSoundEffectsEnabled(true);  
  5. // 设置adapter  
  6. mDateWheel.setAdapter(new WheelTextAdapter(this));  
  7.   
  8.   
  9. // Adapter的实现  
  10. protected class WheelTextAdapter extends BaseAdapter  
  11. {  
  12.     ArrayList<TextInfo> mData = null;  
  13.     int mWidth  = ViewGroup.LayoutParams.MATCH_PARENT;  
  14.     int mHeight = 50;  
  15.     Context mContext = null;  
  16.       
  17.     public WheelTextAdapter(Context context)  
  18.     {  
  19.         mContext = context;  
  20.     }  
  21.       
  22.     public void setData(ArrayList<TextInfo> data)  
  23.     {  
  24.         mData = data;  
  25.         this.notifyDataSetChanged();  
  26.     }  
  27.       
  28.     public void setItemSize(int width, int height)  
  29.     {  
  30.         mWidth  = width;  
  31.         mHeight = height;  
  32.     }  
  33.       
  34.     @Override  
  35.     public int getCount()  
  36.     {  
  37.         return (null != mData) ? mData.size() : 0;  
  38.     }  
  39.   
  40.   
  41.     @Override  
  42.     public Object getItem(int position)  
  43.     {  
  44.         return null;  
  45.     }  
  46.   
  47.   
  48.     @Override  
  49.     public long getItemId(int position)  
  50.     {  
  51.         return 0;  
  52.     }  
  53.   
  54.   
  55.     @Override  
  56.     public View getView(int position, View convertView, ViewGroup parent)  
  57.     {  
  58.         TextView textView = null;  
  59.           
  60.         if (null == convertView)  
  61.         {  
  62.             convertView = new TextView(mContext);  
  63.             convertView.setLayoutParams(new TosGallery.LayoutParams(mWidth, mHeight));  
  64.             textView = (TextView)convertView;  
  65.             textView.setGravity(Gravity.CENTER);  
  66.             textView.setTextSize(26);  
  67.             textView.setTextColor(Color.BLACK);  
  68.         }  
  69.           
  70.         if (null == textView)  
  71.         {  
  72.             textView = (TextView)convertView;  
  73.         }  
  74.           
  75.         TextInfo info = mData.get(position);  
  76.         textView.setText(info.mText);  
  77.         textView.setTextColor(info.mColor);  
  78.           
  79.         return convertView;  
  80.     }  
  81. }  
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝店铺身份信息复核逾期了怎么办 一件代发进货后如果没卖出去怎么办 国外供货商收了钱不发货怎么办 企业被注销之后淘宝企业店怎么办 在淘宝上买了东西店家关门了怎么办 在淘宝上买东西被店家骂了怎么办 淘宝店家错发了两次货怎么办 我的身份证注销了淘宝支付宝怎么办 买了空调坏了店家不管怎么办 支付宝充话费没到账也不退款怎么办 淘宝上店家关铺无法赔偿怎么办 未发货申请退款卖家拒绝怎么办 淘宝订单未发货买家恶意退款怎么办 淘宝被限制购买还有没退款的怎么办 复制粘贴了打字在复制下页怎么办? 得了抑郁症没办法还贷款了怎么办 淘宝东西退了商家不退钱怎么办 京东买东西付款后显示未付款怎么办 不能吃小龙虾的人吃了怎么办 闲鱼退货卖家收到货不退款怎么办 没收到货申请退款卖家不同意怎么办 咸鱼买家不确认收货老退款怎么办 买家买了确认收货然后退款怎么办 买家收确认收货后还申请退款怎么办 淘宝收到货后买家故意说少货怎么办 对面商铺放很大声音乐怎么办 在店面住隔壁商铺一直放音乐怎么办 淘宝卖家把买家评论删了怎么办 淘宝店铺上当顾客说再看看怎么办 车辆摇号申请说手机号注册怎么办 如果在微商手上买到假东西怎么办? 登陆微信显示版本过低该怎么办 苹果手机登陆微信版本过低怎么办 微信版本过低无法登怎么办录 登入微信显示版本过低登不上怎么办 微信版本过低无法使用小程序怎么办 小米4s微信反应很慢怎么办 手机网页缓存的视频播放不了怎么办 ios微信占用内存太大了怎么办 爱奇艺离线视频显示暂无缓存怎么办 酷狗音乐不小心删了歌怎么办