Android 自定义ProgressDialog加载中(加载圈)攻略
在 Android 开发中,我们常常需要向用户展示加载中的提示,在这种场景下,使用 ProgressDialog 是非常常见的方式。但是,android 自带的 ProgressDialog 的样式有限,无法满足一些特殊的需求。本文将会介绍如何自定义 ProgressDialog,以实现更为灵活的加载中提示。
1. 使用自定义布局实现自定义ProgressDialog
1.1 编写布局文件
首先需要准备一个用于自定义 ProgressDialog 的布局文件。该布局文件可以使用 ProgressBar 来实现加载圈的效果,同时还可以添加一些文字说明等内容以更加清晰地告诉用户当前的状态。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerInParent="true" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progressBar"
android:text="Loading..."
android:layout_centerHorizontal="true"
android:textSize="16sp"/>
</RelativeLayout>
1.2 使用自定义布局实现ProgressDialog
接下来,在需要使用 ProgressDialog 的地方,我们就可以通过 LayoutInflater 来加载我们刚才准备好的布局文件,并将其设置到自定义的 ProgressDialog 中。
public class MyProgressDialog extends Dialog {
private ProgressBar mProgressBar;
private TextView mTextView;
public MyProgressDialog(Context context) {
super(context, R.style.MyProgressDialog);
setContentView(R.layout.layout_my_progress_dialog);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mTextView = (TextView) findViewById(R.id.textView);
}
/**
* 设置加载中文字
*
* @param message 加载中文字内容
*/
public void setMessage(String message) {
mTextView.setText(message);
}
}
接下来就可以在需要的地方使用自定义的 ProgressDialog 了,例如:
MyProgressDialog dialog = new MyProgressDialog(this);
dialog.setMessage("正在加载,请稍候...");
dialog.show();
2. 自定义ProgressDialog之CircleProgressView
2.1 CircleProgressView 的设计思路
使用自定义布局的方式实现自定义 ProgressDialog,虽然灵活性较高,但需要手动实现加载圈的绘制,较为复杂。在这里,我们推荐另一种实现方式:使用自定义 View 来实现加载圈的绘制。这种方式的好处是我们可以更方便、更灵活地设计出不同风格的加载圈。接下来,我们将实现一个 CircleProgressView 的自定义 View。这个 CircleProgressView 是由一个圆环和一个指针组成的,进度的变化将会导致指针的旋转。
2.2 CircleProgressView 的实现步骤
首先,我们需要实现自定义 View 的基本功能,包括构造函数、测量、布局和绘制等。然后,根据需求增加进度值设置的接口和进度值变化时指针旋转的逻辑。
① 自定义 View 的构造方法
public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
// 获取自定义属性(圆环颜色和宽度,指针颜色和长度)
TypedArray ta = context.obtainStyledAttributes(R.styleable.CircleProgressView);
mRingColor = ta.getColor(R.styleable.CircleProgressView_ringColor, Color.parseColor("#e0e0e0"));
mRingWidth = ta.getDimensionPixelSize(R.styleable.CircleProgressView_ringWidth, Utils.dp2px(context, 3));
mPointerColor = ta.getColor(R.styleable.CircleProgressView_pointerColor, Color.WHITE);
mPointerLength = ta.getDimensionPixelSize(R.styleable.CircleProgressView_pointerLength, Utils.dp2px(context, 22));
ta.recycle();
// 初始化画笔
mRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRingPaint.setStyle(Paint.Style.STROKE);
mRingPaint.setStrokeWidth(mRingWidth);
mRingPaint.setColor(mRingColor);
// 初始化旋转动画
mRotateAnim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mRotateAnim.setInterpolator(new LinearInterpolator());
mRotateAnim.setDuration(1000);
mRotateAnim.setRepeatCount(Animation.INFINITE);
mRotateAnim.setRepeatMode(Animation.RESTART);
mRotateAnim.setInterpolator(new LinearInterpolator());
}
② 重写 onMeasure() 方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width, height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width = mPointerLength * 2 + mRingWidth + getPaddingLeft() + getPaddingRight();
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = mPointerLength * 2 + mRingWidth + getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(width, height);
}
③ 重写 onDraw() 方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int pointerX = centerX + (int) (mPointerLength * Math.cos(Math.toRadians(mProgress * 3.6 - 90)));
int pointerY = centerY + (int) (mPointerLength * Math.sin(Math.toRadians(mProgress * 3.6 - 90)));
canvas.drawCircle(centerX, centerY, getWidth() / 2 - mRingWidth / 2, mRingPaint);
mPointerPaint.setColor(mPointerColor);
mPointerPaint.setStrokeWidth(Utils.dp2px(getContext(), 3));
mPointerPaint.setStyle(Paint.Style.FILL);
canvas.drawLine(centerX, centerY, pointerX, pointerY, mPointerPaint);
}
④ 实现进度变化与指针旋转的逻辑
/**
* 设置进度值
*
* @param progress 进度值(0-100)
*/
public void setProgress(int progress) {
mProgress = progress;
invalidate();
}
/**
* 开始旋转动画
*/
public void startAnimate() {
clearAnimation();
startAnimation(mRotateAnim);
}
/**
* 停止旋转动画
*/
public void stopAnimate() {
clearAnimation();
}
2.3 在布局文件中使用 CircleProgressView
使用 CircleProgressView 的方式与使用普通 View 无异,只需将 CircleProgressView 添加到布局文件的相应位置即可。
<com.example.mylibrary.widget.CircleProgressView
android:id="@+id/progressView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
app:pointerColor="#ff0000"
app:pointerLength="30dp"
app:ringColor="#e0e0e0"
app:ringWidth="4dp" />
2.4 在代码中使用 CircleProgressView
和普通 View 一样,可以在代码中通过 findViewById 来获取 CircleProgressView 实例,并调用相应的方法来动态修改进度值和指针的样式。
CircleProgressView progressView = findViewById(R.id.progressView);
progressView.setProgress(50);
progressView.startAnimate();
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Adnroid 自定义ProgressDialog加载中(加载圈) - Python技术站