**1.概述 **
點擊效果==》
短視頻抖音*App非常火 ,視頻點擊效果紅心效果也不錯。其實不難就是一些動畫效果的結合使用,這里將具體一步一步實現。使用簡單,歡迎前往github。
老規矩,先看女神效果圖:
douyin.gif
2.效果分析
2.1:首先是構建一張紅心圖片 new ImageView(mContext);
2.2:設置紅心圖片X與Y坐標位置
2.2:添加屬性動畫效果集,包含縮放、透明度、旋轉、向上平移(按一定順序重復)
3.代碼實現
3.1、自定義布局,我這里重寫RelativeLayout
3.2、自定義屬性attrs.xml
<!--attrs文件 屬性-->
<declare-styleable name="HeartLayout">
<attr name="heart_width" format="integer" />
<attr name="heart_height" format="integer" />
<attr name="heart_image_resId" format="reference" />
</declare-styleable>
image.gif
//自定義屬性 寬、高、圖片
TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.HeartLayout);
mWidth=typedArray.getInteger(R.styleable.HeartLayout_heart_width,mWidth);
mHeight=typedArray.getInteger(R.styleable.HeartLayout_heart_height,mHeight);
image_resId=typedArray.getResourceId(R.styleable.HeartLayout_heart_image_resId,image_resId);
image.gif
3.3、創建ImageView,并設置坐標
** 默認圖片或者自定義**
ImageView imageView=new ImageView(mContext);
imageView.setImageResource(image_resId);
image.gif
因為**圖片位置在手指正上方**,所以得到觸摸坐標后進行左移動自身寬度一半,向上移動自身高度。
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(mWidth, mHeight);
int xLeft=(int)event.getX()- mWidth/2;
int yTop=(int)event.getY() - mHeight;
layoutParams.setMargins(xLeft,yTop,0,0);
imageView.setLayoutParams(layoutParams);
image.gif
3.4、動畫效果ObjectAnimator
通過屬性動畫ObjectAnimator進行縮放、旋轉、漸變透明度、平移等操作ImageView心圖片。
3.5、RedHeartLayout自定義布局的整體代碼
/**
* 仿抖音紅心效果
*/
public class RedHeartLayout extends RelativeLayout {
private Context mContext;
private float[] mRandomAngle = {-25, -15, 0, 15, 25};//隨機心形圖片角度
private int image_resId=R.drawable.ic_heart;//默認圖片
private int mWidth=120; //默認圖片寬
private int mHeight=120;//默認圖片高
/**
* new 使用
* @param context
*/
public RedHeartLayout(Context context) {
super(context);
initView(context);
}
/**
* 當有style自定義樣式時候 使用
* @param context
* @param attrs
* @param defStyleAttr
*/
public RedHeartLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
/**
* 布局使用
* @param context
* @param attrs
*/
public RedHeartLayout(Context context, AttributeSet attrs) {
super(context, attrs);
//自定義屬性 寬、高、圖片
TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.HeartLayout);
mWidth=typedArray.getInteger(R.styleable.HeartLayout_heart_width,mWidth);
mHeight=typedArray.getInteger(R.styleable.HeartLayout_heart_height,mHeight);
image_resId=typedArray.getResourceId(R.styleable.HeartLayout_heart_image_resId,image_resId);
initView(context);
}
/**
* 將寬高dp轉化為px
* @param context
*/
private void initView(Context context) {
this.mContext = context;
this.mHeight=dip2px(mContext,mHeight);
this.mWidth=dip2px(mContext,mWidth);
}
/**
* 觸摸事件處理
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
//第一步,創建心形ImageView
final ImageView imageView=new ImageView(mContext);
imageView.setImageResource(image_resId);
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(mWidth, mHeight);
int xLeft=(int)event.getX()- mWidth/2;
int yTop=(int)event.getY() - mHeight;
layoutParams.setMargins(xLeft,yTop,0,0);
imageView.setLayoutParams(layoutParams);
addView(imageView);
//第二步,添加動畫效果集
AnimatorSet animatorSet = new AnimatorSet();
//縮放動畫,X軸2倍縮小至0.9倍
animatorSet.play(scaleXY(imageView, "scaleX", 2f, 0.9f, 100, 0))
//縮放動畫 , Y軸2倍縮小至0.9倍
.with(scaleXY(imageView, "scaleY", 2f, 0.9f, 100, 0))
//旋轉動畫 , 隨機旋轉角度
.with(rotation(imageView, 0, 0))
//透明度動畫 , 透明度從0-1
.with(alpha(imageView, 0, 1, 100, 0))
//縮放動畫 , X軸0.9倍縮小至1倍
.with(scaleXY(imageView, "scaleX", 0.9f, 1, 50, 150))
//縮放動畫 , Y軸0.9倍縮小至1倍
.with(scaleXY(imageView, "scaleY", 0.9f, 1, 50, 150))
//平移動畫 , Y軸從0向上移動700單位
.with(translationY(imageView, "translationY", 0, -700, 800, 400))
//透明度動畫 , 透明度從1-0
.with(alpha(imageView, 1, 0, 400, 400))
//縮放動畫 , X軸1倍放大至3倍
.with(scaleXY(imageView, "scaleX", 1, 3f, 800, 400))
//縮放動畫 , Y軸1倍放大至3倍
.with(scaleXY(imageView, "scaleY", 1, 3f, 800, 400));
animatorSet.start();
//動畫移除
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
removeViewInLayout(imageView);
}
});
return super.onTouchEvent(event);
}
/**
* X軸或Y軸 縮放
* @param view
* @param propertyName
* @param from
* @param to
* @param time
* @param delayTime
* @return
*/
public ObjectAnimator scaleXY(View view, String propertyName, float from, float to, long time, long delayTime) {
ObjectAnimator _scaleXY= ObjectAnimator.ofFloat(view,propertyName,from,to);
////設置插值器為 勻速(補充:有加速、先加后減等)
_scaleXY.setInterpolator(new LinearInterpolator());
//設置開始前延遲
_scaleXY.setStartDelay(delayTime);
//設置動畫持續時間
_scaleXY.setDuration(time);
_scaleXY.start();
return _scaleXY;
}
/**
* X軸或Y軸 平移
* @param view
* @param from
* @param to
* @param time
* @param delayTime
* @return
*/
public ObjectAnimator translationY(View view, String propertyName,float from, float to, long time, long delayTime) {
ObjectAnimator translation = ObjectAnimator.ofFloat(view, propertyName, from, to);
translation.setInterpolator(new LinearInterpolator());
translation.setStartDelay(delayTime);
translation.setDuration(time);
return translation;
}
/**
* 透明化處理
* @param view
* @param from
* @param to
* @param time
* @param delayTime
* @return
*/
public ObjectAnimator alpha(View view, float from, float to, long time, long delayTime) {
ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", from, to);
alpha.setInterpolator(new LinearInterpolator());
alpha.setStartDelay(delayTime);
alpha.setDuration(time);
return alpha;
}
/**
* 旋轉
* @param view
* @param time
* @param delayTime
* @return
*/
public ObjectAnimator rotation(View view, long time, long delayTime) {
//隨機旋轉角度
float angle= mRandomAngle[new Random().nextInt(4)];
ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", angle);
rotation.setDuration(time);
rotation.setStartDelay(delayTime);
rotation.setInterpolator(new TimeInterpolator() {
@Override
public float getInterpolation(float input) {
//抖動系數越小幅度越大 0-1
return input;
}
});
return rotation;
}
/**
* 根據手機的分辨率從 dp 的單位 轉成為 px(像素)
*/
public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
image.gif
4、布局使用
4.1、使用默認配置(推薦直接使用)
<com.lzj.douyin.redheart.library.RedHeartLayout
android:layout_width="match_parent"
android:layout_height="match_parent"/>
image.gif
4.2、自定義寬、高、引入其他圖片作為效果
<com.lzj.douyin.redheart.library.RedHeartLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:heart_image_resId="@drawable/ic_heart"
app:heart_width="120"
app:heart_height="120" />
image.gif
5、Demo地址github**
覺得還行的老鐵,雙擊66。源碼地址歡迎前往