❶ android如何在屏幕点击位置画一个小圆
主要运用SurfaceView来实现在屏幕上画一个圆,你可以通过按方向键和触摸屏幕来改变圆的位置
代码:
Activity
package com.view;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隐藏状态栏
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 把Activity的标题去掉
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 设置布局
this.setContentView(new MySurfaceView(this));
}
}
SurfaceView
package com.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView implements Runnable, Callback {
private SurfaceHolder mHolder; // 用于控制SurfaceView
private Thread t; // 声明一条线程
private boolean flag; // 线程运行的标识,用于控制线程
private Canvas mCanvas; // 声明一张画布
private Paint p; // 声明一支画笔
private int x = 50, y = 50, r = 10; // 圆的坐标和半径
public MySurfaceView(Context context) {
super(context);
mHolder = getHolder(); // 获得SurfaceHolder对象
mHolder.addCallback(this); // 为SurfaceView添加状态监听
p = new Paint(); // 创建一个画笔对象
p.setColor(Color.WHITE); // 设置画笔的颜色为白色
setFocusable(true); // 设置焦点
}
/**
* 自定义一个方法,在画布上画一个圆
*/
public void Draw() {
mCanvas = mHolder.lockCanvas(); // 获得画布对象,开始对画布画画
mCanvas.drawRGB(0, 0, 0); // 把画布填充为黑色
mCanvas.drawCircle(x, y, r, p); // 画一个圆
mHolder.unlockCanvasAndPost(mCanvas); // 完成画画,把画布显示在屏幕上
}
/**
* 当SurfaceView创建的时候,调用此函数
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
t = new Thread(this); // 创建一个线程对象
flag = true; // 把线程运行的标识设置成true
t.start(); // 启动线程
}
/**
* 当SurfaceView的视图发生改变的时候,调用此函数
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
/**
* 当SurfaceView销毁的时候,调用此函数
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
flag = false; // 把线程运行的标识设置成false
}
/**
* 当屏幕被触摸时调用
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
x = (int) event.getX(); // 获得屏幕被触摸时对应的X轴坐标
y = (int) event.getY(); // 获得屏幕被触摸时对应的Y轴坐标
return true;
}
/**
* 当用户按键时调用
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DPAD_UP){ //当用户点击↑键时
y--; //设置Y轴坐标减1
}
return super.onKeyDown(keyCode, event);
}
@Override
public void run() {
while (flag) {
Draw(); // 调用自定义画画方法
try {
Thread.sleep(50); // 让线程休息50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
MySurfaceView首先继承SurfaceView,然后实现Runnable和Callback接口
重写了Runnable的run方法和Callback的surfaceCreated(SurfaceHolder holder),surfaceChanged(SurfaceHolder holder, int format, int width,int height),surfaceDestroyed(SurfaceHolder holder)方法,
还实现了onTouchEvent(MotionEvent event),onKeyDown(int keyCode, KeyEvent event)方法来,详细的在代码里已注释。
❷ android videoview和surfaceview的区别
在Android游戏当中充当主要的除了控制类外就是显示类,在J2ME中我们用Display和Canvas来实现这些,而Google Android中涉及到显示的为view类,Android游戏开发中比较重要和复杂的就是显示和游戏逻辑的处理。
这里说下android.view.View和android.view.SurfaceView。SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView,到底有哪些优势呢? SurfaceView可以控制表面的格式,比如大小,显示在屏幕中的位置,最关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的有Canvas lockCanvas()
Canvas lockCanvas(Rect dirty) 、void removeCallback(SurfaceHolder.Callback callback)、void unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制,而在SurfaceHolder.Callback 接口回调中可以通过重写下面方法实现。
使用的SurfaceView的时候,一般情况下要对其进行创建,销毁,改变时的情况进行监视,这就要用到 SurfaceHolder.Callback.
class XxxView extends SurfaceView implements SurfaceHolder.Callback {
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}
//看其名知其义,在surface的大小发生改变时激发
public void surfaceCreated(SurfaceHolder holder){}
//同上,在创建时激发,一般在这里调用画图的线程。
public void surfaceDestroyed(SurfaceHolder holder) {}
//同上,销毁时激发,一般在这里将画图的线程停止、释放。
}
对于Surface相关的,Android底层还提供了GPU加速功能,所以一般实时性很强的应用中主要使用SurfaceView而不是直接从View构建,同时后来做android 3d OpenGL中的GLSurfaceView也是从该类实现。
SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。
所以基于以上,根据游戏特点,一般分成两类。
1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。
2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。
3.Android中的SurfaceView类就是双缓冲机制。因此,开发游戏时尽量使用SurfaceView而不要使用View,这样的话效率较高,而且SurfaceView的功能也更加完善。
考虑以上几点,所以我一直都选用 SurfaceView 来进行游戏开发。
那么在以后源码实例中,都会以继承sarfaceView框架来进行演示。
❸ android的surfaceView类不执行surfaceCreated(),lockCanvas返回null
你把你初始化的代码放到onCreate外面去,然后在oncreate里面调用ca1=sfh.lockCanvas(null);
试试。
❹ 对android中的surfaceview的困惑,双缓冲区该怎么理解
最近开发一款小游戏,需要用到surfaceView,出于效率的考虑,需要使用脏矩形刷新技术。一开始怎么都不成功,到网上搜了很多有关脏矩形的使用的文章,但总是不懂。后来就只能到google上去搜索英文的相关文章,但是也收获甚微。后来,直接看Android
Developers上面的解释,也是一懂半懂的。
canvas
= holder.lockCanvas(Rect
dirty);中定义脏矩形刷新。我的理解是,给定dirty之后,系统会自动把前一个画布中dirty矩形外的部分拷贝过来,然后把dirty矩形内部留给现在的canvas来绘制。但是在项目的运行中,我发现根本不是这样的,系统好像不会自动拷贝dirty之外的部分过来,因为我的背景图片在绘制了一次之后,直接被黑色背景覆盖了。我查了一下AndroidDevelopers上面有关这个脏矩形的讲解,上面这样介绍:Just
likelockCanvas()but allows
specification of a dirty rectangle. Every pixel within that
rectangle must be written; however pixels outside the dirty
rectangle will be preserved by the next call to
lockCanvas()。意思就是说:在矩形内的每一个像素必须都要被写入,然后dirty矩形外的像素将在下次调用的时候保留。我在想,这个dirty脏矩形是不是为下次的绘图而准备的?
后来又仔细想了一会,结合网上的有关surfaceView的双缓冲实现,我觉得可能问题是这样的:第一次画背景是画在前景帧上,缓冲帧没有。而第二次画时,系统把缓冲帧与前景帧调换了,这样由于之前的缓冲帧里面没有画背景,就导致第二次绘画中背景没有画出来。而第二次绘画又是使用的脏矩形绘制,将在下一次绘制的时候保留脏矩形之外的部分,导致第三次绘画时,虽然调出了最开始画了背景的那一帧,但是脏矩形机制填充了脏矩形之外的部分,导致背景再次被覆盖。自此,背景彻底从缓冲的两帧中消失了。
找到了原因所在,解决就比较好办了。直接在一开始的时候,调用两遍绘制背景的函数,这样保证缓冲的两帧上面都有背景,那么之后再用脏矩形,就没有问题了。
当然,明白了这些,就不难解释网上那些闪烁的问题的根源了。只需要在一开始把背景绘制两遍即可。
在解决这个问题的过程中,通过所查的资料,以及我单步跟踪调试,也发现了一个android的隐藏操作:就是在每次定制好脏矩形之后,android系统会自动重置脏矩形的大小尺寸(一般重置为当前整个画布的大小),所以,为了能够在下次循环的时候能够继续调用之前的脏矩形对象,就需要重置一下脏矩形的大小;或者还有一个办法,就是直接写一个函数,这个函数返回一个脏矩形的拷贝给canvas,这样canvas就只能更改这个拷贝,而不能更改脏矩形对象本身了。
❺ Android自定义控件复写onDraw(Canvas canvas),canvas是怎样获取的
ViewRootImpl.java中
如果是软件绘制的话,drawSoftWare方法会调用view.draw()方法。
从上图中可以看到canvas来源于mSurface.lockCanvas。这里会调用到native层,简单点说就是去申请了一块buffer。这个时候canvas就可以用了,接下来就会调用view.draw方法。
具体点的过程自己可以去看看。
❻ android里面如何填充矩形呢
方案:
在canvas上画矩形,然后设置画笔为实心就可以了。
代码示例:
paint.setStyle(Style.FILL);//实心矩形框
paint.setColor(Color.RED);//颜色为红色
canvas.drawRect(newRectF(10,10,300,100),paint);//画一个290*90的红色实心矩形
❼ android开发:lockcanvas返回null,附上简单的代码
一般很少这样使用surfaceview的,一般使用surfaceview来做游戏界面,开一个线程不断的对canvas重新绘制,像你实现的这种功能 让你的自定义view集成View类就行了,没必要使用surfaceview
一般来说surfaceview 这样使用
publicvoiddraw(){
Canvascanvas=null;
synchronized(holder){
try{
canvas=holder.lockCanvas();
if(whichView==WhichView.start_view){
if(canvas!=null)
canvas.drawBitmap(bitmap,0,0,paint);
hero.drawSelf(canvas,x,y,direction);
}
}catch(Exceptione){
e.printStackTrace();
}
finally{
if(canvas!=null)
holder.unlockCanvasAndPost(canvas);
}
}
}
然后再一个线程里调用draw()方法不断进行界面绘制
像你的那种情况应该是你调用lockcanvas的时候surfaceView还没有创建,你可以尝试在surfaceCreate()中调用这个方法,刚开始这个canvas确实是获取不到的。我尝试过
❽ android 中 holder.lockCanvas(null)为什么获取为空
在canvas进行画图时,会把原有的图层清空,以盛放新的新的绘图区内容;反正获取画布,代码都这样格式的,另外这个问题国内外都有争议,不知道底层代码怎么搞的
❾ android surfaceview视频播放如何让视频翻转90
《android逆向视频》网络网盘资源免费下载
链接:https://pan..com/s/1W1NAE-AeKbz0bb6E4mdXfA
❿ android 怎么在屏幕中间画一个圆
主要运用SurfaceView来实现在屏幕上画一个圆,你可以通过按方向键和触摸屏幕来改变圆的位置 代码: Activity package com.view; import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 隐藏状态栏 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // 把Activity的标题去掉 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置布局 this.setContentView(new MySurfaceView(this)); } } SurfaceView package com.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; public class MySurfaceView extends SurfaceView implements Runnable, Callback { private SurfaceHolder mHolder; // 用于控制SurfaceView private Thread t; // 声明一条线程 private boolean flag; // 线程运行的标识,用于控制线程 private Canvas mCanvas; // 声明一张画布 private Paint p; // 声明一支画笔 private int x = 50, y = 50, r = 10; // 圆的坐标和半径 public MySurfaceView(Context context) { super(context); mHolder = getHolder(); // 获得SurfaceHolder对象 mHolder.addCallback(this); // 为SurfaceView添加状态监听 p = new Paint(); // 创建一个画笔对象 p.setColor(Color.WHITE); // 设置画笔的颜色为白色 setFocusable(true); // 设置焦点 } /** * 自定义一个方法,在画布上画一个圆 */ public void Draw() { mCanvas = mHolder.lockCanvas(); // 获得画布对象,开始对画布画画 mCanvas.drawRGB(0, 0, 0); // 把画布填充为黑色 mCanvas.drawCircle(x, y, r, p); // 画一个圆 mHolder.unlockCanvasAndPost(mCanvas); // 完成画画,把画布显示在屏幕上 } /** * 当SurfaceView创建的时候,调用此函数 */ @Override public void surfaceCreated(SurfaceHolder holder) { t = new Thread(this); // 创建一个线程对象 flag = true; // 把线程运行的标识设置成true t.start(); // 启动线程 } /** * 当SurfaceView的视图发生改变的时候,调用此函数 */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * 当SurfaceView销毁的时候,调用此函数 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { flag = false; // 把线程运行的标识设置成false } /** * 当屏幕被触摸时调用 */ @Override public boolean onTouchEvent(MotionEvent event) { x = (int) event.getX(); // 获得屏幕被触摸时对应的X轴坐标 y = (int) event.getY(); // 获得屏幕被触摸时对应的Y轴坐标 return true; } /** * 当用户按键时调用 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_DPAD_UP){ //当用户点击↑键时 y--; //设置Y轴坐标减1 } return super.onKeyDown(keyCode, event); } @Override public void run() { while (flag) { Draw(); // 调用自定义画画方法 try { Thread.sleep(50); // 让线程休息50毫秒 } catch (InterruptedException e) { e.printStackTrace(); } } } } MySurfaceView首先继承SurfaceView,然后实现Runnable和Callback接口 重写了Runnable的run方法和Callback的surfaceCreated(SurfaceHolder holder),surfaceChanged(SurfaceHolder holder, int format, int width,int height),surfaceDestroyed(SurfaceHolder holder)方法, 还实现了onTouchEvent(MotionEvent event),onKeyDown(int keyCode, KeyEvent event)方法来,详细的在代码里已注释。