安卓自定义View----且看如何巧妙地实现一个类似于电视遥控板的环形按钮效果(上)
2016-08-31 10:59
851 查看
本文力求用最简单的方式实现这样的一个效果,并辅以详细的文字说明。
老规矩,先看图:
一个点餐界面,6种菜品,意味着6个按钮,点击‘开始点餐’ 幕布上升效果,这个动画下篇再讲。这篇的重点是这个样式的布局怎么实现。
可以看到,很简单的一个相对布局,一个textview,一个大背景的imageview,然后6个自定义的view,也就是图中的6个菜品按钮,最后3个button。
接下来,关键就是这个view是怎么写的呢?
其中只有两个方法:
若点击事件发生在当前view上,则实现父类的ontouchEvent方法,若没有则返回false。了解事件传递机制的同学应该知道,安卓默认都是实现的super,也即为若是默认实现,则这个事件最终会向上传递到activiy,再响应onclick。
这儿不花篇幅去讲,若是想进一步了解的同学,我推荐一篇文章
http://www.jianshu.com/p/e99b5e8bd67b
主要是isTouchPointInView这个方法的实现:
首先在当前点击的这个图片的view上创建一个bitmap(16位的也可以,还省内存),然后以bitmap对象创建一个画布,准备将内容都绘制在bitmap上。
X,Y即为手指点击的位置坐标(默认从屏幕左上角向右为+X坐标,向下为+Y坐标),如果触摸位置不在当前画布上,则返回false。这儿返回false即为onTouchEvent也返回false,则不触发点击事件。
然后根据bitmap对象得到位图点击位置的像素值pixel,并与一个高8位为1的ARGB颜色进行与运算,得到的结果若不为0,则返回true,否则,返回false。
下来我详解一下上面加粗的这句话,
因为ff代表全1,0xff000000=1111 1111 0000 0000 0000 0000 0000 0000
且 0&0=0
0&1=0
1&1=1
所以后面24位,无论pixel是多少都是0
前面8位,只有在pixel高8位有1时才不是0,所以(pixel&0xff000000)只有当pixel的高8位全为0时才为0。
下来我们在看一下bitmap.getPixel(x,y)常见的返回值:
BLACK:-16777216
BLUE:-16776961
GRAY:-7829368
GREEN:-16711936
TRANSPARENT :0
WHITE:-1
YELLOW :-256
因此我们此处通过getPixel(x, y) ==0 来判断该像素是否为透明(TRANSPARENT )。
但是为什么要判断点击位置是否透明呢?
下来看一张图,这张图就是上面我们的6个菜品按钮的图片,相信你看了也会明白的。
图中用红颜色的框出来的其实是透明的,只有“热菜那块不透明”。
那么总结一下,上面那一大块代码的意思就是说,在当前view上,若点到“热菜”这个区域上,即点击的位置不透明,则触发点击事件。其余不触发点击。
源码我上传到github上,欢迎下载,喜欢的给个star,嘿嘿。
https://github.com/qht1003077897/Android-The-ring-button.git
下篇再讲这个其中的动画实现。
老规矩,先看图:
一个点餐界面,6种菜品,意味着6个按钮,点击‘开始点餐’ 幕布上升效果,这个动画下篇再讲。这篇的重点是这个样式的布局怎么实现。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" > <TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:text="你好!" android:textSize="20sp" /> <ImageView android:id="@+id/split_ll" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="@drawable/total1111111" > </ImageView> <com.example.opendor.TrapezoidImageButton android:id="@+id/telId1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/a" android:tag="telId1" /> <com.example.opendor.TrapezoidImageButton android:id="@+id/telId2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/b" android:tag="telId12" /> <com.example.opendor.TrapezoidImageButton android:id="@+id/telId3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/c" android:tag="telId3" /> <com.example.opendor.TrapezoidImageButton android:id="@+id/telId4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/d" android:tag="telId4" /> <com.example.opendor.TrapezoidImageButton android:id="@+id/telId5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/e" android:tag="telId5" /> <com.example.opendor.TrapezoidImageButton android:id="@+id/telId6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/f" android:tag="telId6" /> <Button android:id="@+id/bill" android:layout_width="100dp" android:layout_height="50dp" android:layout_above="@+id/clear" android:layout_marginBottom="20dp" android:background="@drawable/local_order" android:gravity="center" android:onClick="bill" android:textSize="20sp" /> <Button android:id="@+id/clear" android:layout_width="100dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_marginBottom="5dp" android:background="@drawable/clear_data" android:gravity="center" android:onClick="clear" android:textSize="20sp" /> <Button android:id="@+id/order" android:layout_width="100dp" android:layout_height="50dp" android:layout_alignBaseline="@id/clear" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="20dp" android:background="@drawable/start_menu" android:gravity="center" android:onClick="order" android:textSize="20sp" /> </RelativeLayout>
可以看到,很简单的一个相对布局,一个textview,一个大背景的imageview,然后6个自定义的view,也就是图中的6个菜品按钮,最后3个button。
接下来,关键就是这个view是怎么写的呢?
其中只有两个方法:
public boolean onTouchEvent(MotionEvent event) { if (isTouchPointInView(event.getX(),event.getY())||event.getAction() != MotionEvent.ACTION_DOWN){ return super.onTouchEvent(event); }else{ return false; } }
若点击事件发生在当前view上,则实现父类的ontouchEvent方法,若没有则返回false。了解事件传递机制的同学应该知道,安卓默认都是实现的super,也即为若是默认实现,则这个事件最终会向上传递到activiy,再响应onclick。
这儿不花篇幅去讲,若是想进一步了解的同学,我推荐一篇文章
http://www.jianshu.com/p/e99b5e8bd67b
主要是isTouchPointInView这个方法的实现:
protected boolean isTouchPointInView(float localX, float localY){ if(bitmap!=null){ bitmap=null; } bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_4444); Canvas canvas = new Canvas(bitmap); draw(canvas); int x = (int)localX; int y = (int)localY; if (x < 0 || x >= getWidth()) return false; if (y < 0 || y >= getHeight()) return false; int pixel = bitmap.getPixel(x,y); if ((pixel&0xff000000) != 0){ return true; }else{ return false; } }
首先在当前点击的这个图片的view上创建一个bitmap(16位的也可以,还省内存),然后以bitmap对象创建一个画布,准备将内容都绘制在bitmap上。
X,Y即为手指点击的位置坐标(默认从屏幕左上角向右为+X坐标,向下为+Y坐标),如果触摸位置不在当前画布上,则返回false。这儿返回false即为onTouchEvent也返回false,则不触发点击事件。
然后根据bitmap对象得到位图点击位置的像素值pixel,并与一个高8位为1的ARGB颜色进行与运算,得到的结果若不为0,则返回true,否则,返回false。
下来我详解一下上面加粗的这句话,
因为ff代表全1,0xff000000=1111 1111 0000 0000 0000 0000 0000 0000
且 0&0=0
0&1=0
1&1=1
所以后面24位,无论pixel是多少都是0
前面8位,只有在pixel高8位有1时才不是0,所以(pixel&0xff000000)只有当pixel的高8位全为0时才为0。
下来我们在看一下bitmap.getPixel(x,y)常见的返回值:
BLACK:-16777216
BLUE:-16776961
GRAY:-7829368
GREEN:-16711936
TRANSPARENT :0
WHITE:-1
YELLOW :-256
因此我们此处通过getPixel(x, y) ==0 来判断该像素是否为透明(TRANSPARENT )。
但是为什么要判断点击位置是否透明呢?
下来看一张图,这张图就是上面我们的6个菜品按钮的图片,相信你看了也会明白的。
图中用红颜色的框出来的其实是透明的,只有“热菜那块不透明”。
那么总结一下,上面那一大块代码的意思就是说,在当前view上,若点到“热菜”这个区域上,即点击的位置不透明,则触发点击事件。其余不触发点击。
源码我上传到github上,欢迎下载,喜欢的给个star,嘿嘿。
https://github.com/qht1003077897/Android-The-ring-button.git
下篇再讲这个其中的动画实现。
相关文章推荐
- Android自定义View:如何实现一个模拟时钟?
- 安卓开发笔记——自定义HorizontalScrollView控件(实现QQ5.0侧滑效果)
- Android自定义View: 如何实现类钟摆的动画效果?
- Android GridView 中如何实现item合并,类似于桌面的应用图标效果,长按拖动,加入到另外一个已经存在的文件夹中,或者是压在另一个图标上,行成新的
- 使用xib文件和自定义类来实现自定义View(如何利用xib封装一个View)
- navigationController push动画 从下往上,类似于presentView的默认动画效果如何实现
- 【安卓-自定义布局】安卓App开发思路 一步一个脚印(七)实现ViewPager无限循环与自动播放
- navigationController push动画 从下往上,类似于presentView的默认动画效果如何实现
- 安卓如何实现点击一个按钮退出整个程序?
- 在一个tableView 中需要自定义多种样式的cell(两种或三种),通常你如何实现,说说思路即可?
- 安卓自定义ImageView实现圆形图片效果
- Multiple-View ViewPager-如何实现Viewpager控件的一个页面展示多个page以及回弹效果
- 如何实现一个原质化菜单项或按钮HTML5动画效果
- android自定义TextView实现安卓手机开机android文字Log的动画效果
- Android自定义View之实现一个动态的文字闪动效果
- 黄聪:如何给wordpress的编辑器添加一个自定义按钮,并且实现插入功能
- 安卓中自定义view控件代替radiogroup实现颜色渐变效果的写法
- 【安卓-自定义布局】安卓App开发思路 一步一个脚印(六)实现ViewPager最基本的
- 【安卓-自定义布局】安卓App开发思路 一步一个脚印(十)实现内嵌在app中的webview 腾讯开源X5 高效安全
- 安卓自定义TextView实现签到效果