Skip to content

Commit

Permalink
抖音view
Browse files Browse the repository at this point in the history
  • Loading branch information
JrDong committed Oct 10, 2018
1 parent 28dfa53 commit 0681460
Show file tree
Hide file tree
Showing 18 changed files with 848 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
android:screenOrientation="portrait"/>
<activity android:name=".picture.activity.PictureDemoActivity"
android:screenOrientation="portrait"/>
<activity android:name=".dou.DouYinActivity"
android:screenOrientation="portrait"/>

</application>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class LinkedListReverse {
public static void main(String[] args) {
print(initNode(3));
print(reverseByRecur(initNode(3)));
print(reverse(initNode(3)));
print(reverse(initNode(5)));
}

public static Node reverse(Node head) {
Expand Down
39 changes: 39 additions & 0 deletions app/src/main/java/com/djr/commonlibrary/dou/BezierEvaluator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.djr.commonlibrary.dou;

import android.animation.TypeEvaluator;
import android.graphics.PointF;

/**
* @author DongJr
*
* @date 2018/08/02
*/
public class BezierEvaluator implements TypeEvaluator<PointF>{

private PointF mControlP1;
private PointF mControlP2;

public BezierEvaluator(PointF controlP1) {
this.mControlP1 = controlP1;
// this.mControlP2 = controlP2;
}

@Override
public PointF evaluate(float time, PointF start, PointF end) {

float timeLeft = 1.0f - time;
PointF point = new PointF();

point.x = timeLeft * timeLeft * timeLeft * (start.x) +
3 * timeLeft * timeLeft * time * (mControlP1.x) +
// 3 * timeLeft * time * time * (mControlP2.x) +
time * time * time * (end.x);

point.y = timeLeft * timeLeft * timeLeft * (start.y) +
3 * timeLeft * timeLeft * time * (mControlP1.y) +
// 3 * timeLeft * time * time * (mControlP2.y) +
time * time * time * (end.y);
return point;
}

}
35 changes: 35 additions & 0 deletions app/src/main/java/com/djr/commonlibrary/dou/DouYinActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.djr.commonlibrary.dou;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import com.djr.commonlibrary.R;


public class DouYinActivity extends AppCompatActivity {


public static void startActivity(Context context) {
Intent intent = new Intent(context, DouYinActivity.class);
context.startActivity(intent);
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_douyin);
final ShowLayout showLayout = (ShowLayout) findViewById(R.id.douyin);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
showLayout.startAnimation();
}
}, 2000);

}

}
146 changes: 146 additions & 0 deletions app/src/main/java/com/djr/commonlibrary/dou/MusicalNoteView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package com.djr.commonlibrary.dou;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.djr.commonlibrary.R;

import java.util.Random;

/**
* @author DongJr
*
* 抖音效果的音符运动轨迹
*/
public class MusicalNoteView extends RelativeLayout {

private Paint mBezierPaint;
private PointF mControl;
private PointF mStartPoint;
private PointF mEndPoint;
private Drawable[] mDrawableArr;
private Random mRandom;
private Handler mHander = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
addMusicNodeView();
mHander.sendEmptyMessageDelayed(0, 1000);
}
};

public MusicalNoteView(Context context) {
this(context, null);
}

public MusicalNoteView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public MusicalNoteView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
mBezierPaint = new Paint();
mBezierPaint.setColor(Color.RED);
mBezierPaint.setStrokeWidth(10);
mBezierPaint.setStyle(Paint.Style.STROKE);
mBezierPaint.setAntiAlias(true);

mDrawableArr = new Drawable[]{
getResources().getDrawable(R.drawable.icon_music_node1),
getResources().getDrawable(R.drawable.icon_music_node2)};
mRandom = new Random();
}

private void addMusicNodeView() {
final ImageView musicNodeView = new ImageView(getContext());
musicNodeView.setImageDrawable(mDrawableArr[mRandom.nextInt(2)]);
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.addRule(CENTER_HORIZONTAL, TRUE);
lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);
addView(musicNodeView ,lp);

ValueAnimator bezierValueAnimator = getBezierValueAnimator(musicNodeView);
bezierValueAnimator.setInterpolator(new LinearInterpolator());
bezierValueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
removeView(musicNodeView);
}
});
bezierValueAnimator.start();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mStartPoint = new PointF(w, h);
mEndPoint = new PointF(w / 2, 0);
mControl = new PointF(0, h * 0.6f);
startAnimation();
}

public void startAnimation(){
mHander.removeCallbacksAndMessages(null);
mHander.sendEmptyMessageDelayed(0, 1000);
}

