吹毛求疵画图板
因为之前java的画图板只是实现了基础功能,所以我想在android上做一个功能完善的画图板。
我们首先要设计界面,现在主流的android 的界面主要是relative layout 和line layout 相互嵌套使用。
另外在android:onClick="cancel" 可以轻松绑定在主界面MainActivity写的方法,轻松快捷,超好用的有木有。组件一般都是先拖上去再在xml中修改代码。另外在布局中,熟练使用 android:layout_weight="1" 我一般先再xml中先写好,然后再在graphical_layout 拉界面调整比例。
然后今天我还知道了如何更改主界面的theme,在AndroidManifest中的application中选择system resours
这是我的界面图:(4寸一般手机是刚好可以铺开的)
布局格式:先是整体用相对布局然后中间嵌套竖直流布局(充满前面一个组件,既充满整个屏幕),然后再在中间加一个imageView横向充满屏幕,下面再加上一个横向线型布局,中间加上各种按钮组件(全部的权重都设为android:layout_weight="1")。下面是代码:
<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:background="@drawable/background" tools:context=".MainActivity" > <LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ImageView android:id="@+id/imageView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="32.15" android:src="@drawable/backgrand" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="horizontal" > <!--onClick绑定点击方法 --> <Button android:id="@+id/line" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="setLine" android:layout_weight="1" android:text="line" /> <Button android:id="@+id/rectangle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="setRect" android:layout_weight="1" android:text="rect" /> <Button android:id="@+id/pen" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="setPen" android:layout_weight="1" android:text="pen" /> <Button android:id="@+id/cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="cancel" android:text="cancel" /> <Button android:id="@+id/clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="clear" android:layout_weight="1" android:text="clear" /> </LinearLayout> </LinearLayout> </RelativeLayout>
具体画直线的歩奏这里就先省略。这里为了实现一般画图板的拖动效果,我们首先采用了双缓冲画图技术。就是采用两张Bitmap 用一张bitmap存本来的图,在MotionEvent.ACTION_MOVE:用另一张显示现在正在拖动的的图片。代码如下:
// 如果没有位图,就新建一个 if (bitmap == null) { bitmap = Bitmap.createBitmap(imageView.getWidth(), imageView.getHeight(), Config.ARGB_8888); // 宽,高,第一个alpha 是透明度 后面是3原色 // 实例化一个canvas对象,通过bitmap canvas = new Canvas(bitmap); paint.setStyle(Style.STROKE);//画一个空心的 paint.setColor(Color.RED); paint.setStrokeWidth(5.0f); canvas.drawRect(0, 0, imageView.getWidth(), imageView.getHeight(), paint);//画入新线 //将缓冲图输出 imageView.setImageBitmap(bitmap); } // 获取触控方式 int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: x1=event.getX(); y1=event.getY(); preX=x1; preY=y1; break; case MotionEvent.ACTION_UP: x2=event.getX(); y2=event.getY(); //设置画笔的属性 paint.setColor(Color.BLACK); paint.setStrokeWidth(5.0f); // paint.setStyle(Style.STROKE);//画一个空心的 // paint.setStyle(Style.FILL); //画线 canvas.drawLine(x1, y1, x2, y2, paint); //输出到位图,再镶嵌到线框 line line=new line(); line.setAttribute(1); line.setX1(x1); line.setX2(x2); line.setY1(y1); line.setY2(y2); list.add(line); imageView.setImageBitmap(bitmap); break; case MotionEvent.ACTION_MOVE: x2=event.getX(); y2=event.getY(); //设置一个缓冲位图 Bitmap buffer = Bitmap.createBitmap(imageView.getWidth(), imageView.getHeight(), Config.ARGB_8888); Canvas canvas2 = new Canvas(buffer); //新化一个缓冲图 canvas2.drawBitmap(bitmap, 0, 0, new Paint());//将以前画的全部写入缓冲区 paint.setColor(Color.BLACK); paint.setStrokeWidth(5.0f); canvas2.drawLine(x1, y1, x2, y2, paint);//画入新线 //将缓冲图输出 imageView.setImageBitmap(buffer); break; }
但是运用这种技术,我们发现手机上可能会有一些不流畅的感觉。但是我们只用一个bitmap将之前存在队列中的图形对象,在move行为结束,新的直线即将即将画出来的时候,先将队列中的图形全部画出。这样就不用每move一下就新建一个对象,减少了内存开销。仅提供思路,有时间再去尝试下。
有了画图板,我们还要做到撤销,要做到撤销为了实现撤销的效果我们每一次画的图都要保存在队列里撤销时,我们删除掉最近一个图形,然后再调用子类中的draw方法,将之前的图形画出来。为了实现这个效果,我们首先要有一个父类(用来做画图存储列表),各个图形对象继承这个父类,当每画一个图形,就把这个图形丢到这个队列中去,子类转换为父类。当点击撤销时,先将父类对象取出(不能直接取出子类),,这时因为在存储时子类转换为父类,所以在JAVA中,子类的方法被隐藏了。再强制转换为子类,就可以调用draw的方法,代码如下:
package com.example.drawboard; import android.graphics.Canvas; import android.graphics.Paint; /** * 所有图形的父类 * @author * */ public abstract class paintList { public int getAttribute() { return attribute; } public void setAttribute(int attribute) { this.attribute = attribute; } public float getX1() { return x1; } public void setX1(float x1) { this.x1 = x1; } public float getY1() { return y1; } public void setY1(float y1) { this.y1 = y1; } public float getX2() { return x2; } public void setX2(float x2) { this.x2 = x2; } public float getY2() { return y2; } public void setY2(float y2) { this.y2 = y2; } private int attribute;//属性,1代表1按钮 private float x1,y1,x2,y2; /** * 绘制的方法 * @param g */ public abstract void draw(Canvas canvas,Paint paint);
package com.example.drawboard; import android.graphics.Canvas; import android.graphics.Paint; /** * 直线类 * @author * */ public class line extends paintList{ public line(){ //构造时设置标志位 this.setAttribute(1); } public void draw(Canvas canvas,Paint paint){ canvas.drawLine(this.getX1(), this.getY1(), this.getX2(), this.getY2(), paint); } }
bitmap = Bitmap.createBitmap(imageView.getWidth(), imageView.getHeight(), Config.ARGB_8888); // 宽,高,第一个alpha 是透明度 后面是3原色 // 实例化一个canvas对象,通过bitmap canvas = new Canvas(bitmap); paint.setStyle(Style.STROKE);//画一个空心的 paint.setColor(Color.RED); paint.setStrokeWidth(5.0f); canvas.drawRect(0, 0, imageView.getWidth(), imageView.getHeight(), paint);//画入新线 //将缓冲图输出 if(list.size()!=0){ paint.setColor(Color.BLACK); list.remove(list.size()-1); int total=list.size(); //还原图片 for(int i=0;i<total;i++){ paintList T=list.get(i); //如果是直线的话 if(T.getAttribute()==1){ line line =(line)T; line.draw(canvas, paint); } if(T.getAttribute()==2){ rect rect =(rect)T; rect.draw(canvas, paint); } if(T.getAttribute()==3){ pen pen =(pen)T; System.out.println("hi"); pen.draw(canvas, paint); } } } imageView.setImageBitmap(bitmap);
最后我来讲一下,如何做到做到铅笔的效果,正所谓所见接虚,我们看到的一条曲线实际上也是由许多直线所构成。我们每画一个pen对象我们就在pen对象中加上直线队列。撤销时再一个个重画出来,就有我们想要的效果了。
package com.example.drawboard; import java.util.ArrayList; import android.graphics.Canvas; import android.graphics.Paint; /** * 铅笔类 * @author */ public class pen extends paintList{ public pen(){ //构造时设置标志位 this.setAttribute(3); } //应该有一个队列存储铅笔的轨迹 private ArrayList<line> list=new ArrayList<line>(); public ArrayList<line> getList() { return list; } public void setList(ArrayList<line> list) { this.list = list; } @Override public void draw(Canvas canvas, Paint paint) { // TODO Auto-generated method stub //如果是直线的话 int total=list.size(); for(int i=0;i<total;i++){ line line =list.get(i); line.draw(canvas, paint); } } }
感悟:
命名规则
类名首字母要大写,否则容易与对象名混淆。
另外在android工程中,我们要看到system.out 我们就要在logcat 中 saved filters 旁边的绿色加号按钮,选择要查看的内容的关键字。这点与java不同。
下一篇blog,我就来讲讲自定义组件,如何在画图板上输入文字,以及将这次代码再优化一下。
相关推荐
嵌入式八股文面试题库资料知识宝典-华为的面试试题.zip
训练导控系统设计.pdf
嵌入式八股文面试题库资料知识宝典-网络编程.zip
人脸转正GAN模型的高效压缩.pdf
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
少儿编程scratch项目源代码文件案例素材-鸡蛋.zip
嵌入式系统_USB设备枚举与HID通信_CH559单片机USB主机键盘鼠标复合设备控制_基于CH559单片机的USB主机模式设备枚举与键盘鼠标数据收发系统支持复合设备识别与HID
嵌入式八股文面试题库资料知识宝典-linux常见面试题.zip
面向智慧工地的压力机在线数据的预警应用开发.pdf
基于Unity3D的鱼类运动行为可视化研究.pdf
少儿编程scratch项目源代码文件案例素材-霍格沃茨魔法学校.zip
少儿编程scratch项目源代码文件案例素材-金币冲刺.zip
内容概要:本文深入探讨了HarmonyOS编译构建子系统的作用及其技术细节。作为鸿蒙操作系统背后的关键技术之一,编译构建子系统通过GN和Ninja工具实现了高效的源代码到机器代码的转换,确保了系统的稳定性和性能优化。该系统不仅支持多系统版本构建、芯片厂商定制,还具备强大的调试与维护能力。其高效编译速度、灵活性和可扩展性使其在华为设备和其他智能终端中发挥了重要作用。文章还比较了HarmonyOS编译构建子系统与安卓和iOS编译系统的异同,并展望了其未来的发展趋势和技术演进方向。; 适合人群:对操作系统底层技术感兴趣的开发者、工程师和技术爱好者。; 使用场景及目标:①了解HarmonyOS编译构建子系统的基本概念和工作原理;②掌握其在不同设备上的应用和优化策略;③对比HarmonyOS与安卓、iOS编译系统的差异;④探索其未来发展方向和技术演进路径。; 其他说明:本文详细介绍了HarmonyOS编译构建子系统的架构设计、核心功能和实际应用案例,强调了其在万物互联时代的重要性和潜力。阅读时建议重点关注编译构建子系统的独特优势及其对鸿蒙生态系统的深远影响。
嵌入式八股文面试题库资料知识宝典-奇虎360 2015校园招聘C++研发工程师笔试题.zip
嵌入式八股文面试题库资料知识宝典-腾讯2014校园招聘C语言笔试题(附答案).zip
双种群变异策略改进RWCE算法优化换热网络.pdf
内容概要:本文详细介绍了基于瞬时无功功率理论的三电平有源电力滤波器(APF)仿真研究。主要内容涵盖并联型APF的工作原理、三相三电平NPC结构、谐波检测方法(ipiq)、双闭环控制策略(电压外环+电流内环PI控制)以及SVPWM矢量调制技术。仿真结果显示,在APF投入前后,电网电流THD从21.9%降至3.77%,显著提高了电能质量。 适用人群:从事电力系统研究、电力电子技术开发的专业人士,尤其是对有源电力滤波器及其仿真感兴趣的工程师和技术人员。 使用场景及目标:适用于需要解决电力系统中谐波污染和无功补偿问题的研究项目。目标是通过仿真验证APF的有效性和可行性,优化电力系统的电能质量。 其他说明:文中提到的仿真模型涉及多个关键模块,如三相交流电压模块、非线性负载、信号采集模块、LC滤波器模块等,这些模块的设计和协同工作对于实现良好的谐波抑制和无功补偿至关重要。
内容概要:本文探讨了在工业自动化和物联网交汇背景下,构建OPC DA转MQTT网关软件的需求及其具体实现方法。文中详细介绍了如何利用Python编程语言及相关库(如OpenOPC用于读取OPC DA数据,paho-mqtt用于MQTT消息传递),完成从OPC DA数据解析、格式转换到最终通过MQTT协议发布数据的关键步骤。此外,还讨论了针对不良网络环境下数据传输优化措施以及后续测试验证过程。 适合人群:从事工业自动化系统集成、物联网项目开发的技术人员,特别是那些希望提升跨协议数据交换能力的专业人士。 使用场景及目标:适用于需要在不同通信协议间建立高效稳定的数据通道的应用场合,比如制造业生产线监控、远程设备管理等。主要目的是克服传统有线网络限制,实现在不稳定无线网络条件下仍能保持良好性能的数据传输。 其他说明:文中提供了具体的代码片段帮助理解整个流程,并强调了实际部署过程中可能遇到的问题及解决方案。
基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档~ 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 基于C#实现的检测小说章节的重复、缺失、广告等功能+源码+项目文档,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档
少儿编程scratch项目源代码文件案例素材-火柴人终极之战.zip