自定义View(三) switch开关按钮 ViewDragHelper的使用初级
2015-09-19 19:01
597 查看
声明本文是为使用ViewDragHelper技术,直接监听touchEvent来实现开关按钮更方便快捷。ViewDragHelper一般用于ViewGroup中来实现views的拖拽滑动等事件的帮助类。
开关按钮,在iOS和android中均比较常见。主要分为两个状态(on,off)。不多说,先上主布局xml:
此布局中含两张图片,一张背景图片,和滑动的按钮,资源图如下:
http://my.csdn.net/my/album/detail/1814243 http://my.csdn.net/my/album/detail/1814245
我们继续,下面是自定义的代码如下:
由于我们想实现slideButton滑动来达到切换开关的目的。故我们用简单的相对布局,将slidebutton放于上层即达到覆盖背景目的。
首先,几个构造函数不再赘述。
我们看ViewDragHelper的初始化:
下面详细讲述下Callback的几个需要复写的方法。
上述代码。最后松手释放时调用
参考:1. http://blog.csdn.net/lmj623565791/article/details/46858663
2. http://www.apkbus.com/android-245699-1-1.html?_dsign=b8a273ef
开关按钮,在iOS和android中均比较常见。主要分为两个状态(on,off)。不多说,先上主布局xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="60dp"> <com.utils.nothingl3.selector_demo.SwitchButton android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"> <ImageView android:id="@+id/switch_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitCenter" android:src="@drawable/switch_bg" /> <ImageView android:id="@+id/slide_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitCenter" android:src="@drawable/slide_button" /> </com.utils.nothingl3.selector_demo.SwitchButton> </RelativeLayout>
此布局中含两张图片,一张背景图片,和滑动的按钮,资源图如下:
http://my.csdn.net/my/album/detail/1814243 http://my.csdn.net/my/album/detail/1814245
我们继续,下面是自定义的代码如下:
public class SwitchButton extends RelativeLayout { private ImageView mBgImageview; private ImageView mSlideButton; private ViewDragHelper mDragger; private int mRange; public SwitchButton(Context context) { this(context, null); } public SwitchButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onFinishInflate() { super.onFinishInflate(); mBgImageview= (ImageView) getChildAt(0); mBgImageview.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(mSlideButton.getLeft()>0) { mSlideButton.layout(0, 0, mSlideButton.getWidth(), mSlideButton.getHeight()); } else{ mSlideButton.layout(mBgImageview.getWidth() - mSlideButton.getWidth(), 0, mBgImageview.getWidth(), mSlideButton.getHeight()); } } }); mSlideButton=(ImageView)getChildAt(1); mDragger= ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(View child, int pointerId) { return true; } @Override public int clampViewPositionHorizontal(View child, int left, int dx){ if(child==mSlideButton) {//滑动按钮 final int leftBound = 0; final int rightBound = mBgImageview.getWidth() - mSlideButton.getWidth()- leftBound; final int newLeft = Math.min(Math.max(left, leftBound), rightBound); return newLeft; } return 0; } @Override public void onViewReleased(View releasedChild, float xvel, float yvel){ mRange=mBgImageview.getWidth()-mSlideButton.getWidth(); if((releasedChild==mSlideButton)) { if ((xvel >= 0) && (mSlideButton.getLeft() >= mRange / 2)) {//button右滑超过一半,重置位置 mSlideButton.layout(mRange, 0, mRange + mSlideButton.getWidth(), mSlideButton.getHeight()); } else if ((xvel >=0) && (mSlideButton.getLeft() < mRange / 2)) {//button右滑不足,回到起始点 mSlideButton.layout(0, 0, mSlideButton.getWidth(), mSlideButton.getHeight()); } else if ((xvel < 0) && (mSlideButton.getLeft() >= mRange / 2)) {//button左滑超过不足 mSlideButton.layout(mRange, 0, mRange + mSlideButton.getWidth(), mSlideButton.getHeight()); } else if ((xvel < 0) && (mSlideButton.getLeft() < mRange / 2)) {//button左滑回到起始点 mSlideButton.layout(0, 0, mSlideButton.getWidth(), mSlideButton.getHeight()); } } } @Override public int getViewHorizontalDragRange(View child) { return mRange=mBgImageview.getWidth() - mSlideButton.getWidth(); } }); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mDragger.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event){ mDragger.processTouchEvent(event); return true; } }
由于我们想实现slideButton滑动来达到切换开关的目的。故我们用简单的相对布局,将slidebutton放于上层即达到覆盖背景目的。
首先,几个构造函数不再赘述。
我们看ViewDragHelper的初始化:
ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback())
三个参数:第一个是作用的ViewGroup,第二个是敏感度(这里取默认值),第三个为callback参数。
其次我们看最后两个函数:
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mDragger.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event){ mDragger.processTouchEvent(event); return true; }即将事件拦截和处理交个ViewDragHelper类Calback具体执行。
下面详细讲述下Callback的几个需要复写的方法。
public boolean tryCaptureView(View child, int pointerId) { return true; }该函数表示是否捕捉该子view(drag),这里返回false的话,不对该View的事件进出处理。
public int clampViewPositionHorizontal(View child, int left, int dx)该函数是view水平运动(与之相对有Vertical方向)时调用,left即为此时运动的值。由于mSlideButton滑动按钮运动范围只有【0,背景图宽度】,故须进行调整,具体调整如
上述代码。最后松手释放时调用
public void onViewReleased(View releasedChild, float xvel, float yvel)此代码分别调用mSlideButton.layout()对按钮位置进行设置。
参考:1. http://blog.csdn.net/lmj623565791/article/details/46858663
2. http://www.apkbus.com/android-245699-1-1.html?_dsign=b8a273ef
相关文章推荐
- Android高级控件小练习
- HDU 5461 Largest Point(关键在于最值)——2015 ACM/ICPC Asia Regional Shenyang Online
- 使用ATL创建简单ActiveX控件(二) —— 添加方法/属性和枚举
- redis 集群性能测试以及与单机性能对比
- Oracle压缩总结2— 估计表压缩效应
- 软件工程
- 接口理解2
- 动画Animation 和 xml 解析Animation
- 博客之感想
- HTML5拖放代码
- 二维数组的指针复习
- 从一次 FULL GC 卡顿谈对服务的影响
- Cocos2d-x3.0游戏实例《不要救我》三——背景滚动周期
- C#基础知识系列四(运算符汇总)
- CMake 使用方法
- 深入理解Spark Streaming执行模型
- B-Tree/B+Tree
- 监听EditText内容变化设置Button是否可点击
- hadoop2.7.1 在Ubuntu 32位 上安装单机版伪分布环境
- IIS7.5 伪静态 脚本映射 配置方法