解决Android SurfaceView绘制触摸轨迹闪烁问题的方法

本文分享了解决SurfaceView触摸轨迹闪烁问题的方法,供大家参考,具体内容如下

第一种解决SurfaceView触摸轨迹闪烁问题的方法:

由于SurfaceView使用双缓存机制,两张画布轮流显示到屏幕上。那么,要存储触摸轨迹并避免两张画布内容不一致造成的闪烁问题,完全可以利用保存绘制过程并不断重新绘制的方法解决闪烁,而且这样还顺带解决了多次试验中偶尔出现的因为moveTo()函数不能读取到参数执行默认设置(参数设为上次的触摸点)而出现的断线连接闪烁问题,详细代码如下:

package com.tobacco.touchdraw;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnTouchListener;
public class LSurfaceView extends SurfaceView implements Callback,OnTouchListener,Runnable{
 private SurfaceHolder sfh;
 private Canvas canvas;
 private Paint paint;
 private Path path;
 private ArrayList<Path> paths;
 private boolean flag;
 public LSurfaceView(Context context) {
 super(context);
 sfh=this.getHolder();
 sfh.addCallback(this);
 paint=new Paint();
 paint.setColor(Color.RED);
 paint.setAntiAlias(true);
 paint.setStrokeWidth(4);
 paint.setStyle(Paint.Style.STROKE);
 paint.setStrokeCap(Paint.Cap.ROUND);
 paths=new ArrayList<Path>();
 path=new Path();
 }
 public void myDraw(MotionEvent e){
 int action=e.getAction();
 switch(action){
 case MotionEvent.ACTION_DOWN:
  path.moveTo(e.getX(),e.getY());
  break;
 case MotionEvent.ACTION_MOVE:
  path.lineTo(e.getX(),e.getY());
  break;
 case MotionEvent.ACTION_UP:
  //path.close();
  Path path1=new Path(path);
  paths.add(path1);
  path.reset();
  break;
 }

 }
 @Override
 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

 }
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 flag=true;
 setOnTouchListener(this);
 new Thread(this).start();

 }
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 flag=false;
 }
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 myDraw(event);
 return true;
 }
 @Override
 public void run() {
 while(flag){
  long start=System.currentTimeMillis();
  canvas=sfh.lockCanvas();
  if(canvas!=null){
  canvas.drawColor(Color.BLACK);
  for(int i=0;i<paths.size();i++)
   canvas.drawPath(paths.get(i),paint);
  canvas.drawPath(path,paint);
  sfh.unlockCanvasAndPost(canvas);
  }
  long end=System.currentTimeMillis();
  try{
  if(end-start<30){
   Thread.sleep(30-(end-start));
  }
  }
  catch(Exception e){
  }
 }

 }
}

这里还要注意的是:ArrayList保存的是对象的引用,所以要在每次添加时都新建一个对象实体。

第二种解决SurfaceView触摸轨迹闪烁问题的方法:

处理触屏轨迹的绘制时,用到了SurfaceView,建立Path对象,在点击时开始设置Path对象,滑动过程中记录触摸点,离开后重新设置Path对象,因不能阻塞主线程,所以新建了一个子线程来不断刷新屏幕,也就是将path不断绘制。但是,接着就出现了一个问题:屏幕中每条轨迹线的终点都会有一小段直线段不断闪烁。猜测可能是lockCanvas()获取的对象区域不一样,就试着使用了lockCanvas(Rect re),但是,运行后发现还是没有解决问题;接着想到可能是因为每次lockCanvas()后获取的对象不同,就在主线程中添加了一个Canvas对象,每次都在Canvas对象中修改画面,然后提交显示,但是,程序运行后效果丝毫没有改变!程序代码如下:

package com.tobacco.touchdraw;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnTouchListener;
public class MySurfaceView extends SurfaceView implements Callback,OnTouchListener,Runnable{
 private SurfaceHolder sfh;
 private Canvas canvas;
 private Paint paint;
 private float lastX,lastY;
 private Path path;
 private boolean flag;
 public MySurfaceView(Context context) {
 super(context);
 sfh=this.getHolder();
 sfh.addCallback(this);
 paint=new Paint();
 paint.setColor(Color.RED);
 paint.setAntiAlias(true);
 paint.setStrokeWidth(5);
 paint.setStyle(Paint.Style.STROKE);
 paint.setStrokeCap(Paint.Cap.ROUND);
 path=new Path();

 }
 public void myDraw(MotionEvent e){
 int action=e.getAction();
 switch(action){
 case MotionEvent.ACTION_DOWN:
  path.moveTo(e.getX(),e.getY());
  lastX=e.getX();
  lastY=e.getY();
  break;
 case MotionEvent.ACTION_MOVE:
  path.quadTo(lastX,lastY,e.getX(),e.getY());
  lastX=e.getX();
  lastY=e.getY();
  break;
 case MotionEvent.ACTION_UP:
  //path.quadTo(lastX,lastY,e.getX(),e.getY());
  path.reset();
  break;
 }

 }
 @Override
 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

 }
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 flag=true;
 setOnTouchListener(this);
 new Thread(this).start();

 }
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 flag=false;
 }
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 myDraw(event);
 return true;
 }
 @Override
 public void run() {
 while(flag){
  long start=System.currentTimeMillis();
  canvas=sfh.lockCanvas();
  if(canvas!=null){
  canvas.drawPath(path,paint);
  sfh.unlockCanvasAndPost(canvas);
  }
  long end=System.currentTimeMillis();
  try{
  if(end-start<100){
   Thread.sleep(100-(end-start));
  }
  }
  catch(Exception e){
  }
 }

 }
}

