Android进阶练习-自定义视图实战之刷新等待进度条
来源:互联网 发布:一般淘宝客佣金关闭 编辑:程序博客网 时间:2024/04/27 03:57
实现一个最简单的自定义视图(不包含处理用户的触摸事件),往往只需要三步
一、继承自一个View(可以是一个更具体的Android已实现好的View),并增加必须的构造方法(这个根据自定义View怎么使用来判断)二、覆写onDraw(Canvas canvas)方法,并且自定义绘制三、重绘,分为实时重绘和属性更新重绘
自定义视图如果是继承自原始View的话,public View(android.content.Context context)这个构造方法是必须的。而
public View(android.content.Context context, android.util.AttributeSet attrs)这个构造方法是可选,但如果你想在xml布局文件中使用自定义视图的话,带属性的构造函数也是必须的,因为Android系统是根据这个构造函数去实例化视图的,这样也可以让我们的视图可视化,配置的属性值也能够根据它来获得
关于自定义绘制,需要注意的是Android框架已经为我们提供了很多的方法来绘制各种图元,直接使用就行了,要记住的是自定义视图并不会自己主动的去重绘自己,首次显示会绘制一次,往往需要我们去通知它进行重绘,可以在视图上调用invalidate()和postInvalidate()来通知重绘,两者的区别稍后会进行解释
重绘,有些视图往往需要实时的进行重绘,像一些实时性很强的游戏,但这个一般需要使用到SurfaceView,有兴趣的话可以去学习下,我们今天的例子也需要进行实时重绘,但没有使用到SurfaceView,而是继承于View。有的时候可能并不需要实时进行重绘,像只有在改变了视图的一个属性值的情况下才需要重新绘制,这个时候我们可以在setXX()方法中调用invalidate()方法就行
下面是一个等待进度条的例子
package tu.bingbing.customdialogview.view;import tu.bingbing.customdialogview.R;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;public class CustomDialogView extends View { // 加载图片资源id,存入缓存数组 private final int[] ids = new int[] { R.drawable. loading01, R.drawable. loading02, R.drawable.loading03, R.drawable.loading04 , R.drawable. loading05, R.drawable.loading06, R.drawable.loading07 , R.drawable. loading08, R.drawable.loading09, R.drawable.loading10 , R.drawable. loading11 }; private Bitmap[] loadingImgs ; private Paint loadingImagePaint ; private int currentIdsIndex = 0; public CustomDialogView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CustomDialogView(Context context) { super(context); init(); } private void init() { // 实例化画笔 loadingImagePaint = new Paint(); // 设置抗锯齿 loadingImagePaint.setAntiAlias(true); // 一次性放进缓存数组中 loadingImgs = new Bitmap[] { BitmapFactory. decodeResource(getResources(), ids[0]), BitmapFactory. decodeResource(getResources(), ids[1]), BitmapFactory. decodeResource(getResources(), ids[2]), BitmapFactory. decodeResource(getResources(), ids[3]), BitmapFactory. decodeResource(getResources(), ids[4]), BitmapFactory. decodeResource(getResources(), ids[5]), BitmapFactory. decodeResource(getResources(), ids[6]), BitmapFactory. decodeResource(getResources(), ids[7]), BitmapFactory. decodeResource(getResources(), ids[8]), BitmapFactory. decodeResource(getResources(), ids[9]), BitmapFactory. decodeResource(getResources(), ids[10]) }; } @Override protected void onDraw(Canvas canvas) { // 循环控制每一张图片的绘制顺序,让看起来像是播放动画 if (currentIdsIndex >= (ids .length - 1)) { currentIdsIndex = 0; } Bitmap currentLoadingBitmap = loadingImgs[currentIdsIndex ]; // 绘制图片,显示在屏幕正中 canvas.drawBitmap(currentLoadingBitmap, (getWidth() - currentLoadingBitmap.getWidth())/2, (getHeight() - currentLoadingBitmap.getHeight())/2, loadingImagePaint ); currentIdsIndex++; super.onDraw(canvas); }}
在View上getWidth()和getHeight()方法取到的是屏幕的高和宽,BitmapFactory.decodeResource(Resources res, int id)方法根据资源id得到一张位图用于显示,关于是否应该把所有的图片一次性的加载入内存,这个可以根据需要来定,你可以一次性全部加载,可以得到更流畅的UI,但更耗损内存;你也可以到在要用到的时候再加载,这样可能会有一定的延迟,但可以有效的节省内存;也可以使用软引用来保存图片,这样可以使得在程序内存不足时,图片内存得以回收,两全其美。
在Activity中实时重绘视图
package tu.bingbing.customdialogview;import tu.bingbing.customdialogview.view.CustomDialogView;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity { private CustomDialogView customDialogView ; private RedrawCustomDialogViewThread redrawCdvRunnable ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main); customDialogView = (CustomDialogView) findViewById(R.id.view_customdialog ); redrawCdvRunnable = new RedrawCustomDialogViewThread(); new Thread(redrawCdvRunnable ).start(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu. main, menu); return true ; } final class RedrawCustomDialogViewThread implements Runnable{ private boolean isRun = true; @Override public void run() { while(isRun ){ try { Thread. sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 通知重绘 customDialogView.postInvalidate(); } } public boolean isRun() { return isRun ; } public void setRun(boolean isRun) { this.isRun = isRun; } } @Override protected void onDestroy() { redrawCdvRunnable.setRun(false ); super.onDestroy(); }}
布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <tu.bingbing.customdialogview.view.CustomDialogView android:id="@+id/view_customdialog" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
除了使用postInvalidate()方法外,还可以使用invalidate()方法,前者让程序可以在UI主线程外的线程中去通知视图进行重绘,后者必须在UI主线程中进行调用通知,一般可以和Handler一起使用
使用到的图片资源
程序运行效果
- Android进阶练习-自定义视图实战之刷新等待进度条
- Android进阶练习-自定义视图(1)
- Android进阶练习-自定义视图(2)
- Android进阶练习-自定义视图(3)
- <Android 进阶(一)> 自定义View之仪表盘进度条
- iOS开发之 等待视图 刷新
- Android之自定义进度条
- 自定义等待进度条实现
- Android进阶之自定义View实战(三)贝塞尔曲线应用
- Android 高手进阶,自定义圆形进度条
- Qt之模型/视图(自定义进度条)
- Android 自定义对话框,进度条,下拉刷新等
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- 基于朴素贝叶斯分类器的文本分类算法
- Directfb Flip 参数对性能的影响
- Linux启动文件
- 深入浅出JSONP:解决AJAX跨域问题
- 通过XML创建界面---对象的动态创建以及属性的设置
- Android进阶练习-自定义视图实战之刷新等待进度条
- SQL Server游标的使用
- ubuntu12.04 测试/proc下创建文件
- .net(C#)3小时开发网站
- 指针——C语言的灵魂
- 安卓txt电子书阅读器源码
- CH 白色情人节1(②第一天-KM算法)
- ekho-5.2安装
- 大规模WEB服务之实用算法(一)