Android view
1.view
view在api中的结构
java.lang.Object
android.view.View
直接子类:
AnalogClock, ImageView, KeyboardView, ProgressBar, SurfaceView, TextVie, ViewGroup, ViewStub
间接子类:
AbsListView, AbsSeekBar, AbsSpinner, AbsoluteLayout, AdapterView<T extends Adapter>, AppWidgetHostView, AutoCompleteTextView, Button, CheckBox, CheckedTextView, Chrono
meter, CompoundButton, DatePicker, DialerFilter, DigitalClock,EditView, ExpandableListView, ExtractEditText, FrameLayout, GLSurfaceView, Gallery, GestureOverlayView, GridView, HorizontalScrollView, ImageButton, ImageSwitcher, LinearLayout, ListView, MediaController, MultiAutoCompleteTextView, QuickContactBadge, RadioButton, RadioGroup, RatingBar, RelativeLayout, ScrollView, SeekBar, SlidingDrawer, Spinner, TabHost, TabWidget, TableLayout, TableRow, TextSwitcher, TimePicker, ToggleButton, TwoLineListItem, VideoView, ViewAnimator, ViewFlipper, ViewSwitcher, WebView, ZoomButton, ZoomControls
由此可见View类属于Android开发绘制中的显示老大,任何与绘制有关系的控件都是它的子类。在这篇文章中我主要讲View 与SurFaceView 使用线程刷新屏幕绘制方面的知识。开发中如何去选择使用View还是SurFaceView。我相信读过我前几篇博客的朋友应该知道我在刷新屏幕的时候使用invalidate()方法来重绘,下面我详细的说明一下Andooid刷新屏幕的几种方法。
第一种: 在onDraw方法最后调用invalidate()方法,它会通知UI线程重绘 这样 View会
重新调用onDraw方法,实现刷新屏幕。 这样写看起来代码非常简洁漂亮,但是它也同时存在一个很大的问题,它和游戏主线程是分开的 它违背了单线程模式,这样操作绘制的话是很不安全的,举个例子 比如程序先进在Activity1中 使用invalidate()方法来重绘, 然后我跳到了Activity2这时候Activity1已经finash()掉 可是Activity1中 的invalidate() 的线程还在程序中,Android的虚拟机不可能主动杀死正在运行中的线程所以这样操作是非常危险的。因为它是在UI线程中被动掉用的所以很不安全。
invalidate() 更新整个屏幕区域
view ui框架invalidate(Rect rect) 更新Rect区域
invalidate(l, t, r, b) 更新指定矩形区域
view plaincopy to clipboard
public void onDraw(Canvas canvas){
DosomeThing();
invalidate();
}
[java] view plaincopy
public void onDraw(Canvas canvas){
DosomeThing();
invalidate();
}
第二种:使用postInvalidate();方法来刷新屏幕 ,调用后它会用handler通知UI线程重绘屏幕,我们可以 new Thread(this).start(); 开启一个游戏的主线程 然后在主线程中通过调用pos
tInvalidate();方法来刷新屏幕。postInvalidate();方法 调用后 系统会帮我们调用onDraw方法 ,它是在我们自己的线程中调用 通过调用它可以通知UI线程刷新屏幕 。由此可见它是主动调用UI线程的。所以建议使用postInvalidate()方法通知UI线程来刷新整个屏幕。
postInvalidate(left, top, right, bottom) 方法 通过UI线程来刷新规定矩形区域。
view plaincopy to clipboard
@Override
public void run() {
while (mIsRunning) {
try {
Thread.sleep(100);
postInvalidate();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
[java] view plaincopy
@Override
public void run() {
while (mIsRunning) {
try {
Thread.sleep(100);
postInvalidate();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
View中用到的双缓冲技术
重绘的原理是 程序根据时间来刷新屏幕 如果有一帧图形还没有完全绘制结束 程序就开始刷新屏幕这样就会造成瞬间屏幕闪烁 画面很不美观,所以双缓冲的技术就诞生了。它存在的目的就是解决屏幕闪烁的问题,下面我说说在自定义View中如何实现双缓冲。
首先我们需要创建一张屏幕大小的缓冲图片,我说一下第三个参数 ARGB 分别代表的是 透明度 红 绿 蓝
Bitmap.Config ARGB_4444 ARGB 分别占四位
Bitmap.Config ARGB_8888 ARGB 分别占八位
Bitmap.Config RGB_565 没有透明度(A) R占5位 G 占6位 B占5位
Bitmap.Config ARGB_8888 ARGB 分别占八位
Bitmap.Config RGB_565 没有透明度(A) R占5位 G 占6位 B占5位
一般情况下我们使用ARGB_8888 因为它的效果是最好了 当然它也是最占内存的。
view plaincopy to clipboard
mBufferBitmap = ateBitmap(mScreenWidth,mScreenHeight,Config.ARGB_8888);
[java] view plaincopy
mBufferBitmap =&ateBitmap(mScreenWidth,mScreenHeight,Config.ARGB_8888);
创建一个缓冲的画布,将内容绘制在缓冲区mBufferBitmap中
view plaincopy to clipboard
Canvas mCanvas = new Canvas();
mCanvas.setBitmap(mBufferBitmap);
[java] view plaincopy
Canvas mCanvas = new Canvas();
mCanvas.setBitmap(mBufferBitmap);
最后一次性的把缓冲区mBufferBitmap绘制在屏幕上,怎么样 简单吧 呵呵。
view plaincopy to clipboard
@Override
protected void onDraw(Canvas canvas) {
/**这里先把所有须要绘制的资源绘制到mBufferBitmap上**/
/**绘制地图**/
DrawMap(mCanvas,mPaint,mBitmap);
/**绘制动画**/
RenderAnimation(mCanvas);
/**更新动画**/
UpdateAnimation();
if(isBorderCollision) {
DrawCollision(mCanvas,"与边界发生碰撞");
}
if(isAcotrCollision) {
DrawCollision(mCanvas,"与实体层发生碰撞");
}
if(isPersonCollision) {
DrawCollision(mCanvas,"与NPC发生碰撞");
}
/**最后通过canvas一次性的把mBufferBitmap绘制到屏幕上**/
canvas.drawBitmap(mBufferBitmap, 0,0, mPaint);
Draw(canvas);
}
[java] view plaincopy
@Override
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论