android自定义滑块解锁
虽然网上已经有很多这个代码,但是还是需要自己写一遍,才能更深刻的了解其中的原理和步骤。先看效果图:这里的矩形,可以设置圆角,圆角非常大的时候,会变成圆形。看代码:自定义集成View:package com.test.viewtest;import android.animation.ValueAnimator;import android.content.Context;import androi
·
虽然网上已经有很多这个代码,但是还是需要自己写一遍,才能更深刻的了解其中的原理和步骤。
先看效果图:
这里的矩形,可以设置圆角,圆角非常大的时候,会变成圆形。
看代码:
自定义集成View:
package com.test.viewtest;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @date 2021/09/07
* 侧滑按钮
*/
public class ProfileSlideView extends View {
private Paint mBgPaint;
private Paint mSliderPaint;
private Paint mTextPaint;
private Paint mArrowPaint;
private RectF mBgRectF;
private RectF mSliderRectF;
private RectF mProgressRectF;
//侧滑条圆角度数
private Float mCorner = 50f;
private float mPadding = 4;
private float mSliderWidth = 200;//滑块宽度
private Path mSlideArrowPath;
private String mTipText = "右滑开锁";//提示文案
private float mTextSize ;//文字大小
private float mLastTouchX = 0;
//动画
private ValueAnimator mAutoSlideAnimator;
//滑块自动归位动画时长
private int mAutoSlideTime = 500;
private float mSliderLevel = 0.5f;
private int mProgressColor ;//已滑过的区域颜色
private int mBackgroundColor ;//背景图颜色
private int mArrowPaintColor ;//箭头颜色
private int mTextPaintColor ;//提示文字颜色
private int mSliderPaintColor ;//滑块颜色
public ProfileSlideView(Context context) {
this(context, null);
}
public ProfileSlideView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ProfileSlideView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context,attrs,defStyleAttr);
mBgPaint = new Paint();
mBgPaint.setAntiAlias(true);
mBgPaint.setStyle(Paint.Style.FILL);
mBgPaint.setColor(mBackgroundColor);
mBgPaint.setAlpha(100);
mSliderPaint = new Paint();
mSliderPaint.setAntiAlias(true);
mSliderPaint.setStyle(Paint.Style.FILL);
mArrowPaint = new Paint();
mArrowPaint.setAntiAlias(true);
mArrowPaint.setStyle(Paint.Style.FILL);
mArrowPaint.setColor(mArrowPaintColor);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(mTextPaintColor);
mTextPaint.setTextSize(30);
mBgRectF = new RectF();
mSliderRectF = new RectF();
mProgressRectF = new RectF();
mSlideArrowPath = new Path();
}
private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProfileSlideView, defStyleAttr, 0);
mCorner = typedArray.getDimension(R.styleable.ProfileSlideView_slideCorner, 22f);
mSliderWidth = typedArray.getDimension(R.styleable.ProfileSlideView_sliderWidth,80f);
mTextSize = typedArray.getDimension(R.styleable.ProfileSlideView_tipTextSize,16f);
mAutoSlideTime = typedArray.getInt(R.styleable.ProfileSlideView_autoSlideTime, 500);
mTipText = typedArray.getString(R.styleable.ProfileSlideView_tipText);
mPadding = typedArray.getDimension(R.styleable.ProfileSlideView_sliderPadding, 2f);
mSliderLevel = typedArray.getFloat(R.styleable.ProfileSlideView_sliderLevel, 0.5f);
mProgressColor = typedArray.getColor(R.styleable.ProfileSlideView_mProgressColor, Color.parseColor("#88FFA0"));
mBackgroundColor = typedArray.getColor(R.styleable.ProfileSlideView_bgPaintColor, Color.parseColor("#AAAAAA"));
mArrowPaintColor = typedArray.getColor(R.styleable.ProfileSlideView_arrowPaintColor, Color.parseColor("#1A42E6"));
mTextPaintColor = typedArray.getColor(R.styleable.ProfileSlideView_tipPaintColor, Color.parseColor("#444444"));
mSliderPaintColor = typedArray.getColor(R.styleable.ProfileSlideView_sliderPaintColor, Color.parseColor("#00BB25"));
typedArray.recycle();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
int viewWidth = right - left;
int viewHeight = bottom - top;
mBgRectF.left = 0f;
mBgRectF.top = 0f;
mBgRectF.right = viewWidth * 1.0f;
mBgRectF.bottom = viewHeight * 1.0f;
//mPadding为滑块与背景条之间的边距
mSliderRectF.left = mPadding;
mSliderRectF.top = mPadding;
mSliderRectF.right = mSliderWidth;
mSliderRectF.bottom = viewHeight * 1.0f - mPadding;
mProgressRectF.left = mPadding;
mProgressRectF.top = mPadding;
mProgressRectF.right = mSliderWidth / 2;
mProgressRectF.bottom = viewHeight * 1.0f - mPadding;
Log.d("viewTest", "mSliderRectF: "+mSliderRectF.toString());
Log.d("viewTest", "mProgressRectF: "+mProgressRectF.toString());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制背景图
drawBackground(canvas);
//绘制有效进度
drawProgress(canvas);
//绘制 圆形滑块
drawSlide(canvas);
//绘制文字
drawTipText(canvas);
//初始化动画
initAnim();
}
private void drawBackground(Canvas canvas) {
canvas.drawRoundRect(mBgRectF, mCorner, mCorner, mBgPaint);
}
//绘制滑块
private void drawSlide(Canvas canvas) {
mSliderPaint.setColor(mSliderPaintColor);
canvas.drawRoundRect(mSliderRectF, mCorner, mCorner,mSliderPaint);
mArrowPaint.setStyle(Paint.Style.STROKE);
mArrowPaint.setStrokeWidth(3f);
//箭头宽度为滑块的1/16
float arrowWidth = mSliderWidth / 16f;
//绘制箭头
mSlideArrowPath.reset();
//这里使得 箭头的横坐标 在滑块的1/2处
float arrowPos = 0.5f;
mSlideArrowPath.moveTo(mSliderRectF.left + mSliderWidth * arrowPos - (arrowWidth) / 2, mSliderRectF.bottom / 3f);
mSlideArrowPath.lineTo(mSliderRectF.left + mSliderWidth * arrowPos + arrowWidth, mSliderRectF.bottom / 2f);
mSlideArrowPath.lineTo(mSliderRectF.left + mSliderWidth * arrowPos - arrowWidth / 2, mSliderRectF.bottom * 2 / 3f);
canvas.drawPath(mSlideArrowPath, mArrowPaint);
}
private void drawTipText(Canvas canvas) {
float textWidth = mTextPaint.measureText(mTipText);
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
Float baseLine = mBgRectF.height() * 0.5f - (fontMetrics.ascent + fontMetrics.descent) / 2;
canvas.drawText(mTipText, ((mBgRectF.width() - mSliderWidth - textWidth) / 2f) + mSliderWidth, baseLine, mTextPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
Log.v("viewTest"," x= " +x+" y = "+y);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if(mSliderRectF.contains(x,y)){
mAutoSlideAnimator.cancel();
}else {
return false;
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (mLastTouchX > 0f) {
if( mSliderRectF.left + x - mLastTouchX + mSliderWidth > mBgRectF.width() - mPadding ){//判断是否滑到了整个View的最右边
mSliderRectF.left = mBgRectF.width() - mPadding - mSliderWidth;
}else if(mSliderRectF.left + x - mLastTouchX < mPadding){//判断是否滑到了整个View的最左边
mSliderRectF.left = mPadding;
}else {
mSliderRectF.left += x - mLastTouchX;
}
mSliderRectF.right = mSliderRectF.left + mSliderWidth;
mProgressRectF.right = mSliderRectF.right;
invalidate();
}
mLastTouchX = x;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
// if (mSliderRectF.centerX() > mBgRectF.centerX()) {
if (mSliderRectF.centerX() > (mBgRectF.left+(mBgRectF.right-mBgRectF.left)*mSliderLevel)) {
mAutoSlideAnimator.setFloatValues(mSliderRectF.left, mBgRectF.right - mPadding - mSliderWidth);
mAutoSlideAnimator.start();
} else {
mAutoSlideAnimator.setFloatValues(mSliderRectF.left, mPadding);
mAutoSlideAnimator.start();
}
}
return true;
}
private void initAnim() {
mAutoSlideAnimator = new ValueAnimator();
mAutoSlideAnimator.setDuration(mAutoSlideTime);
mAutoSlideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mSliderRectF.left = (float) animation.getAnimatedValue();
mSliderRectF.right = mSliderRectF.left + mSliderWidth;
Log.e("viewTest"," mSliderRectF.right=="+ mSliderRectF.right);
mProgressRectF.right = mSliderRectF.right;
if (mSliderRectF.right == mBgRectF.width() - mPadding) {
if(mListener !=null){
mListener.slideEnd();
}
Log.e("viewTest"," mListener.slideEnd();");
}
invalidate();
}
});
}
private void drawProgress(Canvas canvas) {
mSliderPaint.setColor(mProgressColor);
canvas.drawRoundRect(mProgressRectF, mCorner, mCorner, mSliderPaint);
}
SlideListener mListener;
public void addSlideListener(SlideListener listener) {
mListener = listener;
}
public interface SlideListener {
void slideEnd();
}
}
自定义属性:
<declare-styleable name="ProfileSlideView">
<!-- 滑块宽度 -->
<attr name="sliderWidth" format="dimension" />
<!-- 侧滑条圆角度数 -->
<attr name="slideCorner" format="dimension" />
<!-- 滑块和background之间的padding -->
<attr name="sliderPadding" format="dimension" />
<!-- 提示的文字 -->
<attr name="tipText" format="string" />
<!-- 提示的文字 大小 -->
<attr name="tipTextSize" format="dimension" />
<!-- 滑块自动归位动画时长 -->
<attr name="autoSlideTime" format="integer" />
<!-- 已滑过的区域颜色 -->
<attr name="mProgressColor" format="color" />
<!-- 背景图颜色 -->
<attr name="bgPaintColor" format="color" />
<!-- 箭头颜色 -->
<attr name="arrowPaintColor" format="color" />
<!-- 提示文字颜色 -->
<attr name="tipPaintColor" format="color" />
<!-- 滑块颜色 -->
<attr name="sliderPaintColor" format="color" />
<!-- 阀值(0-1之间) -->
<attr name="sliderLevel" format="float" />
</declare-styleable>
xml文件中使用:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.test.viewtest.ProfileSlideView
android:id="@+id/slideView"
android:layout_width="match_parent"
android:layout_height="100dp"
app:sliderWidth="200px"
app:slideCorner="20dp"
app:sliderPadding="2dp"
app:tipText="右滑开锁"
app:tipTextSize="30sp"
app:tipPaintColor="@color/textPaintColor"
app:bgPaintColor="@color/backgroundColor"
app:arrowPaintColor="@color/arrowPaintColor"
app:mProgressColor="@color/progressColor"
app:sliderPaintColor="@color/sliderPaintColor"
app:sliderLevel="0.7"
app:autoSlideTime="500" />
</LinearLayout>
activity中使用:
package com.test.viewtest.activity;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.test.viewtest.ProfileSlideView;
import com.test.viewtest.R;
public class SlideViewActivity extends Activity {
private ProfileSlideView profileSlideView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slide_view);
profileSlideView = findViewById(R.id.slideView);
profileSlideView.addSlideListener(new ProfileSlideView.SlideListener() {
@Override
public void slideEnd() {
Log.d("SlideViewActivity","slideEnd");
Toast.makeText(SlideViewActivity.this,"slideEnd",Toast.LENGTH_SHORT).show();
}
});
}
}
更多推荐
已为社区贡献7条内容
所有评论(0)