Commit 8f9a78d5 authored by mengcuiguang's avatar mengcuiguang

代码优化

parent 1af1a0f7
package com.mints.wisdomclean.ui.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.mints.wisdomclean.R;
import com.mints.wisdomclean.mvp.model.DataModel;
import com.mints.wisdomclean.ui.widgets.RecyclerViewType;
import java.util.ArrayList;
/**
* Created by sonu on 24/07/17.
*/
public class SectionRecyclerViewAdapter extends RecyclerView.Adapter<SectionRecyclerViewAdapter.SectionViewHolder> {
class SectionViewHolder extends RecyclerView.ViewHolder {
private TextView sectionLabel, showAllButton;
private RecyclerView itemRecyclerView;
public SectionViewHolder(View itemView) {
super(itemView);
sectionLabel = (TextView) itemView.findViewById(R.id.section_label);
itemRecyclerView = (RecyclerView) itemView.findViewById(R.id.item_recycler_view);
}
}
private Context context;
private RecyclerViewType recyclerViewType;
private ArrayList<DataModel> sectionModelArrayList;
public SectionRecyclerViewAdapter(Context context, RecyclerViewType recyclerViewType, ArrayList<DataModel> sectionModelArrayList) {
this.context = context;
this.recyclerViewType = recyclerViewType;
this.sectionModelArrayList = sectionModelArrayList;
}
@Override
public SectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.section_custom_row_dupicate, parent, false);
return new SectionViewHolder(view);
}
@Override
public void onBindViewHolder(SectionViewHolder holder, int position) {
final DataModel mDataModel = sectionModelArrayList.get(position);
holder.sectionLabel.setText(mDataModel.getTitleGroup());
//recycler view for items
holder.itemRecyclerView.setHasFixedSize(true);
holder.itemRecyclerView.setNestedScrollingEnabled(false);
/* set layout manager on basis of recyclerview enum type */
switch (recyclerViewType) {
case LINEAR_VERTICAL:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, RecyclerView.VERTICAL, false);
holder.itemRecyclerView.setLayoutManager(linearLayoutManager);
break;
case LINEAR_HORIZONTAL:
LinearLayoutManager linearLayoutManager1 = new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false);
holder.itemRecyclerView.setLayoutManager(linearLayoutManager1);
break;
case GRID:
GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 3);
holder.itemRecyclerView.setLayoutManager(gridLayoutManager);
break;
}
ItemRecyclerViewAdapter adapter = new ItemRecyclerViewAdapter(context, mDataModel.getListDuplicate());
holder.itemRecyclerView.setAdapter(adapter);
//show toast on click of show all button
// holder.showAllButton.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// Toast.makeText(context, "You clicked on Show All of : " + mDataModel.getTitleGroup() ,Toast.LENGTH_SHORT).show();
// }
// });
}
@Override
public int getItemCount() {
return sectionModelArrayList.size();
}
}
package com.mints.wisdomclean.ui.widgets
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.mints.wisdomclean.R
class BgChooseView : View {
constructor(context: Context) : this(context, null)
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)
constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
companion object {
const val BG_COLOR_RED = "#FF0000"
const val BG_COLOR_BLUE = "#00BFF3"
const val BG_COLOR_WHITE = "#FFFFFF"
const val BG_COLOR_BLUE_GRADUAL = "BLUE_GRADUAL"
}
private var mColor: String = BG_COLOR_BLUE
private var mPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var mIsChecked: Boolean = false
private val mGary = context.resources.getColor(R.color.id_photo_gray)
private var mWidth = 0f
private var mHeight = 0f
init {
mPaint.strokeWidth = 6f
}
fun setColor(color: String) {
mColor = color
invalidate()
}
fun setChecked(isChecked: Boolean) {
mIsChecked = isChecked
invalidate()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
mPaint.shader = null
mPaint.color = mGary
mPaint.style = Paint.Style.FILL
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mPaint)
if (mColor == BG_COLOR_BLUE_GRADUAL) {
val colors = IntArray(2)
val positions = FloatArray(2)
// 第1个点
colors[0] = Color.parseColor(BG_COLOR_BLUE)
positions[0] = 0f
// 第2个点
colors[1] = Color.WHITE
positions[1] = 1f
val shader = LinearGradient(
0f, 0f,
0f, mHeight,
colors,
positions,
Shader.TileMode.MIRROR)
mPaint.shader = shader
} else {
mPaint.shader = null
mPaint.color = Color.parseColor(mColor)
mPaint.style = Paint.Style.FILL
}
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2 - 12, mPaint)
if (mIsChecked) {
mPaint.style = Paint.Style.STROKE
mPaint.color = Color.WHITE
if (mColor == BG_COLOR_WHITE) {
mPaint.color = mGary
}
canvas.translate(mWidth / 2 - 25, mHeight / 2)
val path = Path()
path.lineTo(25f, 20f)
path.lineTo(50f, -20f)
canvas.drawPath(path, mPaint)
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val minimumWidth = suggestedMinimumWidth
val minimumHeight = suggestedMinimumHeight
val width = measureWidth(minimumWidth, widthMeasureSpec)
val height = measureHeight(minimumHeight, heightMeasureSpec)
mWidth = width.toFloat()
mHeight = height.toFloat()
setMeasuredDimension(width, height)
}
private fun measureWidth(defaultWidth: Int, measureSpec: Int): Int {
var measureWidth = defaultWidth
val specMode = MeasureSpec.getMode(measureSpec)
val specSize = MeasureSpec.getSize(measureSpec)
when (specMode) {
MeasureSpec.AT_MOST -> {
measureWidth = specSize + paddingLeft + paddingRight
}
MeasureSpec.EXACTLY -> {
measureWidth = specSize
}
MeasureSpec.UNSPECIFIED -> {
measureWidth = defaultWidth.coerceAtLeast(specSize)
}
}
return measureWidth
}
private fun measureHeight(defaultHeight: Int, measureSpec: Int): Int {
var measureHeight = defaultHeight
val specMode = MeasureSpec.getMode(measureSpec)
val specSize = MeasureSpec.getSize(measureSpec)
when (specMode) {
MeasureSpec.AT_MOST -> {
measureHeight = specSize + paddingTop + paddingBottom
}
MeasureSpec.EXACTLY -> {
measureHeight = specSize
}
MeasureSpec.UNSPECIFIED -> {
measureHeight = defaultHeight.coerceAtLeast(specSize)
}
}
return measureHeight
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Property;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import com.mints.wisdomclean.R;
/*
* findViewById返回Null..
* 自定义View需要重写两个参数的构造
* 并且调用super(context, attrs);方法
* 为什么调用三个的构造却不行。
* 事实证明调用三个的构造函数也是可以的 不过defStyleAttr必须设置为0 而不是-1;
*/
public class ButtonView extends View {
int mWidth=(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, this.getResources().getDisplayMetrics());
int onBackground;
int offBackground;
int time;
float layout_width;
float layout_height;
Paint mPaint;
Scroller mScroller;
float lastX;
VelocityTracker mVelocity;
ViewConfiguration mConfig;
static final int RADIO=50;
int circleX=0;
boolean isOn=false;//是否开启了
AnimatorSet set;
int circleColor;
private Property<ButtonView, Integer> mColor=new Property<ButtonView, Integer>(Integer.class,"currentColor") {
@Override
public Integer get(ButtonView object) {
return object.currentColor;
}
@Override
public void set(ButtonView object, Integer value) {
// TODO Auto-generated method stub
object.currentColor=value;
invalidate();
}
};
private Property<ButtonView, Integer> mMove=new Property<ButtonView, Integer>(Integer.class,"current_move") {
@Override
public Integer get(ButtonView object) {
// TODO Auto-generated method stub
return object.current_move;
}
@Override
public void set(ButtonView object, Integer value) {
// TODO Auto-generated method stub
object.current_move=value;
}
};
boolean isAnimatorStart=false;
@SuppressWarnings("unchecked")
public void startAnimator(int start,int end,int startColor,int endColor,int duration){
set=new AnimatorSet();
set.playTogether(ObjectAnimator.ofInt(this,mMove, start,end),ObjectAnimator.ofObject(this, mColor, new ArgbEvaluator(),startColor,endColor));
set.setDuration(duration);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
isAnimatorStart=true;
}
@Override
public void onAnimationEnd(Animator animation) {
isAnimatorStart=false;
if(changeListener!=null){
changeListener.onChange(isOn);
}
}
});
set.setInterpolator(new DecelerateInterpolator());
set.start();
}
public ButtonView(Context context) {
this(context,null);
}
public ButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public ButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.buttonView);
offBackground=a.getColor(R.styleable.buttonView_offBackground, Color.parseColor("#F6F6F6"));
onBackground=a.getColor(R.styleable.buttonView_onBackground, Color.parseColor("#38DA4E"));
time=a.getInteger(R.styleable.buttonView_time, 500);
circleColor=a.getColor(R.styleable.buttonView_circleColor, Color.parseColor("#D7D7D7"));
layout_height=a.getDimension(R.styleable.buttonView_layout_height, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, context.getResources().getDisplayMetrics()));
layout_width=a.getDimension(R.styleable.buttonView_layout_width, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, context.getResources().getDisplayMetrics()));
mPaint=new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(offBackground);
mPaint.setDither(true);
mScroller=new Scroller(context);
mConfig=ViewConfiguration.get(context);
}
@Override
public void computeScroll() {
// TODO Auto-generated method stub
if(mScroller.computeScrollOffset()){
current_move=mScroller.getCurrX();
invalidate();
}
}
int min_move=circleX+RADIO;
int max_move=0;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode= MeasureSpec.getMode(heightMeasureSpec);
int heightSize= MeasureSpec.getSize(heightMeasureSpec);
int widthMode= MeasureSpec.getMode(widthMeasureSpec);
int widthSize= MeasureSpec.getSize(widthMeasureSpec);
int measureView_width = measureView(widthMode, widthSize, layout_width);
int measureView_height= measureView(heightMode, heightSize, layout_height);
//最大移动位置
max_move=(int) (layout_width-RADIO-circleX);
//最小移动位置
setMeasuredDimension(measureView_width, measureView_height);
}
private int measureView(int mode,int size,float defaultSize){
switch (mode) {
case MeasureSpec.UNSPECIFIED:
case MeasureSpec.AT_MOST:
if(size>defaultSize){
size=(int) Math.ceil(defaultSize);
}
return MeasureSpec.makeMeasureSpec(size,MeasureSpec.EXACTLY);
case MeasureSpec.EXACTLY:
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
return -1;
}
int current_move=min_move;
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setColor(currentColor);
mPaint.setDither(true);
canvas.drawRoundRect(new RectF(0, 0, layout_width, layout_height), RADIO, RADIO, mPaint);
mPaint.setStyle(Style.STROKE);
mPaint.setColor(Color.parseColor("#DADADA"));
canvas.drawRoundRect(new RectF(0, 0, layout_width, layout_height), RADIO, RADIO, mPaint);
mPaint.setStyle(Style.FILL);
mPaint.setColor(circleColor);
canvas.drawCircle(current_move, layout_height/2, layout_height/2-4, mPaint);
}
float x=0;
float y=0;
boolean isClick=false;
Handler mHandler=new Handler();
/**
* 当前颜色
*/
int currentColor=offBackground;
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
mHandler.removeCallbacks(clickRunable);
if(isClick){
if(isOn){//开启则关闭
if(!isAnimatorStart){
startAnimator(max_move, min_move, onBackground, offBackground, time);
isOn=false;
}
// if(mScroller.isFinished()){
// mScroller.startScroll(max_move, (int)this.getY(), min_move-max_move,(int)this.getY(), 1000);
// currentColor=offBackground;
// invalidate();
// isOn=false;
// }
}else{//否则开启
if(!isAnimatorStart){
startAnimator(min_move, max_move, offBackground, onBackground, time);
isOn=true;
}
//if(mScroller.isFinished()){
// mScroller.startScroll(min_move, (int)this.getY(), max_move-min_move,(int)this.getY(), 1000);
// currentColor=onBackground;
// invalidate();
// isOn=true;
//}
}
if(click!=null){
click.onClick(this);
}
//Toast.makeText(getContext(), "单击事件", Toast.LENGTH_SHORT).show();
}
break;
case MotionEvent.ACTION_DOWN:
x=event.getX();
y=event.getY();
isClick=false;
mHandler.postDelayed(clickRunable, mConfig.getScaledTouchSlop());
break;
case MotionEvent.ACTION_MOVE:
float x=event.getX();
float y=event.getY();
isMove(x, y, mConfig.getScaledTouchSlop());
break;
default:
break;
}
return true;
}
private void isMove(float x,float y,int touchSlop){
if(Math.abs(this.x-x)>touchSlop||Math.abs(this.y-y)>touchSlop){
isClick=false;
}
}
private onChangeListener changeListener;
private onClickListener click;
public void setClick(onClickListener click) {
this.click = click;
}
public void setChangeListener(onChangeListener changeListener) {
this.changeListener = changeListener;
}
public interface onChangeListener{
void onChange(boolean state);
}
public interface onClickListener{
void onClick(View view);
}
ClickRunAble clickRunable=new ClickRunAble();
class ClickRunAble implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
isClick=true;
}
}
}
package com.mints.wisdomclean.ui.widgets;
import android.app.ProgressDialog;
import android.content.Context;
public class CustomProgressDialog extends ProgressDialog {
public CustomProgressDialog(Context context) {
super(context);
setMessage("压缩中...");
setMax(100);
setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
setCanceledOnTouchOutside(false);
setCancelable(false);
}
@Override
public void dismiss() {
super.dismiss();
setProgress(0);
}
@Override
public void cancel() {
super.cancel();
setProgress(0);
}
}
package com.mints.wisdomclean.ui.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.mints.wisdomclean.R;
import com.mints.wisdomclean.utils.BubbleUtils;
/**
* DrawHook
* Created by Zane on 2015/3/4.
*/
public class DrawHookView extends View {
//绘制圆弧的进度值
private int progress = 0;
//线1的x轴
private int line1_x = 0;
//线1的y轴
private int line1_y = 0;
//线2的x轴
private int line2_x = 0;
//线2的y轴
private int line2_y = 0;
private final Paint paint;
public DrawHookView(Context context) {
this(context, null);
}
public DrawHookView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawHookView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawHookView, defStyle, 0);
int color = a.getColor(R.styleable.DrawHookView_dhv_color, Color.WHITE);
a.recycle();
paint = new Paint();
//设置画笔颜色
paint.setColor(getResources().getColor(R.color.white));
//设置圆弧的宽度
paint.setStrokeWidth(BubbleUtils.dp2px(3));
//设置圆弧为空心
paint.setStyle(Paint.Style.STROKE);
//消除锯齿
paint.setAntiAlias(true);
//圆润边
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setColor(color);
}
//绘制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
progress += 2;
//获取圆心的x坐标
int center = getWidth() / 2;
int center1 = center - getWidth() / 4;
//圆弧半径
int radius = getWidth() / 2 - 5;
//定义的圆弧的形状和大小的界限
RectF rectF = new RectF(center - radius - 1, center - radius - 1, center + radius + 1, center + radius + 1);
//根据进度画圆弧
canvas.drawArc(rectF, 180, 360 * progress / 100, false, paint);
/*
* 绘制对勾
*/
//先等圆弧画完,才话对勾
if (progress >= 100) {
if (line1_x < radius / 3) {
line1_x++;
line1_y++;
}
//画第一根线
canvas.drawLine(center1, center, center1 + line1_x, center + line1_y, paint);
if (line1_x == radius / 3) {
line2_x = line1_x;
line2_y = line1_y;
line1_x++;
line1_y++;
}
if (line1_x >= radius / 3 && line2_x <= radius) {
line2_x++;
line2_y--;
}
//画第二根线
canvas.drawLine(center1 + line1_x, center + line1_y, center1 + line2_x, center + line2_y, paint);
}
//每隔10毫秒界面刷新
postInvalidateDelayed(6);
}
}
package com.mints.wisdomclean.ui.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.GridView;
public class ExpandableGridView extends GridView {
boolean expanded = true;
public boolean isExpanded() {
return expanded;
}
public ExpandableGridView(Context context) {
super(context);
}
public ExpandableGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExpandableGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isExpanded()) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
}
package com.mints.wisdomclean.ui.widgets
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Movie
import android.os.Build
import android.util.AttributeSet
import android.view.View
import com.mints.wisdomclean.R
/**
* Created by Cuneyt on 4.10.2015.
* Updated by Cuneyt on 02.04.2019.
* Gifview
*/
class GifView @JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = R.styleable.CustomTheme_gifViewStyle
) : View(context, attrs, defStyle) {
private var movieMovieResourceId: Int = 0
private var movie: Movie? = null
private var movieStart: Long = 0
private var currentAnimationTime: Int = 0
private var movieLeft: Float = 0F
private var movieTop: Float = 0F
private var movieScale: Float = 0F
private var movieMeasuredMovieWidth: Int = 0
private var movieMeasuredMovieHeight: Int = 0
@Volatile
var isPaused: Boolean = false
private var isVisible = true
var gifResource: Int
get() = this.movieMovieResourceId
set(movieResourceId) {
this.movieMovieResourceId = movieResourceId
movie = Movie.decodeStream(resources.openRawResource(movieMovieResourceId))
requestLayout()
}
val isPlaying: Boolean
get() = !this.isPaused
init {
setViewAttributes(context, attrs, defStyle)
}
@SuppressLint("NewApi")
private fun setViewAttributes(context: Context, attrs: AttributeSet?, defStyle: Int) {
setLayerType(LAYER_TYPE_SOFTWARE, null)
val array = context.obtainStyledAttributes(
attrs,
R.styleable.GifView, defStyle, R.style.Widget_GifView
)
//-1 is default value
movieMovieResourceId = array.getResourceId(R.styleable.GifView_src, -1)
isPaused = array.getBoolean(R.styleable.GifView_paused, false)
array.recycle()
if (movieMovieResourceId != -1) {
movie = Movie.decodeStream(resources.openRawResource(movieMovieResourceId))
}
}
fun play() {
if (this.isPaused) {
this.isPaused = false
/**
* Calculate new movie start time, so that it resumes from the same
* frame.
*/
movieStart = android.os.SystemClock.uptimeMillis() - currentAnimationTime
invalidate()
}
}
fun pause() {
if (!this.isPaused) {
this.isPaused = true
invalidate()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (movie != null) {
val movieWidth = movie!!.width()
val movieHeight = movie!!.height()
/*
* Calculate horizontal scaling
*/
var scaleH = 1f
val measureModeWidth = MeasureSpec.getMode(widthMeasureSpec)
if (measureModeWidth != MeasureSpec.UNSPECIFIED) {
val maximumWidth = MeasureSpec.getSize(widthMeasureSpec)
if (movieWidth > maximumWidth * 2) {
scaleH = movieWidth.toFloat() / maximumWidth.toFloat()
} else {
scaleH = movieWidth.toFloat() / maximumWidth.toFloat()
}
// if (movieWidth > maximumWidth) {
// scaleH = movieWidth.toFloat() / maximumWidth.toFloat()
// }
}
/*
* calculate vertical scaling
*/
var scaleW = 1f
val measureModeHeight = MeasureSpec.getMode(heightMeasureSpec)
if (measureModeHeight != MeasureSpec.UNSPECIFIED) {
val maximumHeight = MeasureSpec.getSize(heightMeasureSpec)
if (movieHeight > maximumHeight * 2) {
scaleW = movieHeight.toFloat() / maximumHeight.toFloat()
} else {
scaleW = movieHeight.toFloat() / maximumHeight.toFloat()
}
// if (movieHeight > maximumHeight) {
// scaleW = movieHeight.toFloat() / maximumHeight.toFloat()
// }
}
// LogUtil.d("AAAAAAA" + scaleH)
// LogUtil.d("BBBBBB" + scaleW)
/*
* calculate overall scale
*/
if (scaleH > 1f || scaleW > 1f || scaleW < 0.5f || scaleH < 0.5f) {
movieScale = 1f / scaleH.coerceAtLeast(scaleW)
} else {
movieScale = 1f / scaleH.coerceAtMost(scaleW)
}
movieMeasuredMovieWidth = (movieWidth * movieScale).toInt()
movieMeasuredMovieHeight = (movieHeight * movieScale).toInt()
setMeasuredDimension(movieMeasuredMovieWidth, movieMeasuredMovieHeight)
} else {
/*
* No movie set, just set minimum available size.
*/
setMeasuredDimension(suggestedMinimumWidth, suggestedMinimumHeight)
}
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
/*
* Calculate movieLeft / movieTop for drawing in center
*/
movieLeft = (width - movieMeasuredMovieWidth) / 2f
movieTop = (height - movieMeasuredMovieHeight) / 2f
isVisible = visibility == VISIBLE
}
override fun onDraw(canvas: Canvas) {
if (movie != null) {
if (!isPaused) {
updateAnimationTime()
drawMovieFrame(canvas)
invalidateView()
} else {
drawMovieFrame(canvas)
}
}
}
/**
* Invalidates view only if it is isVisible.
* <br></br>
* [.postInvalidateOnAnimation] is used for Jelly Bean and higher.
*/
@SuppressLint("NewApi")
private fun invalidateView() {
if (isVisible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
postInvalidateOnAnimation()
} else {
invalidate()
}
}
}
/**
* Calculate current animation time
*/
private fun updateAnimationTime() {
val now = android.os.SystemClock.uptimeMillis()
if (movieStart == 0L) {
movieStart = now
}
var duration = movie!!.duration()
if (duration == 0) {
duration = DEFAULT_MOVIE_VIEW_DURATION
}
currentAnimationTime = ((now - movieStart) % duration).toInt()
}
/**
* Draw current GIF frame
*/
private fun drawMovieFrame(canvas: Canvas) {
movie!!.setTime(currentAnimationTime)
canvas.save()
canvas.scale(movieScale, movieScale)
movie!!.draw(canvas, movieLeft / movieScale, movieTop / movieScale)
canvas.restore()
}
@SuppressLint("NewApi")
override fun onScreenStateChanged(screenState: Int) {
super.onScreenStateChanged(screenState)
isVisible = screenState == SCREEN_STATE_ON
invalidateView()
}
@SuppressLint("NewApi")
override fun onVisibilityChanged(changedView: View, visibility: Int) {
super.onVisibilityChanged(changedView, visibility)
isVisible = visibility == VISIBLE
invalidateView()
}
override fun onWindowVisibilityChanged(visibility: Int) {
super.onWindowVisibilityChanged(visibility)
isVisible = visibility == VISIBLE
invalidateView()
}
companion object {
private const val DEFAULT_MOVIE_VIEW_DURATION = 1000
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class InterceptFrameLayout extends FrameLayout {
boolean isIntercept = true;
public boolean isInterceptTouch() {
return isIntercept;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return isIntercept;
}
public InterceptFrameLayout(Context context) {
super(context);
}
public InterceptFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InterceptFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void isIntercept(boolean isIntercept) {
this.isIntercept = isIntercept;
}
}
package com.mints.wisdomclean.ui.widgets;
import android.os.CountDownTimer;
import android.widget.TextView;
/**
* 简单 时,分,秒,毫秒倒计时
* <p>
* 精确到毫秒
*/
public class MilliCountDownTimer extends CountDownTimer {
// 默认倒计时间隔
private static final long DEFAULT_INTERVAL = 100L;
/**
* 秒,分,时对应的毫秒数
*/
private int sec = 1000, min = sec * 60, hr = min * 60;
/**
* 显示时间的视图
*/
private TextView tvDisplay;
/**
* 结束监听
*/
private static OnFinishListener onFinishListener;
/**
* @param millisInFuture 倒计时总时间 单位:毫秒
* The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval 倒计时间隔 单位:毫秒
* The interval along the way to receive
* {@link #onTick(long)} callbacks.
* @param tvDisplay 显示时间的视图
*/
public MilliCountDownTimer(long millisInFuture, long countDownInterval, TextView tvDisplay) {
super(millisInFuture, countDownInterval);
this.tvDisplay = tvDisplay;
}
/**
* @param millisInFuture 倒计时总时间 单位:毫秒
* The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param tvDisplay 显示时间的视图
*/
public MilliCountDownTimer(long millisInFuture, TextView tvDisplay) {
super(millisInFuture, DEFAULT_INTERVAL);
this.tvDisplay = tvDisplay;
}
/**
* 每一次间隔时间到后调用
*
* @param millisUntilFinished 剩余总时间 单位:毫秒
*/
@Override
public void onTick(long millisUntilFinished) {
// 剩余的小时,分钟,秒,毫秒
long lHr = millisUntilFinished / hr;
long lMin = (millisUntilFinished - lHr * hr) / min;
long lSec = (millisUntilFinished - lHr * hr - lMin * min) / sec;
long lMs = millisUntilFinished - lHr * hr - lMin * min - lSec * sec;
String strLHr = getTime(lHr);
String strLMin = getTime(lMin);
String strLSec = getTime(lSec);
String strLMs = getMs(lMs);
// 依次拼接时间 时:分:秒:毫秒
tvDisplay.setText(strLHr + "时" + strLMin + "分" + strLSec + "秒" + strLMs);
}
/**
* 根据毫秒换算成相应单位后是否大于10来返回相应时间
*/
private String getTime(long time) {
return time > 10 ? String.valueOf(time) : "0" + time;
}
/**
* 获取毫秒
*/
private String getMs(long time) {
String strMs = String.valueOf(time);
return time > 100 ? strMs.substring(0, strMs.length() - 1) : "00";
}
/**
* 结束监听,可以在倒计时结束时做一些事
*/
public interface OnFinishListener {
void onFinish();
}
/**
* 设置结束监听
*
* @param onFinishListener 结束监听对象
*/
public MilliCountDownTimer setOnFinishListener(OnFinishListener onFinishListener) {
MilliCountDownTimer.onFinishListener = onFinishListener;
return this;
}
/**
* 倒计时结束时调用
*/
@Override
public void onFinish() {
tvDisplay.setText("00:00:00");
if (onFinishListener != null)
onFinishListener.onFinish();
}
}
package com.mints.wisdomclean.ui.widgets
import android.app.Dialog
import android.content.Context
import android.view.*
import android.widget.LinearLayout
import android.widget.TextView
import com.mints.wisdomclean.R
class PhotoDialog(context: Context) : Dialog(context, R.style.dialog) {
private val llDialogCamera: LinearLayout
private val llDialogAlbum: LinearLayout
private val tvDialogCancel: TextView
private var mOnChangePhotoListener: OnChangePhotoListener? = null
init {
setContentView(R.layout.dialog_photo)
// 设置window属性
window?.let {
val lp = it.attributes
lp.gravity = Gravity.BOTTOM
lp.width = WindowManager.LayoutParams.MATCH_PARENT
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
lp.windowAnimations = R.style.DialogAnimBottom
it.attributes = lp
}
// 设置外部不可关闭
// setCancelable(false)
// setCanceledOnTouchOutside(false)
setOnKeyListener { _, i, _ ->
i == KeyEvent.KEYCODE_BACK
}
llDialogCamera = findViewById<View>(R.id.llDialogCamera) as LinearLayout
llDialogAlbum = findViewById<View>(R.id.llDialogAlbum) as LinearLayout
tvDialogCancel = findViewById<View>(R.id.tvDialogCancel) as TextView
llDialogCamera.setOnClickListener {
mOnChangePhotoListener?.onChangePhoto(0)
}
llDialogAlbum.setOnClickListener {
mOnChangePhotoListener?.onChangePhoto(1)
}
tvDialogCancel.setOnClickListener {
dismiss()
}
}
fun setOnChangePhotoListener(onChangePhotoListener: OnChangePhotoListener): PhotoDialog {
this.mOnChangePhotoListener = onChangePhotoListener
return this
}
interface OnChangePhotoListener {
fun onChangePhoto(status: Int)
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
class PhotoWrpView : View {
constructor(context: Context) : this(context, null)
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)
constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
private var mPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var mTextPaint: TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
private var mWaterMarkPaint: TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
private var mWaterMarkOnOff = false
private var mBitmap: Bitmap? = null
private var mWidth = 0f
private var mHeight = 0f
private val mPaintWidth = 2f
private var mCurrentPhotoInch = PHOTO_INCH_ONE
private var mTopStr: String? = null
private var mRightStr: String? = null
private var mBottomStr: String? = null
private var mLeftStr: String? = null
private var mArr: IntArray? = null
companion object {
/**
* 一寸:25mm*35mm 295*413px
* 二寸:35mm*49mm 413*579px
* 小二寸:35mm*45mm 413*531px
* 大一寸:33mm*48mm 390*567px
*/
const val PHOTO_INCH_ONE = 1 // 一寸
const val PHOTO_INCH_TWO = 2 // 二寸
const val PHOTO_INCH_BIG_ONE = 3 // 大一寸
const val PHOTO_INCH_SMALL_TWO = 5 // 小二寸
const val WATER_MARK_STR = "保存后不显示此文字"
}
init {
mPaint.strokeWidth = mPaintWidth
mPaint.color = Color.GRAY
mPaint.style = Paint.Style.STROKE
mTextPaint.strokeWidth = 1f
mTextPaint.textSize = dp2px(context, 12f)
mTextPaint.textAlign = Paint.Align.CENTER
mTextPaint.color = Color.GRAY
mTextPaint.style = Paint.Style.FILL
mWaterMarkPaint.strokeWidth = 10f
mWaterMarkPaint.textSize = dp2px(context, 18f)
mWaterMarkPaint.color = Color.GRAY
mWaterMarkPaint.style = Paint.Style.FILL
}
private fun dp2px(context: Context, pxVal: Float): Float {
return pxVal * context.resources.displayMetrics.scaledDensity + 0.5f
}
/**
*
* @param bitmap
* @param photoInch
*/
fun setBitmap(bitmap: Bitmap?, photoInch: Int) {
if (bitmap == null) {
return
}
mCurrentPhotoInch = photoInch
mArr = calculatePosition()
//获取图片的宽高
mBitmap = getNewBitmap(bitmap, mArr!![0], mArr!![1])
invalidate()
}
private fun getNewBitmap(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap? {
// 获得图片的宽高.
val width = bitmap.width
val height = bitmap.height
// 计算缩放比例.
val scaleWidth = newWidth.toFloat() / width
val scaleHeight = newHeight.toFloat() / height
// 取得想要缩放的matrix参数.
val matrix = Matrix()
matrix.postScale(scaleWidth, scaleHeight)
// 得到新的图片.
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)
}
fun turnOnWaterMark(onOff: Boolean) {
mWaterMarkOnOff = onOff
invalidate()
}
private fun calculatePosition(): IntArray {
var scaleWidth = 0
var scaleHeight = 0
when (mCurrentPhotoInch) {
PHOTO_INCH_ONE -> {
mTopStr = "295px"
mRightStr = "413px"
mBottomStr = "25mm"
mLeftStr = "35mm"
scaleWidth = (mWidth * 0.6).toInt()
scaleHeight = (scaleWidth * 1.4).toInt()
}
PHOTO_INCH_TWO -> {
mTopStr = "413px"
mRightStr = "579px"
mBottomStr = "35mm"
mLeftStr = "49mm"
scaleWidth = (mWidth * 0.6).toInt()
scaleHeight = (scaleWidth * 1.45).toInt()
}
PHOTO_INCH_BIG_ONE -> {
mTopStr = "390px"
mRightStr = "567px"
mBottomStr = "33mm"
mLeftStr = "48mm"
scaleWidth = (mWidth * 0.6).toInt()
scaleHeight = (scaleWidth * 1.45).toInt()
}
PHOTO_INCH_SMALL_TWO -> {
mTopStr = "413px"
mRightStr = "531px"
mBottomStr = "35mm"
mLeftStr = "45mm"
scaleWidth = (mWidth * 0.6).toInt()
scaleHeight = (scaleWidth * 1.4).toInt()
}
}
return intArrayOf(scaleWidth, scaleHeight)
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (mBitmap == null) return
val arr = mArr!!
// 计算左边位置
val left = (mWidth - arr[0]) / 2
// 计算上边位置
val top = (mHeight - arr[1]) / 2
val destRect = Rect(left.toInt(), top.toInt(), (left + arr[0]).toInt(), (top + arr[1]).toInt())
val srcRect = Rect(0, 0, arr[0], arr[1])
canvas.drawBitmap(mBitmap!!, srcRect, destRect, mPaint)
// 上方
canvas.drawLine(left, (top - 50), left, top, mPaint)
canvas.drawLine(left, (top - 40), (left + arr[0] / 3), (top - 40), mPaint)
canvas.drawLine((left + arr[0] / 3 * 2), (top - 40), (left + arr[0]), (top - 40), mPaint)
canvas.drawLine((left + arr[0]), (top - 50), (left + arr[0]), top, mPaint)
canvas.drawText(mTopStr!!, mWidth / 2, (top - 30), mTextPaint)
// 右方
canvas.drawLine((left + arr[0]), top, (left + arr[0] + 50), top, mPaint)
canvas.drawLine((left + arr[0] + 40), top, (left + arr[0] + 40), (top + arr[1] / 3), mPaint)
canvas.drawLine((left + arr[0]), (top + arr[1]), (left + arr[0] + 50), (top + arr[1]), mPaint)
canvas.drawLine((left + arr[0] + 40), (top + arr[1] / 3 * 2), (left + arr[0] + 40), (top + arr[1]), mPaint)
drawAngleText(canvas, mRightStr!!, (left + arr[0] + 50), mHeight / 2, mTextPaint, -90f)
// 下方
canvas.drawLine(left, (top + arr[1]), left, (top + arr[1] + 50), mPaint)
canvas.drawLine(left, (top + arr[1] + 40), (left + arr[0] / 3), (top + arr[1] + 40), mPaint)
canvas.drawLine((left + arr[0] / 3 * 2), (top + arr[1] + 40), (left + arr[0]), (top + arr[1] + 40), mPaint)
canvas.drawLine((left + arr[0]), (top + arr[1]), (left + arr[0]), (top + arr[1] + 50), mPaint)
canvas.drawText(mBottomStr!!, mWidth / 2, (top + arr[1] + 50), mTextPaint)
// 左方
canvas.drawLine((left - 50), top, left, top, mPaint)
canvas.drawLine((left - 40), top, (left - 40), (top + arr[1] / 3), mPaint)
canvas.drawLine((left - 40), (top + arr[1] / 3 * 2), (left - 40), (top + arr[1]), mPaint)
canvas.drawLine((left - 50), (top + arr[1]), left, (top + arr[1]), mPaint)
drawAngleText(canvas, mLeftStr!!, (left - 30), mHeight / 2, mTextPaint, -90f)
// if (mWaterMarkOnOff) {
drawAngleText(canvas, WATER_MARK_STR, left + arr[0] / 6, top + arr[1] / 6 * 3, mWaterMarkPaint, -30f)
drawAngleText(canvas, WATER_MARK_STR, left + arr[0] / 6, top + arr[1] / 6 * 4, mWaterMarkPaint, -30f)
drawAngleText(canvas, WATER_MARK_STR, left + arr[0] / 6, top + arr[1] / 6 * 5, mWaterMarkPaint, -30f)
// }
}
private fun drawAngleText(canvas: Canvas, text: String, x: Float, y: Float, paint: Paint, angle: Float) {
if (angle != 0f) {
canvas.rotate(angle, x, y)
}
canvas.drawText(text, x, y, paint)
if (angle != 0f) {
canvas.rotate(-angle, x, y)
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val minimumWidth = suggestedMinimumWidth
val minimumHeight = suggestedMinimumHeight
val width = measureWidth(minimumWidth, widthMeasureSpec)
val height = measureHeight(minimumHeight, heightMeasureSpec)
mWidth = width.toFloat()
mHeight = height.toFloat()
setMeasuredDimension(width, height)
}
private fun measureWidth(defaultWidth: Int, measureSpec: Int): Int {
var measureWidth = defaultWidth
val specMode = MeasureSpec.getMode(measureSpec)
val specSize = MeasureSpec.getSize(measureSpec)
when (specMode) {
MeasureSpec.AT_MOST -> {
measureWidth = specSize + paddingLeft + paddingRight
}
MeasureSpec.EXACTLY -> {
measureWidth = specSize
}
MeasureSpec.UNSPECIFIED -> {
measureWidth = defaultWidth.coerceAtLeast(specSize)
}
}
return measureWidth
}
private fun measureHeight(defaultHeight: Int, measureSpec: Int): Int {
var measureHeight = defaultHeight
val specMode = MeasureSpec.getMode(measureSpec)
val specSize = MeasureSpec.getSize(measureSpec)
when (specMode) {
MeasureSpec.AT_MOST -> {
measureHeight = specSize + paddingTop + paddingBottom
}
MeasureSpec.EXACTLY -> {
measureHeight = specSize
}
MeasureSpec.UNSPECIFIED -> {
measureHeight = defaultHeight.coerceAtLeast(specSize)
}
}
return measureHeight
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatButton;
import androidx.core.content.ContextCompat;
import com.mints.wisdomclean.R;
public class ProgressButton extends AppCompatButton {
private float mCornerRadius = 15;
private float mProgressMargin = 0;
private boolean mFinish;
private int mProgress;
private int mMaxProgress = 100;
private int mMinProgress = 0;
private boolean isCycle = false;
private GradientDrawable mDrawableButton;
private GradientDrawable mDrawableProgressBackground;
private GradientDrawable mDrawableProgress;
public ProgressButton(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public ProgressButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attrs) {
mDrawableProgressBackground = new GradientDrawable();
mDrawableProgress = new GradientDrawable();
mDrawableButton = new GradientDrawable();
int defaultButtonColor = ContextCompat.getColor(context, R.color.color_main);
int defaultProgressColor = ContextCompat.getColor(context, R.color.color_10000000);
int defaultBackColor = ContextCompat.getColor(context, R.color.color_main);
TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.ProgressButton);
try {
mProgressMargin = attr.getDimension(R.styleable.ProgressButton_progressMargin, mProgressMargin);
mCornerRadius = attr.getDimension(R.styleable.ProgressButton_cornerRadius, mCornerRadius);
//Get custom normal color
int buttonColor = attr.getColor(R.styleable.ProgressButton_buttonColor, defaultButtonColor);
//Set normal color
mDrawableButton.setColor(buttonColor);
//Get custom progress background color
int progressBackColor = attr.getColor(R.styleable.ProgressButton_progressBackColor, defaultBackColor);
//Set progress background drawable color
mDrawableProgressBackground.setColor(progressBackColor);
//Get custom progress color
int progressColor = attr.getColor(R.styleable.ProgressButton_progressColor, defaultProgressColor);
//Set progress drawable color
mDrawableProgress.setColor(progressColor);
//Get default progress
mProgress = attr.getInteger(R.styleable.ProgressButton_progress, mProgress);
//Get minimum progress
mMinProgress = attr.getInteger(R.styleable.ProgressButton_minProgress, mMinProgress);
//Get maximize progress
mMaxProgress = attr.getInteger(R.styleable.ProgressButton_maxProgress, mMaxProgress);
} finally {
attr.recycle();
}
//Set corner radius
mDrawableButton.setCornerRadius(mCornerRadius);
mDrawableProgressBackground.setCornerRadius(mCornerRadius);
mDrawableProgress.setCornerRadius(mCornerRadius - mProgressMargin);
setBackgroundDrawable(mDrawableButton);
mFinish = false;
}
@Override
protected void onDraw(Canvas canvas) {
if (isCycle) {
if (mProgress >= 100) {
mProgress = 0;
}
mProgress++;
postInvalidateDelayed(10);
}
if (mProgress > mMinProgress && mProgress <= mMaxProgress) {
float progressWidth =
(float) getMeasuredWidth() * ((float) (mProgress - mMinProgress) / mMaxProgress - mMinProgress);
if (progressWidth < mCornerRadius * 2) {
progressWidth = mCornerRadius * 2;
}
mDrawableProgress.setBounds((int) mProgressMargin, (int) mProgressMargin,
(int) (progressWidth - mProgressMargin), getMeasuredHeight() - (int) mProgressMargin);
mDrawableProgress.draw(canvas);
if (mProgress == mMaxProgress) {
setBackgroundDrawable(mDrawableButton);
// mFinish = true;
}
}
super.onDraw(canvas);
}
public void startCycle() {
isCycle = true;
mProgress = 0;
invalidate();
}
public void pauseCycle() {
isCycle = false;
mProgress = 0;
invalidate();
}
/**
* Set current progress
*/
public void setProgress(int progress) {
if (!mFinish) {
mProgress = progress;
setBackgroundDrawable(mDrawableProgressBackground);
invalidate();
}
}
public void setMaxProgress(int maxProgress) {
mMaxProgress = maxProgress;
}
public void setMinProgress(int minProgress) {
mMinProgress = minProgress;
}
public void reset() {
mFinish = false;
mProgress = mMinProgress;
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.mints.wisdomclean.R;
public class RoundAngleImageView extends ImageView {
private Paint paint;
/**
* 个人理解是
*
* 这两个都是画圆的半径
*/
private int roundWidth = 20;
private int roundHeight = 20;
private Paint paint2;
public RoundAngleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
public RoundAngleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public RoundAngleImageView(Context context) {
super(context);
init(context, null);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundAngleImageView);
roundWidth = a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundWidth, roundWidth);
roundHeight = a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundHeight, roundHeight);
} else {
float density = context.getResources().getDisplayMetrics().density;
roundWidth = (int) (roundWidth * density);
roundHeight = (int) (roundHeight * density);
}
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
paint2 = new Paint();
paint2.setXfermode(null);
}
@Override
public void draw(Canvas canvas) {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas2 = new Canvas(bitmap);
super.draw(canvas2);
drawLiftUp(canvas2);
drawLiftDown(canvas2);
drawRightUp(canvas2);
drawRightDown(canvas2);
canvas.drawBitmap(bitmap, 0, 0, paint2);
bitmap.recycle();
}
private void drawLiftUp(Canvas canvas) {
Path path = new Path();
path.moveTo(0, roundHeight);
path.lineTo(0, 0);
path.lineTo(roundWidth, 0);
path.arcTo(new RectF(0, 0, roundWidth * 2, roundHeight * 2), -90, -90);
path.close();
canvas.drawPath(path, paint);
}
private void drawLiftDown(Canvas canvas) {
Path path = new Path();
path.moveTo(0, getHeight() - roundHeight);
path.lineTo(0, getHeight());
path.lineTo(roundWidth, getHeight());
path.arcTo(new RectF(0, getHeight() - roundHeight * 2, roundWidth * 2, getHeight()), 90, 90);
path.close();
canvas.drawPath(path, paint);
}
private void drawRightDown(Canvas canvas) {
Path path = new Path();
path.moveTo(getWidth() - roundWidth, getHeight());
path.lineTo(getWidth(), getHeight());
path.lineTo(getWidth(), getHeight() - roundHeight);
path.arcTo(new RectF(getWidth() - roundWidth * 2, getHeight() - roundHeight * 2, getWidth(), getHeight()), -0, 90);
path.close();
canvas.drawPath(path, paint);
}
private void drawRightUp(Canvas canvas) {
Path path = new Path();
path.moveTo(getWidth(), roundHeight);
path.lineTo(getWidth(), 0);
path.lineTo(getWidth() - roundWidth, 0);
path.arcTo(new RectF(getWidth() - roundWidth * 2, 0, getWidth(), 0 + roundHeight * 2), -90, 90);
path.close();
canvas.drawPath(path, paint);
}
}
package com.mints.wisdomclean.ui.widgets
import android.content.Context
import android.util.AttributeSet
class RoundCheckBox : androidx.appcompat.widget.AppCompatCheckBox {
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, androidx.appcompat.R.attr.radioButtonStyle)
constructor(context: Context) : this(context, null)
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
public class WaveView extends View {
private int width = 0;
private int height = 0;
private int baseLine = 0;// 基线,用于控制水位上涨的,这里是写死了没动,你可以不断的设置改变。
private Paint mPaint;
private Paint mCirclePaint;
private TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private int waveHeight = 26;// 波浪的最高度
private int waveWidth;//波长
private float offset = 0f;//偏移量
private String mForegroundColor = "#F61F03";
private String mProgressStr = "72%";
private Path mCirclePath;
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public void setProgressStr(String progressStr) {
this.mProgressStr = progressStr;
invalidate();
}
public void setForegroundColor(String foregroundColor) {
this.mForegroundColor = foregroundColor;
invalidate();
}
/**
* 不断的更新偏移量,并且循环。
*/
private void updateXControl() {
//设置一个波长的偏移
ValueAnimator mAnimator = ValueAnimator.ofFloat(0, waveWidth);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(animation -> {
float animatorValue = (float) animation.getAnimatedValue();
offset = animatorValue;//不断的设置偏移量,并重画
postInvalidate();
});
mAnimator.setDuration(1000);
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.WHITE);
canvas.drawPath(mCirclePath, mPaint);
canvas.save();
canvas.clipPath(mCirclePath);
mPaint.setColor(Color.WHITE);
canvas.drawPath(getPath(), mPaint);
mPaint.setColor(Color.parseColor(mForegroundColor));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(getPath(), mPaint);
mCirclePaint.setColor(Color.parseColor(mForegroundColor));
canvas.drawCircle(waveWidth / 2, waveWidth / 2, waveWidth / 2 - 2f, mCirclePaint);
canvas.drawText(mProgressStr, waveWidth / 2, waveWidth / 2 + 10, mTextPaint);
canvas.restore();
}
//初始化paint,没什么可说的。
private void initView() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mCirclePaint = new Paint();
mCirclePaint.setStrokeWidth(4f);
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setAntiAlias(true);
mCirclePath = new Path();
mTextPaint.setStrokeWidth(1f);
mTextPaint.setTextSize(dp2px(getContext(), 12f));
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
width = getMeasuredWidth();//获取屏幕宽度
height = getMeasuredHeight();//获取屏幕高度
waveWidth = width;
baseLine = height / 2 - 10;
updateXControl();
int circleRadius = height < width ? height / 2 : width / 2;
mCirclePath.addCircle(width / 2, height / 2, circleRadius, Path.Direction.CCW);
}
/**
* 核心代码,计算path
*
* @return
*/
private Path getPath() {
int itemWidth = waveWidth / 2;//半个波长
Path mPath = new Path();
mPath.moveTo(-itemWidth * 3, baseLine);//起始坐标
//核心的代码就是这里
for (int i = -3; i < 2; i++) {
int startX = i * itemWidth;
mPath.quadTo(
startX + itemWidth / 2 + offset,//控制点的X,(起始点X + itemWidth/2 + offset)
getWaveHeight(i),//控制点的Y
startX + itemWidth + offset,//结束点的X
baseLine//结束点的Y
);//只需要处理完半个波长,剩下的有for循环自已就添加了。
}
//下面这三句话很重要,它是形成了一封闭区间,让曲线以下的面积填充一种颜色,大家可以把这3句话注释了看看效果。
mPath.lineTo(width, height);
mPath.lineTo(0, height);
mPath.close();
return mPath;
}
//奇数峰值是正的,偶数峰值是负数
private int getWaveHeight(int num) {
if (num % 2 == 0) {
return baseLine + waveHeight;
}
return baseLine - waveHeight;
}
private float dp2px(Context context, Float pxVal) {
return pxVal * context.getResources().getDisplayMetrics().scaledDensity + 0.5f;
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.widgets.applock;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.view.View;
import com.mints.wisdomclean.utils.BubbleUtils;
@SuppressLint("ViewConstructor")
public class GestureView extends View {
private static final String TAG = GestureView.class.getName();
/**
* GestureLockView的三种状态
*/
enum Mode {
STATUS_NO_FINGER, STATUS_FINGER_ON, STATUS_FINGER_UP;
}
/**
* GestureLockView的当前状态
*/
private Mode mCurrentStatus = Mode.STATUS_NO_FINGER;
/**
* 宽度
*/
private int mWidth;
/**
* 高度
*/
private int mHeight;
/**
* 外圆半径
*/
private int mRadius;
/**
* 画笔的宽度
*/
private int mStrokeWidth = 2;
/**
* 圆心坐标
*/
private int mCenterX;
private int mCenterY;
private Paint mPaint;
/**
* 箭头(小三角最长边的一半长度 = mArrawRate * mWidth / 2 )
*/
private float mArrowRate = 0.333f;
private int mArrowDegree = -1;
private Path mArrowPath;
/**
* 内圆的半径 = mInnerCircleRadiusRate * mRadus
*/
private float mInnerCircleRadiusRate = 0.25f;
/**
* 四个颜色,可由用户自定义,初始化时由GestureLockViewGroup传入
*/
private int mColorNoFingerInner;
private int mColorNoFingerOutter;
private int mColorFingerOn;
private int mColorFingerUpMatched;
private int mColorFingerUpNotMatched;
private boolean matched;
public GestureView(Context context, int colorNoFingerInner, int colorNoFingerOutter, int colorFingerOn, int colorFingerUpMatched, int colorFingerUpNotMatched) {
super(context);
this.mColorNoFingerInner = colorNoFingerInner;
this.mColorNoFingerOutter = colorNoFingerOutter;
this.mColorFingerOn = colorFingerOn;
this.mColorFingerUpMatched = colorFingerUpMatched;
this.mColorFingerUpNotMatched = colorFingerUpNotMatched;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mArrowPath = new Path();
mStrokeWidth = BubbleUtils.dp2px(1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
// 取长和宽中的小值
mWidth = Math.min(mWidth, mHeight);
mCenterX = mCenterY = mWidth / 2;
mRadius = mWidth / 3;
mRadius -= mStrokeWidth / 2;
// 绘制三角形,初始时是个默认箭头朝上的一个等腰三角形,用户绘制结束后,根据由两个GestureLockView决定需要旋转多少度
float mArrowLength = mWidth / 2 * mArrowRate;
mArrowPath.moveTo(mWidth / 2, mStrokeWidth + 2);
mArrowPath.lineTo(mWidth / 2 - mArrowLength, mStrokeWidth + 2
+ mArrowLength);
mArrowPath.lineTo(mWidth / 2 + mArrowLength, mStrokeWidth + 2
+ mArrowLength);
mArrowPath.close();
mArrowPath.setFillType(Path.FillType.WINDING);
}
@Override
protected void onDraw(Canvas canvas) {
switch (mCurrentStatus) {
case STATUS_FINGER_ON:
// 绘制外圆
mPaint.setStyle(Style.FILL); //
mPaint.setColor(0x33ffffff);
mPaint.setStrokeWidth(mStrokeWidth);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
// 绘制外圆环
mPaint.setStyle(Style.STROKE);
mPaint.setColor(0x99fdfdfd);
mPaint.setStrokeWidth(mStrokeWidth);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
// 绘制内圆
mPaint.setStyle(Style.FILL);
mPaint.setColor(mColorFingerOn);
canvas.drawCircle(mCenterX, mCenterY, mRadius
* mInnerCircleRadiusRate, mPaint);
break;
case STATUS_FINGER_UP:
if (matched) {
// 绘制外圆环
mPaint.setColor(mColorFingerUpMatched);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
} else {
// 外圆
mPaint.setStyle(Style.FILL);
mPaint.setColor(0x33ff5c5c);
mPaint.setStrokeWidth(mStrokeWidth);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
// 外圆环
mPaint.setColor(0x99e3362d);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
mPaint.setColor(mColorFingerUpNotMatched);
}
// 绘制内圆
mPaint.setStyle(Style.FILL);
canvas.drawCircle(mCenterX, mCenterY, mRadius
* mInnerCircleRadiusRate, mPaint);
// drawArrow(canvas);
break;
case STATUS_NO_FINGER:
// 绘制外圆
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setColor(mColorNoFingerOutter);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
// 绘制内圆
mPaint.setStyle(Style.FILL);
mPaint.setColor(mColorNoFingerInner);
canvas.drawCircle(mCenterX, mCenterY, mRadius
* mInnerCircleRadiusRate, mPaint);
break;
}
}
/**
* 绘制箭头
*
* @param canvas
*/
private void drawArrow(Canvas canvas) {
if (mArrowDegree != -1) {
mPaint.setStyle(Style.FILL);
canvas.save();
canvas.rotate(mArrowDegree, mCenterX, mCenterY);
canvas.drawPath(mArrowPath, mPaint);
canvas.restore();
}
}
public void setMatched(boolean matched) {
this.matched = matched;
}
/**
* 设置当前模式并重绘界面
*
* @param mode
*/
public void setMode(Mode mode) {
this.mCurrentStatus = mode;
invalidate();
}
public void setArrowDegree(int degree) {
this.mArrowDegree = degree;
}
public int getArrowDegree() {
return this.mArrowDegree;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment