基于Lottie的动态锁屏APP
先上实现图
锁屏效果图
APP主页面
预览页面
设置解锁方式
主页面侧边栏
实现思路:(大家实现类似APP时,也可以按照这种步骤进行分工,并进行迭代开发)
重点部分:其实在这个APP中,比较难的一点就是锁屏页面自定义View的实现,和锁屏交互逻辑的实现,现在放上这两个部分的代码。
锁屏中间部分的自定义View
package com.example.lockscreen.myview;
import android.animation.Animator;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextClock;
import android.widget.TextView;
import com.airbnb.lottie.LottieAnimationView;
import com.example.lockscreen.R;
import com.example.lockscreen.StyleDetailActivity;
import com.example.lockscreen.vo.CodeData;
import com.example.lockscreen.vo.ViewDisplay;
import com.example.lockscreen.vo.WordDisplay;
import androidx.appcompat.app.AppCompatActivity;
public class LockScreenView extends RelativeLayout {
private ProgressBar mProgressBar;
private LottieAnimationView mLottieView;
private RelativeLayout.LayoutParams mProgressBarLayout;
private CodeData mCodeData;
private ViewDisplay mViewDisplay;
private Context mContext;
//此视图布局
private View mView;
//屏幕宽和高
private int mWidth;
private int mHeight;
//手指按下时的坐标
private float mStartX;
private float mStartY;
//展示该View的Activity
private AppCompatActivity mActivity;
//显示进度条
private final float SHOW_PROGRESS = 1f;
//-1代表相对于父容器
private final int SUBJECT = -1;
//解锁方式
private int mInteractionCode = 1;
//正在播放动画的文件名(assets下加载)
private String mLottieName;
//正在播放动画的json字符串(本地加载)
private String mLottieJson;
public LockScreenView(Context context) {
this(context, null);
}
public LockScreenView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LockScreenView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
/**
* 初始化
*
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
mView = LayoutInflater.from(context).inflate(R.layout.lock_screen,this, true);
mProgressBar = mView.findViewById(R.id.progressBar);
mProgressBarLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
mProgressBarLayout.addRule(RelativeLayout.CENTER_HORIZONTAL);
mProgressBarLayout.addRule(RelativeLayout.ALIGN_BOTTOM, SUBJECT);
//加载视图布局
mLottieView = mView.findViewById(R.id.lock_screen_lottie);
mLottieView.addAnimatorListener(myLottieListener);
mActivity = (AppCompatActivity) context;
//mContext = getContext();
mCodeData = new CodeData();
mViewDisplay = new ViewDisplay(mCodeData);
}
/**
* 测量
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量子view
measureChildren(widthMeasureSpec, heightMeasureSpec);
//获取屏幕宽高
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
}
/**
* 布局
*
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//设置滚动条的相对布局位置和相关属性
mProgressBar.setMax(mWidth / 5 * 2);
mProgressBarLayout.topMargin = mHeight / 10 * 9;
mProgressBarLayout.width = mWidth / 5 * 2;
mProgressBarLayout.height = mHeight / 100;
mProgressBar.setLayoutParams(mProgressBarLayout);
}
/**
* 动画播放进度监听器
*/
private Animator.AnimatorListener myLottieListener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
if (mLottieView.getSpeed() < 0) {
//用户滑动屏幕后将速度恢复正常
mLottieView.setSpeed(1f);
}
}
};
/**
* 此方法会在所有的控件都从xml中加载完毕后加载
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
/**
* 监听屏幕点击和移动事件
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getRawX();
final float y &#