android 自定义控件---简单的加载View
2017-06-06 11:03
316 查看
项目需要写了一个简单的加载View,看效果:
秒针在右半圆(-90度到90度)慢速旋转,左半圆(90度到270度)快速旋转。
由于注释写的已经很详细了,直接上代码:
Loading:/** * loading 工具类 * * @author zyc * created at 2017/6/5 11:39 */ public class Loading extends View { // 圆环画笔 private Paint mCirclePaint; // 时针画笔 private Paint mTimePaint; // 半径 50px private int radius = 50; // 秒针长度 private int secondLength = 60; // 不动针长度 private int minuteLength = 30; // 旋转状态--默认true private boolean rotate = true; // 变化角度--初始12点钟方向 private int changeAn = -90; // 属性动画 private ValueAnimator valueAnimator; // 圆心坐标x private int xCenter = 100; // 圆心坐标y private int yCenter = 100; // 旋转终点x坐标 private int xStop = xCenter; // 旋转终点y坐标 private int yStop = secondLength; public Context context; public Loading(Context context) { this(context, null); } public Loading(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.context = context; initView(); } /** * 初始化工具 */ private void initView() { //初始化半径 radius = dip2px(16); // 初始化秒针长度 secondLength = dip2px(14); // 初始化分针长度 minuteLength = dip2px(10); // 画圆画笔 if (mCirclePaint == null) { mCirclePaint = new Paint(); } mCirclePaint.setDither(true); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(getResources().getColor(android.R.color.white)); mCirclePaint.setStyle(Paint.Style.STROKE); //stroke 宽度 mCirclePaint.setStrokeWidth(3); // 时针画笔--画线 if (mTimePaint == null) { mTimePaint = new Paint(); } mTimePaint.setDither(true); mTimePaint.setAntiAlias(true); mTimePaint.setColor(getResources().getColor(android.R.color.white)); mTimePaint.setStyle(Paint.Style.FILL); //stroke 宽度 mTimePaint.setStrokeWidth(5); if (rotate){ startRotate(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(100, 100); } else if (widthSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(100, heightSpecSize); } else if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSpecSize, 100); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 取中心位置 yCenter = xCenter = getWidth() / 2; // 画圆 canvas.drawCircle(xCenter, yCenter, radius, mCirclePaint); // 画秒针--动 if (rotate) { canvas.drawLine(xCenter, yCenter, xStop, yStop, mTimePaint); } else { canvas.drawLine(xCenter, yCenter, xCenter, secondLength, mTimePaint); } // 画时针--不动 canvas.drawLine(xCenter, yCenter, xCenter + minuteLength, yCenter, mTimePaint); } /** * 旋转秒针 */ private void rorateSecond() { valueAnimator = new ValueAnimator().ofInt(0, 60000); valueAnimator.setRepeatMode(ValueAnimator.RESTART); valueAnimator.setDuration(60000); valueAnimator.start(); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //计算终点坐标 // 弧度 float angle = (float) ((Math.PI / 180) * (changeAn)); xStop = (int) (xCenter + (radius - 10) * Math.cos(angle)); yStop = (int) (yCenter + (radius - 10) * Math.sin(angle)); changeAn++; // 270 一圈 置为-90 if (changeAn >= 270) { changeAn = -90; } //changeAn > 90 && changeAn < 270 快速旋转 否则慢速旋转 if (changeAn >= 90 && changeAn < 270) { changeAn = changeAn + 5; } // 重绘 postInvalidate(); } }); } /** * 开始旋转动画 */ public void startRotate() { changeAn = -90; rotate = true; rorateSecond(); } /** * 停止旋转动画 */ public void stopRotate() { rotate = false; if (valueAnimator != null && valueAnimator.isRunning()) { valueAnimator.cancel(); } changeAn = -90; } /** * convert dp to px */ public int dip2px(float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }
LoadingActivity:
/** * 测试 加载 view *@author zyc *created at 2017/6/5 12:07 */ public class LoadingActivity extends Activity{ @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_loading); initView(); } private void initView() { final Loading load = (Loading) findViewById(R.id.loading); findViewById(R.id.tv_start).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DialogLoading.showDialog(LoadingActivity.this); } }); findViewById(R.id.tv_stop).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DialogLoading.closeDialog(); } }); } }
activity_loading.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:orientation="vertical" > <com.lefu8.www.loadingdemo.views.Loading android:id="@+id/loading" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center_horizontal" > </com.lefu8.www.loadingdemo.views.Loading> <TextView android:id="@+id/tv_start" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="开启动画" android:textColor="@android:color/holo_red_light" android:textSize="30sp" /> <TextView android:id="@+id/tv_stop" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="关闭动画" android:textColor="@android:color/holo_red_light" android:textSize="30sp" /> <TextView android:id="@+id/tv_stop1" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="关闭动画" android:textColor="@android:color/holo_red_light" android:textSize="30sp" /> <TextView android:id="@+id/tv_stop2" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="关闭动画" android:textColor="@android:color/holo_red_light" android:textSize="30sp" /> <TextView android:id="@+id/tv_stop3" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="关闭动画" android:textColor="@android:color/holo_red_light" android:textSize="30sp" /> <TextView android:id="@+id/tv_stop4" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="关闭动画" android:textColor="@android:color/holo_red_light" android:textSize="30sp" /> </LinearLayout>
DialogLoading:
/** * 封装的dialog *@author zyc *created at 2017/6/6 11:01 */ public class DialogLoading { /** * 通用显示等待对话框 */ public static void showDialog(final Activity act) { act.runOnUiThread(new Runnable() { @Override public void run() { waitingDialog = getWaitingDialog(act); waitingDialog.show(); } }); } private static volatile Dialog waitingDialog; private static Dialog getWaitingDialog(Activity act) { if (waitingDialog != null) { waitingDialog = null; } waitingDialog = new Dialog(act,R.style.my_dialog ); waitingDialog.setContentView(R.layout.layout_loading); waitingDialog.setCancelable(true); waitingDialog.setCanceledOnTouchOutside(false); Window w = waitingDialog.getWindow(); w.setGravity(Gravity.CENTER); WindowManager.LayoutParams attributes = w.getAttributes(); attributes.alpha = 0.6f; // 透明度 w.setAttributes(attributes); return waitingDialog; } /** * 通用关闭等待对话框 synchronized避免并发访问 在调用showDialog()的类的onPause中, * 加上Tools.closeDialog();是很好的做法,能够避免窗口泄露 */ public static synchronized void closeDialog() { try { if (waitingDialog != null) { if (waitingDialog.isShowing()) { waitingDialog.cancel(); } waitingDialog = null; } } catch (Exception e) { e.printStackTrace(); } } /** * 通用显示等待对话框,不可取消 */ public static void showDialogUnCancelable(final Activity act) { act.runOnUiThread(new Runnable() { @Override public void run() { waitingDialog = getWaitingDialog(act); waitingDialog.setCancelable(false); waitingDialog.show(); } }); } }
相关文章推荐
- 老猪带你玩转android自定义控件一——打造最简单viewpagerindicator
- android ViewPager 简单多线程加载本地图片
- Android RecyclerView加载不同布局简单实现
- android 自定义控件之NetWorkImageView 处理listview等控件中的图片加载乱序问题
- Android XRecyclerView简单实现上拉刷新,下拉加载
- Android Recyclerview 简单实用 瀑布流等方式,并加入上下拉加载
- 【Android实战】----RecyclerView下拉刷新和上拉加载的简单实现
- android 简单实现 RecyclerView 下拉刷新上拉加载
- android-smart-image-view图片加载简单使用
- Android Recyclerview 简单实用 瀑布流等方式,并加入上下拉加载
- android webview简单加载echart表格(折线,饼形,柱形)
- Android WebView的简单使用,实现标题、加载进度提示
- Android-搭建简单服务器+ViewPager异步加载数据
- SwipeRefreshLayout+RecyclerView 完成下拉刷新,上拉加载更多的自定义控件,简单好用
- Android RecyclerView加载不同布局简单实现
- Android ViewPager使用详解,加载几个简单布局案例+代码
- Android自定义控件---TabIndicatord选项卡按钮(可用于ViewPager,使用简单)
- android 自定义控件4 - 自定义view(加载进度条)
- android 中ViewPager动态加载数据的简单demo
- Android的简单图形和view刷新