自定义LinearLayout实现RatingBar效果,打造一个评分控件
2017-04-17 20:20
453 查看
项目中一直用到RatingBar这个评分控件但奈何系统的太难用了,使用他要满足我们的需求需要弄一堆样式、设置这些或者那些东西。但这都不是重点最要命的是设置我们自己的图片他竟然对图片大小还有要求,若不合格就直接影响到了界面的美观….所以就有了这篇文章。
extends LinearLayout在设置Orientation为HORIZONTAL并将Gravity设置为CENTER
代码动态创建5个ImageView(当然这里可以不止5个)并添加至LinearLayout中
点击事件的逻辑操作
就这四步是不是so easy
如果有对这些属性定义不太清楚的伙伴,可以找找资源毕竟网上有好多。
2.布局使用
● 修复
● version-1.1
从图中我们可以看出getRight()函数可以获取到View想对于ViewGroup的距离,有了这个坐标我们就可以计算手指移动到了那个view上了。
3.为ViewGroup设置
一: 我们来看下实现的效果图
二:总的来说这个自定义还是很简单的,大致步骤如下:
定义一些布局属性extends LinearLayout在设置Orientation为HORIZONTAL并将Gravity设置为CENTER
代码动态创建5个ImageView(当然这里可以不止5个)并添加至LinearLayout中
点击事件的逻辑操作
就这四步是不是so easy
三:在values文件夹中创建一个attrs文件用来定义一些布局属性
<declare-styleable name="a_zhon"> <!--填充图片--> <attr name="star_img" format="reference" /> <!--默认图片--> <attr name="unstar_img" format="reference" /> <!--图片宽度--> <attr name="image_width" format="dimension" /> <!--图片高度--> <attr name="image_height" format="dimension" /> <!--图片之间的间距--> <attr name="image_padding" format="dimension" /> <!--图片总数--> <attr name="star_count" format="integer" /> <!--填充的图片数量--> <attr name="star" format="integer" /> <!--是否可以点击--> <attr name="clickable" format="boolean" /> </declare-styleable>
如果有对这些属性定义不太清楚的伙伴,可以找找资源毕竟网上有好多。
四:既然我们自定义了一些布局属性,那在代码中肯定是要用到的现在我们来加载它们
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.a_zhon); Drawable starDrawable = array.getDrawable(R.styleable.a_zhon_star_img); Drawable unStarDrawable = array.getDrawable(R.styleable.a_zhon_unstar_img); float width = array.getDimension(R.styleable.a_zhon_image_width, dip2px(context, 36)); float height = array.getDimension(R.styleable.a_zhon_image_height, dip2px(context, 36)); float imagePadding = array.getDimension(R.styleable.a_zhon_image_padding, 5); boolean clickable = array.getBoolean(R.styleable.a_zhon_clickable, true); int starCount = array.getInt(R.styleable.a_zhon_star_count, 5); int star = array.getInt(R.styleable.a_zhon_star, 0); //TypedArray需要被回收释放资源 array.recycle();
五:为了代码的高复用性,在这里创建一个方法用来创建显示的ImageView
/** * 创建默认的ImageView * * @param context 上下文 * @param width 宽度 * @param height 高度 * @return ImageView */ private ImageView getImageView(Context context, float width, float height) { ImageView view = new ImageView(context); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(Math.round(width), Math.round(height)); view.setLayoutParams(params); view.setPadding(dip2px(context, imagePadding), 0, 0, 0); if (unStarDrawable == null) { throw new NullPointerException("请先设置默认的图片资源!"); } else { view.setImageDrawable(unStarDrawable); } return view; }
为了适配广大机型,这里将dip转为手机对应的像素了
/** * 根据手机的分辨率从 dip 的单位 转成为 px(像素) */ private int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); }
六:在写一个改变ImageView背景图片的方法,当用户点击可以改变当前星级。
/** * 填充图片 * * @param i 点击的图片下标 */ private void fillingImage(int i) { //首先将所有的背景都设置为默认背景图片 for (int j = 0; j < starCount; j++) { ImageView view = (ImageView) getChildAt(j); if (unStarDrawable == null) { throw new NullPointerException("请先设置默认的图片资源!"); } else { view.setImageDrawable(unStarDrawable); } } //填充选中的等级 for (int j = 0; j <= i; j++) { ImageView view = (ImageView) getChildAt(j); if (starDrawable == null) { throw new NullPointerException("请先设置填充的图片资源!"); } else { view.setImageDrawable(starDrawable); } } }
七:啥都写好了接下来就so easy,只需要在初始化中调用这两个函数即可
for (int i = 0; i < starCount; i++) { ImageView view = getImageView(context, width, height); //设置ImageView的下标 view.setTag(i); addView(view); //可以点击评分 if (clickable) view.setOnClickListener(this); } if (star != 0) { if (star <= starCount) { //填充图片 fillingImage(star - 1); } else { throw new RuntimeException("star填充数量不能大于总数star_count!"); } }
八:用户点击调整评分数量
/** * 图片的点击事件 */ @Override public void onClick(View v) { fillingImage((Integer) v.getTag()); }
九:使用方法:
1.在build.gradle中添加依赖compile 'com.azhon:ratingbar:1.0.0'
2.布局使用
<com.azhong.rattingbar.RatingBar android:layout_width="match_parent" android:layout_height="wrap_content" a_zhon:clickable="true" a_zhon:image_height="36dp" a_zhon:image_padding="3dp" a_zhon:image_width="36dp" a_zhon:star="0" a_zhon:star_count="5" a_zhon:star_img="@mipmap/star" a_zhon:unstar_img="@mipmap/unstar" />
十:于2017年5月26日将版本更新至1.1.0版本
● 添加滑动手势打分● 修复
getStar()函数返回错误值
● version-1.1
compile 'com.azhon:ratingbar:1.1.0'
十一:Get新技能
滑动手势:通过分析我们知道,手指在view上左右滑动可以设置onTouch事件并获取到坐标 x , y 值,那同样的如果我们获取到里面的每一个ImageView相对与父容器(LinearLayout)的坐标 ;这样我们就可以写出滑动打分的这个效果了,下面来看代码1.获取子View相对于ViewGroup的坐标,来看一张分析图,
从图中我们可以看出getRight()函数可以获取到View想对于ViewGroup的距离,有了这个坐标我们就可以计算手指移动到了那个view上了。
2.这里还需要注意的是需要当ViewGroup完全加载好后,才能获取到真正的getRight()的值。
//给LinearLayout设置加载完成时回调 getViewTreeObserver().addOnGlobalLayoutListener(this); @Override public void onGlobalLayout() { //保存每个view相对于ViewGroup的X轴距离 int viewX[] viewX = new int[starCount]; for (int i = 0; i < starCount; i++) { //view相对于ViewGroup的X轴距离 int right = getChildAt(i).getRight(); viewX[i] = right; } }
3.为ViewGroup设置onTouch()
事件;但你滑动到ImageView上时你会发现并不会回调onTouch()
函数,因为此时响应的时ImageView的onTouch()
事件也就涉及了Android事件传递机制了,所以我们需要拦截子View的onTouch()
事件即可,如下代码:
@Override public boolean onInterceptTouchEvent(MotionEvent e) { switch (e.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: //必须要在MOVE中return才有效果,在这里return后UP事件也会被拦截 return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: break; } return super.onInterceptTouchEvent(e); }
4.最后一步也就是计算触摸到那一个ImageView了,也很简单直接来看代码。
@Override public boolean onTouchEvent(MotionEvent event) { //如果不能点击,那么也不能通过滑动来评分 if (!clickable) return false; if (event.getAction() == MotionEvent.ACTION_MOVE) { //只需要判断x轴坐标是否在Imageview的左右之间即可,width为ImageView的宽度 for (int i = 0; i < viewX.length; i++) { if (event.getX() < viewX[i] && event.getX() > viewX[i] - width) { //填充图片 fillingImage(i); star = i + 1; } } } return true; }
阅读完整代码可前往终点站查阅,到这里车就开完了~~有什么问题欢迎留言。
相关文章推荐
- 自定义LinearLayout实现RatingBar效果,打造一个评分控件
- Android 自定义 HorizontalScrollView 实现ViewPager效果,打造再多图片(控件)也不怕 OOM
- 自定义view——实现评分控件RatingBar的实现
- [Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果
- DEV中的TreeList控件应用的一个小效果实现——个人总结
- 自定义view实现一个view的磁贴效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- 【Animation】实现某一个控件的抖动效果
- 一个树控件类的实现---打造自己的树控件
- 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果
- [Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果
- 实现一个Asp.net自定义Back控件
- 扩展GridView实现的一个自定义无刷新分页,排序,支持多种数据源的控件TwfGridView
- [原]Windows mobile 上自定义的一个滚动字幕效果的控件
- 【Animation】 使用handler和Runnable实现某一个控件的抖动效果
- [Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果
- Flex中如何创建一个自定义数据显示Tips的slider控件。鼠标按住滑标察看效果
- c#+Winform实现自定义的“复制、粘贴”右键快捷菜单,多个控件共享使用一个右键菜单。
- GGrid网页手写签批控件个人实现在页面上自定义显示的一个例子
- iOS cocos2d实现自定义button(按钮特效)控件效果源码