private ValueAnimator getBezierValueAnimator(final View target) {
// 初始化贝塞尔估值器
BezierEvaluator evaluator = new BezierEvaluator(mControl);
ValueAnimator animator = ValueAnimator.ofObject(evaluator, mStartPoint, mEndPoint);
animator.setTarget(target);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
PointF pointF = (PointF) valueAnimator.getAnimatedValue();
float animatedFraction = valueAnimator.getAnimatedFraction();
target.setX(pointF.x);
target.setY(pointF.y);
if (animatedFraction <= 0.5f){
//0 - 1f
target.setAlpha(animatedFraction * 2f);
//1 - 1.5f
target.setScaleX(1f + animatedFraction);
target.setScaleY(1f + animatedFraction);
} else {
//1f - 0f
target.setAlpha(2 - (animatedFraction * 2));
//1.5f - 1
target.setScaleX(2f - animatedFraction);
target.setScaleY(2f - animatedFraction);
}
}
});

animator.setDuration(3000);
return animator;
}



}
156 changes: 156 additions & 0 deletions app/src/main/java/com/djr/commonlibrary/dou/ShowHeadView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package com.djr.commonlibrary.dou;


import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.djr.commonlibrary.R;
import com.djr.commonlibrary.utils.DensityUtils;

/**
* @author DongJr
*
* @date 2018/08/06
*/
public class ShowHeadView extends RelativeLayout{

private Paint mCirclePaint;
private Paint mCircleFramePaint;
private int mParentSize ;
private int mHeadSize ;
private int mHeadRadius ;
private static final int ANIMATION_DURATION = 1000;
private int mFrameRadius;

public ShowHeadView(Context context) {
this(context , null);
}

public ShowHeadView(Context context, AttributeSet attrs) {
this(context, attrs , 0);
}

public ShowHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
mCirclePaint = new Paint();
mCirclePaint.setColor(Color.parseColor("#6924F2"));
mCirclePaint.setAntiAlias(true);
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(2);

mCircleFramePaint = new Paint();
mCircleFramePaint.setColor(Color.parseColor("#6924F2"));
mCircleFramePaint.setAntiAlias(true);
mCircleFramePaint.setStyle(Paint.Style.STROKE);
mCircleFramePaint.setStrokeWidth(2);

setWillNotDraw(false);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mParentSize = h;
mHeadSize = (int) (h * 0.8);
mHeadRadius = (int) (h * 0.45);
mFrameRadius = mHeadRadius;
addImageView();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(mParentSize / 2, mParentSize / 2, mHeadRadius, mCirclePaint);
canvas.drawCircle(mParentSize / 2, mParentSize / 2, mFrameRadius, mCircleFramePaint);
}

private void addImageView(){
final ImageView headView = new ImageView(getContext());
LayoutParams lp = new LayoutParams(mHeadSize, mHeadSize);
lp.addRule(CENTER_IN_PARENT, TRUE);
headView.setImageDrawable(getResources().getDrawable(R.drawable.avatar));
addView(headView, lp);
startFrameAnimation();
startHeadTwinkleAnimation(headView);
}

private void startFrameAnimation(){
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f);
valueAnimator.setInterpolator(new AccelerateInterpolator());
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setDuration(ANIMATION_DURATION);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
mCircleFramePaint.setAlpha((int) (value * 255));
mFrameRadius = (int) (mHeadRadius + DensityUtils.dp2px(4) * (1 - value));
invalidate();
}
});
valueAnimator.setStartDelay(1000);
valueAnimator.start();
}

private void startHeadTwinkleAnimation(View target) {
//先闪动4次,再缩放切换
ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 1f, 0.9f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 1f, 0.9f, 1f);
scaleX.setRepeatCount(4);
scaleY.setRepeatCount(4);
AnimatorSet twinkleSet = new AnimatorSet();
twinkleSet.setInterpolator(new LinearInterpolator());
twinkleSet.setDuration(ANIMATION_DURATION).playTogether(scaleX, scaleY);


ObjectAnimator changeScaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 1f, 0.2f, 1f);
ObjectAnimator changeScaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 1f, 0.2f, 1f);
AnimatorSet changeSet = new AnimatorSet();
changeSet.setInterpolator(new AccelerateDecelerateInterpolator());
changeSet.setDuration(ANIMATION_DURATION).playTogether(changeScaleX, changeScaleY);


final AnimatorSet finalSet = new AnimatorSet();
finalSet.playSequentially(twinkleSet, changeSet);
finalSet.setTarget(target);
finalSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {

}

@Override
public void onAnimationEnd(Animator animation) {
finalSet.start();
}

@Override
public void onAnimationCancel(Animator animation) {

}

@Override
public void onAnimationRepeat(Animator animation) {
}
});
finalSet.start();
}

}
Loading

0 comments on commit 0681460

Please sign in to comment.