Android自定义控件之仿网易星球浮动小球
2018-03-14 17:05
295 查看
仿网易星球浮动小球
读呗开发过程中遇到新需求,类似于网易星球收集黑钻的界面,考虑到可能也有人会使用,索性封装成库,后面好移植使用先看看需要实现的效果:
需求分析:
数据集合可能是int、double、float等类型小球位置随机
没有数据时只有一个默认小球,位置固定
小球上下抖动,点击向上运动消失
实现分析:
小球随机的位置固定在父view的宽高范围内可以在初始化和点击时判断集合是否为空从而显示默认小球
补间动画实现抖动、属性动画实现点击上滑消失(纯属个人习惯,没有规定动画类型)
实现步骤:
FloatView
父控件使用Relativelayout(背景可以先指定,后面已经抽取出来可以自定义)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@mipmap/star_bg"> </RelativeLayout>
小球布局
<TextView android:id="@+id/float_view" android:layout_width="35dp" android:layout_height="35dp" android:gravity="center" android:text="0.01234" android:textSize="6dp" android:textColor="#ffffff" android:background="@drawable/shape_circle"> </TextView>
上面布局都是暂定的,后面封装的时候都保留了接口
1、定义构造方法
public FloatView(Context context) { this(context,null); mcontext = context; } public FloatView(Context context, AttributeSet attrs) { super(context, attrs); mcontext = context; } public FloatView(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs); mcontext = context; }
2、初始化默认小球
LayoutParams params = new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT); defaultView = (TextView) LayoutInflater.from(mcontext).inflate(R.layout.view_float, this, false); params.addRule(RelativeLayout.CENTER_IN_PARENT); if (mFloat.size() != 0){ defaultView.setVisibility(GONE); } addView(defaultView,params);
3、设置子view位置并添加
子View随机坐标范围(保证不能出parentView的边界)
Random randomX = new Random(); Random randomY = new Random(); float x = randomX.nextFloat() * (parentWidth - childView.getMeasuredWidth()); float y = randomY.nextFloat() * (parentHeight - childView.getMeasuredHeight()); childView.setX(x); childView.setY(y);
添加子View
for (int i = 0; i < mFloat.size(); i++) { TextView floatview = (TextView) LayoutInflater.from(mcontext).inflate(R.layout.view_float, this, false); setChildViewPosition(floatview); floatview.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); addView(floatview); }
5、设置子View抖动动画
Animation anim = new TranslateAnimation(0,0,-10,20); anim.setInterpolator(new AccelerateDecelerateInterpolator()); anim.setDuration(ANIMATION_TIME); anim.setRepeatCount(Integer.MAX_VALUE); anim.setRepeatMode(Animation.REVERSE);//反方向执行 view.startAnimation(anim);
6、点击移除(使用回调接口暴露方法,并判断是否是数据集合是否为空以显示默认子View)
alueAnimator animator = ValueAnimator.ofFloat(parentHeight,0); animator.setDuration(1000); animator.setInterpolator(new LinearInterpolator()); //动画更新的监听 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float Value = (float) animation.getAnimatedValue(); view.setAlpha(Value/parentHeight); view.setTranslationY(view.getY()-(parentHeight-Value)); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { removeView(view); } }); animator.start();
设置回调(详情见源码):
mListener.itemClick((int)view.getTag(),mFloat.get((int)view.getTag()));
实现效果图:
难点分析:
1、获取的宽高为0?view绘制过程中measure的时间和Activity的生命周期不能保持一致,所以可能在onCreate()中获取的宽高为0;
解决办法:使用post()
post(new Runnable() { @Override public void run() { init(); } });
2、子View的属性为wrap_content,获取的宽高为0,?
在获取的宽高的时候,先指定测量规则
int width = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); parentView.measure(width,height); parentHeight = parentView.getMeasuredHeight(); parentWidth = parentView.getMeasuredWidth();
3、传输数据固定?
这里list使用Number类型的泛型,可以指定为int、float、double、long
public void setList(List<? extends Number> list){ ... //回调里 mListener.itemClick((int)view.getTag(),mFloat.get((int)view.getTag())); }
封装
GIthub地址:StarFloatView使用方法:
在工程目录的build.gradle中添加JitPack.io的代码仓库地址
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
项目目录中的build.gradle中添加依赖
ependencies { compile 'com.github.ErChenZhang:StarFloatView:v1.1' }
在布局文件中使用
<com.smoke.zhangchen.floatviewlib.FloatView android:id="@+id/float_view" android:layout_width="match_parent" android:layout_height="wrap_content app:childTextColor="#ff0000" app:defaultViewText="正在生成中" app:chidTextSize="6sp" app:parentViewBackground="@mipmap/star_bg" app:childViewBackground="@drawable/shape_circle">
childTextColor:小球文字颜色大小,默认白色
defaultViewText:默认小球显示文字
parentViewBackground:整体背景
childViewBackground:小球背景
chidTextSize:小球文字大小,默认6sp
设置数据
当前数据支持int、long、float、doubleList<Float> list = new ArrayList<>(); list.add((float) 1.245); list.add((float) 1.567); list.add((float) 0.261); floatview.setList(list);
小球点击回调(value.floatValue()对应传入的list类型)
floatview.setOnItemClickListener(new FloatView.OnItemClickListener() { @Override public void itemClick(int position, Number value) { Toast.makeText(MainActivit 9195 y.this, "当前是第"+position+"个,其值是"+value.floatValue(), Toast.LENGTH_SHORT).show(); } });
相关文章推荐
- Android群英传读书笔记第三章(Android控件架构与自定义View)
- Android中如何在“自定义布局”中“动态”添加控件
- 初识Android之(一)-自定义标题栏控件
- Android-自定义贝塞尔曲线图表控件
- Android-自定义可滑动开关控件之SlidingSwitchView
- Android学习——自定义简易的方向盘操作控件
- Android 高仿微信头像截取 打造不一样的自定义控件
- Android自定义组合型控件
- 自定义Android控件
- Android 自定义键盘控件_身份证号码输入
- Android DIY(自定义) UI(控件,界面)
- Android 自定义圆圈进度并显示百分比例控件(纯代码实现)
- Android自定义UI有哪些基本控件以及需求
- android项目自定义组合控件添加属性
- Android自定义垂直滚动自动选择日期控件
- Android自定义简单控件--星级评价
- Android 自定义价格日历控件
- 【Android自定义View实战】之自定义评价打分控件RatingBar,可以自定义星星大小和间距
- Android 自定义视图容器控件拦截ontouch事件传递给其子控件
- 控件视图Android 自定义视图容器控件拦截ontouch事件传递给其子控件