一.需求
具體的需求就是雙擊視頻任意位置可以冒出向上飛的小心心.之前寫的太模糊,回來詳細編輯一次,末尾附上源碼好了.
二.實現(xiàn)思路
自定義一個RelativeLayout,點擊其內部任意一位置,將其坐標傳入自定義布局,然后add一個??的view,并給這個??加上動畫.
三.實現(xiàn)
1.自定義布局
public class Love extends RelativeLayout {
private Context context;
? ? private LayoutParams params;
? ? private Drawable[]icons =new Drawable[4];
? ? private Interpolator[]interpolators =new Interpolator[4];
? ? private int mWidth;
? ? private int mHeight;
? ? public Love(Context context, AttributeSet attrs) {
super(context, attrs);
? ? ? ? this.context =context;
? ? ? ? initView();
? ? }
private void initView() {
// 圖片資源
? ? ? ? icons[0] = getResources().getDrawable(R.drawable.heart_red);
? ? ? ? icons[1] = getResources().getDrawable(R.drawable.heart_red);
? ? ? ? icons[2] = getResources().getDrawable(R.drawable.heart_red);
? ? ? ? icons[3] = getResources().getDrawable(R.drawable.heart_red);
? ? ? ? // 插值器
? ? ? ? interpolators[0] =new AccelerateDecelerateInterpolator(); // 在動畫開始與結束的地方速率改變比較慢未妹,在中間的時候加速
? ? ? ? interpolators[1] =new AccelerateInterpolator();? // 在動畫開始的地方速率改變比較慢寇蚊,然后開始加速
? ? ? ? interpolators[2] =new DecelerateInterpolator(); // 在動畫開始的地方快然后慢
? ? ? ? interpolators[3] =new LinearInterpolator();? // 以常量速率改變
? ? }
public void addLoveView(float x, float y) {
if (x <100) {
x =101;
? ? ? ? }
if (y <100) {
y =101;
? ? ? ? }
mWidth = (int) (x -100);
? ? ? ? mHeight = (int) (y -100);
? ? ? ? final ImageView iv =new ImageView(context);
? ? ? ? params =new LayoutParams(200, 200);
? ? ? ? iv.setLayoutParams(params);
? ? ? ? iv.setImageDrawable(icons[new Random().nextInt(4)]);
? ? ? ? addView(iv);
? ? ? ? // 開啟動畫跋选,并且用完銷毀
? ? ? ? AnimatorSet set = getAnimatorSet(iv);
? ? ? ? set.start();
? ? ? ? set.addListener(new AnimatorListenerAdapter() {
@Override
? ? ? ? ? ? public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
? ? ? ? ? ? ? ? super.onAnimationEnd(animation);
? ? ? ? ? ? ? ? removeView(iv);
? ? ? ? ? ? }
});
? ? }
/**
? ? * 獲取動畫集合
? ? *
? ? * @param iv
? ? */
? ? private AnimatorSet getAnimatorSet(ImageView iv) {
// 1.alpha動畫
? ? ? ? ObjectAnimator alpha =ObjectAnimator.ofFloat(iv, "alpha", 0.3f, 1f);
? ? ? ? // 2.縮放動畫
? ? ? ? ObjectAnimator scaleX =ObjectAnimator.ofFloat(iv, "scaleX", 0.2f, 1f);
? ? ? ? ObjectAnimator scaleY =ObjectAnimator.ofFloat(iv, "scaleY", 0.2f, 1f);
? ? ? ? // 動畫集合
? ? ? ? AnimatorSet set =new AnimatorSet();
? ? ? ? set.playTogether(alpha, scaleX, scaleY);
? ? ? ? set.setDuration(2000);
? ? ? ? // 貝塞爾曲線動畫
? ? ? ? ValueAnimator bzier = getBzierAnimator(iv);
? ? ? ? AnimatorSet set2 =new AnimatorSet();
? ? ? ? set2.playTogether(set, bzier);
? ? ? ? set2.setTarget(iv);
? ? ? ? return set2;
? ? }
/**
? ? * 貝塞爾動畫
? ? */
? ? private ValueAnimator getBzierAnimator(final ImageView iv) {
// TODO Auto-generated method stub
? ? ? ? PointF[]PointFs = getPointFs(iv); // 4個點的坐標
? ? ? ? BasEvaluator evaluator =new BasEvaluator(PointFs[1], PointFs[2]);
? ? ? ? ValueAnimator valueAnim =ValueAnimator.ofObject(evaluator, PointFs[0], PointFs[3]);
? ? ? ? valueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
? ? ? ? ? ? public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
? ? ? ? ? ? ? ? PointF p = (PointF)animation.getAnimatedValue();
? ? ? ? ? ? ? ? iv.setX(p.x);
? ? ? ? ? ? ? ? iv.setY(p.y);
? ? ? ? ? ? ? ? iv.setAlpha(1 -animation.getAnimatedFraction()); // 透明度
? ? ? ? ? ? }
});
? ? ? ? valueAnim.setTarget(iv);
? ? ? ? valueAnim.setDuration(2000);
? ? ? ? valueAnim.setInterpolator(interpolators[new Random().nextInt(4)]);
? ? ? ? return valueAnim;
? ? }
private PointF[]getPointFs(ImageView iv) {
// TODO Auto-generated method stub
? ? ? ? PointF[]PointFs =new PointF[4];
? ? ? ? PointFs[0] =new PointF(); // p0
? ? ? ? PointFs[0].x = ((int)mWidth);
? ? ? ? PointFs[0].y =mHeight;
? ? ? ? PointFs[1] =new PointF(); // p1
? ? ? ? PointFs[1].x =new Random().nextInt(mWidth);
? ? ? ? PointFs[1].y =new Random().nextInt(mHeight /2) +mHeight /2 +params.height;
? ? ? ? PointFs[2] =new PointF(); // p2
? ? ? ? PointFs[2].x =new Random().nextInt(mWidth);
? ? ? ? PointFs[2].y =new Random().nextInt(mHeight /2);
? ? ? ? PointFs[3] =new PointF(); // p3
? ? ? ? PointFs[3].x =new Random().nextInt(mWidth);
? ? ? ? PointFs[3].y =0;
? ? ? ? return PointFs;
? ? }
}
2.將你的布局套在你想要冒出????的范圍部分,寫在xml里.
<?xml version="1.0" encoding="utf-8"?>
<com.example.technology.lovedemo.Love xmlns:android="http://schemas.android.com/apk/res/android"
? ? android:id="@+id/lovelayout"
? ? android:layout_width="match_parent"
? ? android:background="#d2aab7"
? ? android:layout_height="match_parent">
? ? ? ? android:id="@+id/iamge"
? ? ? ? android:layout_width="300dp"
? ? ? ? android:layout_height="300dp"
? ? ? ? android:layout_centerInParent="true"
? ? ? ? android:background="@drawable/ceshi" />
3.為你的控件設置手勢識別
自定義一個GestureDetector.通過MotionEvent拿到點擊處位于屏幕上的坐標,使用自定義layout的addview方法,把坐標傳入就可以再傳入位置生成向上飛的小??了;
public class MainActivity extends AppCompatActivity {
private GestureDetector myGestureDetector;
? ? private Love ll_love;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? ll_love = (Love) findViewById(R.id.lovelayout);
? ? ? ? ImageView iamge = findViewById(R.id.iamge);
? ? ? ? //實例化GestureDetector
? ? ? ? myGestureDetector =new GestureDetector(this, new myOnGestureListener());
? ? ? ? //增加監(jiān)聽事件
? ? ? ? iamge.setOnTouchListener(new View.OnTouchListener() {
@Override//可以捕獲觸摸屏幕發(fā)生的Event事件
? ? ? ? ? ? public boolean onTouch(View v, MotionEvent event) {
//使用GestureDetector轉發(fā)MotionEvent對象給OnGestureListener
? ? ? ? ? ? ? ? myGestureDetector.onTouchEvent(event);
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
});
? ? }
class myOnGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
? ? ? ? public boolean onDoubleTap(MotionEvent e) {
ll_love.addLoveView(e.getRawX(),e.getRawY());
? ? ? ? ? ? return super.onDoubleTap(e);
? ? ? ? }
}
}
四.源碼
https://github.com/liumaomao0209/LoveDemo