以上就是本文的全部内容,希望能够帮助大家轻松解决SurfaceView触摸轨迹闪烁问题。

(0)

相关推荐

  • Android QQ登录界面绘制代码

    先看看效果图: 首先过程中碰到的几个问题: 1.对 EditText 进行自定义背景 2.运行时自动 EditText 自动获得焦点 3.在获得焦点时即清空 hint ,而不是输入后清空 4.清空按钮的出现时机(在得到焦点并且有输入内容时) ---  这些问题都有一一解决 --- 以下是代码: 布局 fragment_main(问题2) <!-- android:focusable="true" android:focusableInTouchMode="true&qu

  • Android listView 绘制表格实例详解

    Android  listView 绘制表格 效果图: 二,创建步骤: 1,创建布局: activity_main中的布局: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:

  • Android开发 OpenGL ES绘制3D 图形实例详解

    OpenGL ES是 OpenGL三维图形API 的子集,针对手机.PDA和游戏主机等嵌入式设备而设计. Ophone目前支持OpenGL ES 1.0 ,OpenGL ES 1.0 是以 OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以 OpenGL 1.5 规范为基础的.本文主要介绍利用OpenGL ES绘制图形方面的基本步骤. 本文内容由三部分构成.首先通过EGL获得OpenGL ES的编程接口;其次介绍构建3D程序的基本概念;最后是一个应用程序示例. OpenGL E

  • Android中使用ListView绘制自定义表格技巧分享

    先上一下可以实现的效果图  要实现的效果有几方面 1.列不固定:可以根据数据源的不同生成不同的列数 2.表格内容可以根据数据源的定义合并列 3.要填写的单元格可以选择自定义键盘还是系统键盘 奔着这三点,做了个简单的实现,把源码贴一下(因为该点是主界面中的一部分,不便于放整个Demo) 自定义适配器,CallBackInterface是自定义的回调接口,这里定义回调是因为数据输入时需要及时保存 复制代码 代码如下: public class SiteDetailViewAdapter extend

  • Android编程绘制圆形图片的方法

    本文实例讲述了Android编程绘制圆形图片的方法.分享给大家供大家参考,具体如下: 效果图如下: 第一步:新建RoundView自定义控件继承View package com.rong.activity; import com.rong.test.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.grap

  • Android自定义View之继承TextView绘制背景

    本文实例为大家分享了TextView绘制背景的方法,供大家参考,具体内容如下 效果: 实现流程: 1.初始化:对画笔进行设置 mPaintIn = new Paint(); mPaintIn.setAntiAlias(true); mPaintIn.setDither(true); mPaintIn.setStyle(Paint.Style.FILL); mPaintIn.setColor(getResources().getColor(R.color.colorPrimary)); mPain

  • Android开发笔记之:在ImageView上绘制圆环的实现方法

    绘制圆环其实很简单,有大概以下三种思路. 这里先说网上提到的一种方法.思路是先绘制内圆,然后绘制圆环(圆环的宽度就是paint设置的paint.setStrokeWidth的宽度),最后绘制外圆.请看核心源码: 复制代码 代码如下: <SPAN xmlns="http://www.w3.org/1999/xhtml">package yan.guoqi.rectphoto;import android.content.Context;import android.graph

  • Android中使用achartengine生成图表的具体方法

    今天在做项目的时候用到了图表功能,记录下来 achartengine是google的一个开源项目,可以在https://code.google.com/p/achartengine/ 下载技术文档,jar包以及项目源代码 demo下载:https://code.google.com/p/achartengine/downloads/list 一.饼状图 新建工程,添加achartengine  jar包 PieChart.java 复制代码 代码如下: package com.meritit.f

  • Android开发中使用achartengine绘制各种图表的方法

    本文实例讲述了Android开发中使用achartengine绘制各种图表的方法.分享给大家供大家参考,具体如下: 1. ABarChart.java package com.anjoyo.achartengine; import java.util.Random; import org.achartengine.ChartFactory; import org.achartengine.chart.BarChart.Type; import org.achartengine.model.Cat

  • Android百度地图实现搜索和定位及自定义图标绘制并点击时弹出泡泡

    一.问题描述 上一次我们使用百度地图实现基本的定位功能,接下来我们继续实现搜索和定位,并使用LocationOverlay绘制定位位置,同时展示如何使用自定义图标绘制并点击时弹出泡泡 如图所示: 二.编写MyApplication类 public class MyApplication extends Application { private static MyApplication mInstance = null; public boolean m_bKeyRight = true; pu

  • Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)

    本文实例讲述了Android编程开发之在Canvas中利用Path绘制基本图形的方法.分享给大家供大家参考,具体如下: 在Android中绘制基本的集合图形,本程序就是自定义一个View组件,程序重写该View组件的onDraw(Canvase)方法,然后在该Canvas上绘制大量的基本的集合图形. 直接上代码: 1.自定义的View组件代码: package com.infy.configuration; import android.content.Context; import andro

随机推荐