Android 自定義懸浮小球
阿新 • • 發佈:2018-12-12
第一次自己自定義控制元件,看了別人的控制元件,自己模仿出來一個新的,這是精簡版,拓展性很差,文章最後將完全版程式碼附上
效果和支付寶收能量,網易星球首頁鑽石一樣
先上效果圖
1.繼承 Relativelayout
public MyView(Context context)
public MyView(Context context, AttributeSet attrs)
2.在attrs中,定義屬性
<declare-styleable name="MyView"> <attr name="cicleWidth" format="dimension" /> <attr name="myViewWidth" format="dimension" /> <attr name="myViewHeight" format="dimension" /> </declare-styleable>
3.在xml中,要加xmlns:app="http://schemas.android.com/apk/res-auto"
<com.luo.hellocustom.MyView android:id="@+id/myView" android:layout_width="match_parent" android:layout_height="match_parent" app:cicleWidth="35dp" />
4.程式碼中,拿到屬性值
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyView); parentWidth = typedArray.getDimension(R.styleable.MyView_myViewWidth, getScrWidth()); parentHeight = typedArray.getDimension(R.styleable.MyView_myViewHeight, getScrHeight());
拿到控制元件寬度,getScrWidth()是我們自己預設設定的值
5.給控制元件新增小球
寫一個方法setList();在Activity中直接呼叫,等於初始化資料
//設定資料新增子小球 public void setList(List<? extends Number> list) { this.mFloat = list; //使用post方法確保在UI載入完的情況下 呼叫init() 避免獲取到的寬高為0 post(new Runnable() { @Override public void run() { init(); } }); }
使用post是為了可以拿到寬高,否則為0,在post之前就需要
view = LayoutInflater.from(mContext).inflate(R.layout.view_float, this, false);
否則也拿不到值
6.小球的出現使用隨機數,生成xy
Random randomX = new Random(); Random randomY = new Random(); float x = randomX.nextFloat() * (parentWidth - view.getWidth()/2); float y = randomY.nextFloat() * (parentHeight - view.getWidth()/2); view.setX(x); view.setY(y);
取值在,父控制元件的寬度減小球半徑
7,動畫,小球出現時動畫(漸變)
view.setAlpha(0); view.setScaleX(0); view.setScaleY(0); view.animate().alpha(1).scaleX(1).scaleY(1).setDuration(2000).start();
8.小球的點選事件,我們可以加個回撥
public static interface onclickItemListen{ public void onclick(View view,int postion); } private onclickItemListen onclickItemListen; public void setOnclickItemListen(MyView.onclickItemListen onclickItemListen) { this.onclickItemListen = onclickItemListen; }
view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { removeFloatAnim(v); if (onclickItemListen != null) { onclickItemListen.onclick(v,i); } } });
9.小球出現後浮動動畫,動畫(上下位移)
Animation anim = new TranslateAnimation(0, 0, -10, 20); anim.setInterpolator(new AccelerateDecelerateInterpolator()); anim.setDuration(1000); anim.setRepeatCount(Integer.MAX_VALUE); anim.setRepeatMode(Animation.REVERSE);//反方向執行 view.startAnimation(anim);
10.小球點選後,移除動畫(位移)
private void removeFloatAnim(final View view) { ValueAnimator 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(); Log.d(TAG, "onAnimationUpdate: " + view.getTranslationY()); Log.d(TAG, "onAnimationUpdate: " + view.getY()); view.setAlpha(Value / parentHeight); view.setTranslationY(view.getY() - (parentHeight - Value)); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { removeView(view); } }); animator.start(); }
11.為了小球不出現同一位置且重合,需要遞迴
private void addNewPosition(List<Bean> allPostion, View childView) { Random randomX = new Random(); Random randomY = new Random(); float x = randomX.nextFloat() * (parentWidth - 70 - childView.getMeasuredWidth()); float y = randomY.nextFloat() * (parentHeight - 70 - childView.getMeasuredWidth()); boolean flag = false; if (allPostion.size() == 0) { allPostion.add(new Bean(x, y)); } for (Bean bean : allPostion) { float x1 = bean.getX(); float y1 = bean.getY(); if (x > (x1 + 140) || y > (y1 + 140) || x < (x1 - 140) || y < (y1 - 140)) { } else { flag = true; } } if (!flag) { allPostion.add(new Bean(x, y)); return; } else { addNewPosition(allPostion, childView); } }
12.分成兩撥顯示,第一撥點選完以後,出現第二波
public void notifychangeAll(List<? extends Number> list) { allPostion.clear(); this.mFloat = list; //使用post方法確保在UI載入完的情況下 呼叫init() 避免獲取到的寬高為0 post(new Runnable() { @Override public void run() { centerView.clearAnimation(); centerView.setVisibility(GONE); addChidView(); } }); }
和初始化一樣,不過要去掉存放位置的list
ok,最終就完成了,因為時間有限這只是簡版,拓展性不是很大