今天学习了怎么做一个简单的画图板。
由于尝试的过程没有截图,只有最终的结果,所以中间过程的尝试截图就没有了。
首先把参考代码看懂,才能自己做。
“
Android中的触摸事件可是大头中的大头, 其中onTouch事件是在view中定义的,所以想要实现绘图,自己要定义一个绘图组件,这个组件一定要继承view类,同时覆盖重写view中的onDraw方法。 Android画图最基本的三个对象(Color,Paint,Canvas) 三个类都存放在 android.graphics包下 1) Color :颜色对象,相当于现实生活中的 ‘调料’ 2) Paint : 画笔对象,相当于现实生活中画图用的 ‘笔’————主要的还是对‘画笔’进行设置 3) Canvas : 画布对象,相当于现实生活中画图用的 ‘纸 或 布’
”
根据指导,新建一个java类,写上代码
public class paintview extends View{ private List<Point> pointall=new ArrayList<Point>(); public paintview(Context context, AttributeSet attrs) { super(context, attrs); super.setBackgroundColor(Color.WHITE); super.setOnTouchListener(new Touch()); } private class Touch implements OnTouchListener{ @Override public boolean onTouch(View v, MotionEvent e) { // TODO Auto-generated method stub Point p=new Point((int)e.getX(),(int)e.getY()); if(e.getAction()==e.ACTION_DOWN){ //当按下 pointall=new ArrayList<Point>(); pointall.add(p); } else if(e.getAction()==e.ACTION_UP){//当抬起 pointall.add(p); paintview.this.postInvalidate(); //重绘 } else if(e.getAction()==e.ACTION_MOVE){ pointall.add(p); //移动时候 paintview.this.postInvalidate(); //重绘 } return true; } } protected void onDraw(Canvas canvas){ Paint p=new Paint(); //定义画笔 p.setColor(Color.RED); //定义颜色 if(pointall.size()>1){ Iterator<Point> iter=pointall.iterator();// 现在有坐标点保存的时候可以开始进行绘图 Point first=null; Point last=null; while(iter.hasNext()){ if(first==null){ first=(Point)iter.next(); } else{ if(last!=null){ first=last; //将下一个坐标点赋给上面的 } last=(Point)iter.next(); //不停下指 canvas.drawLine(first.x, first.y, last.x, last.y,p); } } } } }
之后配置好activity_main.xml
加上这段:
<com.example.paint.paintview
android:id="@+id/paintview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
现在,参考代码已经全部导入我们的工程了,运行一下看看效果。
试试结果,能画出一条一个像素宽度的线条,并且只有红色,而且再次点击绘制的时候原来线条消失了。
所以尝试对其进行改进,试想加入画笔颜色,画笔粗细。最重要的,可以画多条线。
首先分析代码,线条的绘制方式。其使用迭代器,循环遍历集合并根据相邻点的位置进行连线,达到绘图的效果。
但是发现在按下事件中:
if(e.getAction()==e.ACTION_DOWN){ //当按下
pointall=new ArrayList<Point>();
pointall.add(p);
}
每一次迭代器都被重置了,导致前面的信息丢失。为了解决这个问题,可以设置参数进行判断,当只有在第一次画的时候,重置迭代器,之后的绘制,不会重置迭代器:
if(e.getAction()==e.ACTION_DOWN){ //当按下
if(f==false){
f=true;
pointall=new ArrayList<Point>();
p=new Point(0,-2001);
}
尝试一下。好的,现在我们可以一直绘制了。但是也有问题。
绘制的线条并不是分开的,新线条的起点和旧线条的终点连接在了一起?
问题就在与渲染方式,其遍历集合,把前一个点和后一个点进行连接,而新线条的起点就是和旧线条的终点相邻。怎么办呢?
其实只要进行判断,当遇到终点或起点的时候,不要把他们连接就可以了。
但是如何在集合里面保存起点终点信息?集合里面只有 点 ,要保存起点终点信息,也只能通过点进行保存。
那么可以把起点终点的坐标设置为一个特殊值,当遇到的时候,就知道他们是起点和终点了。
if(e.getAction()==e.ACTION_DOWN){ //当按下
if(f==false){
f=true;
pointall=new ArrayList<Point>();
}
p=new Point(0,0);
pointall.add(p);
起点坐标被强制设置为0。同样的,对终点进行标记。
然后在渲染的方法的前面加上:
if(first.x==0||last.x==0)continue;
canvas.drawLine(first.x, first.y, last.x, last.y,p);
这样,如果遇到起点终点,就会跳过,不渲染。
尝试一下!好的,成功把线条断开了!
颜色怎么办?首先在面板设置组件,点击的时候获取信息,判断选择了什么颜色。
这个组件随便什么都可以,我使用的是Spinner。怎么获取信息并且传入我们之前新建的java类里面,这里就不多说了。
好,现在我们可以从面板中获取颜色信息了,但是怎么改变线条颜色呢?
由于我们只有一个迭代器,需要保存不同线条的信息,同理,我们也只能使用点坐标进行信息保存。仔细看上面的代码,发现我只用了起点终点的x坐标来判断是否渲染,现在,我们把它的y坐标利用上,用它来保存颜色信息!
if(e.getAction()==e.ACTION_DOWN){ //当按下 if(f==false){ f=true; pointall=new ArrayList<Point>(); } p=new Point(0,color1); pointall.add(p); }
参数color1是一个整数,我用来保存颜色信息,需要自己建立面板传入的参数和颜色代表的整数之间的对应!
并且在绘制之前,进行判断当前线条的颜色。
if(first.y==1000)p.setColor(Color.BLACK);//黑 else if(first.y==-1001)p.setColor(Color.RED);//红 else if(first.y==-1002)p.setColor(Color.rgb(255, 150, 0));//橙 else if(first.y==-1003)p.setColor(Color.YELLOW);//黄 else if(first.y==-1004)p.setColor(Color.GREEN);//绿 else if(first.y==-1005)p.setColor(Color.CYAN);//青 else if(first.y==-1006)p.setColor(Color.BLUE);//蓝 else if(first.y==-1007)p.setColor(Color.MAGENTA);//紫 else if(first.y==-1008)p.setColor(Color.GRAY);//灰 //断线跳过 if(first.x==0||last.x==0)continue; canvas.drawLine(first.x, first.y, last.x, last.y,p);
尝试一下!成功了,我们可以切换不同颜色了!而且不同的线条也显示出不同的颜色了!
接下来是更换线条粗细。使用同样的思想,用点来保存信息,但是,起点终点的x和y坐标都被我们利用完了,怎么办?很简单!它们只是记录信息的点,不要要参加绘制,所以可以再来一个点进行记录粗细的信息。
if(e.getAction()==e.ACTION_DOWN){ //当按下 if(f==false){ f=true; pointall=new ArrayList<Point>(); p=new Point(0,-2001); pointall.add(p); } p=new Point(0,linewight); pointall.add(p); p=new Point(0,color1); pointall.add(p); }
linewight这个参数被我用来存放粗细的信息,同样的要自己建立面板传入的参数和信息的整数对应关系。
由于是携带信息的点,所以干脆就和起点放在一起,“两个起点”。
但是!这里要注意一下,我们要给整个集合的第一个点设置一个粗细的参数,不然的话,后面改变线条粗细的时候,会因为第一条线没有起点携带了粗细信息而会跟着被改变
(其实读者可以自己试一试,如果把我上面代码的p=new Point(0,-2001);pointall.add(p);给删掉,会是什么效果)。
接下来,渲染的地方就最终变成这个样子了:
last=(Point)iter.next(); //不停下指 //判断线条颜色 if(first.y==1000)p.setColor(Color.BLACK);//黑 else if(first.y==-1001)p.setColor(Color.RED);//红 else if(first.y==-1002)p.setColor(Color.rgb(255, 150, 0));//橙 else if(first.y==-1003)p.setColor(Color.YELLOW);//黄 else if(first.y==-1004)p.setColor(Color.GREEN);//绿 else if(first.y==-1005)p.setColor(Color.CYAN);//青 else if(first.y==-1006)p.setColor(Color.BLUE);//蓝 else if(first.y==-1007)p.setColor(Color.MAGENTA);//紫 else if(first.y==-1008)p.setColor(Color.GRAY);//灰 //判断线条粗细 if(first.y==-2001)p.setStrokeWidth(1); else if(first.y==-2002)p.setStrokeWidth(2); else if(first.y==-2003)p.setStrokeWidth(3); else if(first.y==-2004)p.setStrokeWidth(4); else if(first.y==-2006)p.setStrokeWidth(6); else if(first.y==-2008)p.setStrokeWidth(8); //断线跳过 if(first.x==0||last.x==0)continue; canvas.drawLine(first.x, first.y, last.x, last.y,p);
我选用的选择线条粗细的组件是图片按钮。
好的,现在我今天的最终版也就做出来了,我们来试试效果。
记住,目标:绘制多条线,不同颜色的线,不同粗细的线!
最后的最后,给上代码:
Main.Activity.java: public class MainActivity extends Activity { private ImageButton px01; private ImageButton px02; private ImageButton px03; private ImageButton px04; private ImageButton px06; private ImageButton px08; private Spinner color; private String color1; private Spinner lwight; private String lwight1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); px01=(ImageButton)findViewById(R.id.imageButton1); px01.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { paintview.linewight=-2001; } }); px02=(ImageButton)findViewById(R.id.imageButton2); px02.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { paintview.linewight=-2002; } }); px03=(ImageButton)findViewById(R.id.imageButton3); px03.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { paintview.linewight=-2003; } }); px04=(ImageButton)findViewById(R.id.imageButton4); px04.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { paintview.linewight=-2004; } }); px06=(ImageButton)findViewById(R.id.imageButton5); px06.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { paintview.linewight=-2006; } }); px08=(ImageButton)findViewById(R.id.imageButton6); px08.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { paintview.linewight=-2008; } }); color=(Spinner)findViewById(R.id.colortext); color.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub color1= (String) color.getSelectedItem(); if(color1.equals("红色")) paintview.color1=-1001; else if(color1.equals("橙色")) paintview.color1=-1002; else if(color1.equals("黄色")) paintview.color1=-1003; else if(color1.equals("绿色")) paintview.color1=-1004; else if(color1.equals("青色")) paintview.color1=-1005; else if(color1.equals("蓝色")) paintview.color1=-1006; else if(color1.equals("紫色")) paintview.color1=-1007; else if(color1.equals("灰色")) paintview.color1=-1008; else paintview.color1=1000; } @Override public void onNothingSelected(AdapterView<?> parent) {} }); } @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; } }
paintview.java: public class paintview extends View{ static int color1; static int linewight; static int linewight2; private List<Point> pointall=new ArrayList<Point>(); private boolean f=false; public paintview(Context context, AttributeSet attrs) { super(context, attrs); super.setBackgroundColor(Color.rgb(250, 245, 220)); super.setOnTouchListener(new Touch()); } private class Touch implements OnTouchListener{ @Override public boolean onTouch(View v, MotionEvent e) { // TODO Auto-generated method stub Point p=new Point((int)e.getX(),(int)e.getY()); if(e.getAction()==e.ACTION_DOWN){ //当按下 if(f==false){ f=true; pointall=new ArrayList<Point>(); p=new Point(0,-2001); pointall.add(p); } p=new Point(0,linewight); pointall.add(p); p=new Point(0,color1); pointall.add(p); } else if(e.getAction()==e.ACTION_UP){//当抬起 pointall.add(p); paintview.this.postInvalidate(); //重绘 } else if(e.getAction()==e.ACTION_MOVE){ pointall.add(p); //移动时候 paintview.this.postInvalidate(); //重绘 } return true; } } protected void onDraw(Canvas canvas){ Paint p=new Paint(); //定义画笔 p.setColor(Color.BLACK); //定义颜色 if(pointall.size()>1){ Iterator<Point> iter=pointall.iterator();// 现在有坐标点保存的时候可以开始进行绘图 Point first=null; Point last=null; while(iter.hasNext()){ if(first==null){ first=(Point)iter.next(); } else{ if(last!=null){ first=last; //将下一个坐标点赋给上面的 } last=(Point)iter.next(); //不停下指 //判断线条颜色 if(first.y==1000)p.setColor(Color.BLACK);//黑 else if(first.y==-1001)p.setColor(Color.RED);//红 else if(first.y==-1002)p.setColor(Color.rgb(255, 150, 0));//橙 else if(first.y==-1003)p.setColor(Color.YELLOW);//黄 else if(first.y==-1004)p.setColor(Color.GREEN);//绿 else if(first.y==-1005)p.setColor(Color.CYAN);//青 else if(first.y==-1006)p.setColor(Color.BLUE);//蓝 else if(first.y==-1007)p.setColor(Color.MAGENTA);//紫 else if(first.y==-1008)p.setColor(Color.GRAY);//灰 //判断线条粗细 if(first.y==-2001)p.setStrokeWidth(1); else if(first.y==-2002)p.setStrokeWidth(2); else if(first.y==-2003)p.setStrokeWidth(3); else if(first.y==-2004)p.setStrokeWidth(4); else if(first.y==-2006)p.setStrokeWidth(6); else if(first.y==-2008)p.setStrokeWidth(8); //断线跳过 if(first.x==0||last.x==0)continue; canvas.drawLine(first.x, first.y, last.x, last.y,p); } } } } }
activity_main.xml: <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" > <com.example.day2.paintview android:id="@+id/paintview" android:layout_width="465dp" android:layout_height="216dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" /> <Spinner android:id="@+id/colortext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignTop="@+id/paintview" android:entries="@array/datacolor" /> <ImageButton android:id="@+id/imageButton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@+id/colortext" android:src="@drawable/onepx" /> <ImageButton android:id="@+id/imageButton2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/paintview" android:layout_below="@+id/imageButton1" android:src="@drawable/twopx" /> <ImageButton android:id="@+id/imageButton3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/paintview" android:layout_below="@+id/imageButton2" android:src="@drawable/threepx" /> <ImageButton android:id="@+id/imageButton4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/paintview" android:layout_below="@+id/imageButton3" android:src="@drawable/fourpx" /> <ImageButton android:id="@+id/imageButton5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/paintview" android:layout_below="@+id/imageButton4" android:src="@drawable/sixpx" /> <ImageButton android:id="@+id/imageButton6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/paintview" android:layout_below="@+id/imageButton5" android:src="@drawable/eighpx" /> </RelativeLayout>
选择框配置xml <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="datacolor"> <item>黑色</item> <item>红色</item> <item>橙色</item> <item>黄色</item> <item>绿色</item> <item>青色</item> <item>蓝色</item> <item>紫色</item> <item>灰色</item> </string-array> </resources>
谢谢欣赏,不足之处还请多多指教
反正我做完就这样了,也不打算改,想怎么说就怎么说吧。
相关推荐
2. **UI设计与优化**:描述中提到"新学Android 很多需要优化的地方",这可能指的是UI界面的设计和用户体验的优化。在Android上,设计师通常使用XML来定义界面布局,通过自定义View和Adapter实现复杂功能。性能优化...
自己写的一个小工具,感兴趣的朋友可以下载来玩玩。 本人G10 上测试没问题,可以运行良好。 【软件功能】 生肖查询软件包括以下几项功能:生肖查询、生肖性格、生肖爱情、生肖优缺点、生肖事业、生肖理财、生肖配对...
数学新学案同步必修4北师大版:第二章滚动训练二
【标题】:“基于Android的英文词典”是一个应用程序开发项目,旨在为用户提供便捷的英语单词查询服务。这个应用集成了在线查询和本地查询两种方式,同时具备生词本和心得日记的功能,帮助用户学习和积累英语词汇。 ...
新学学校工作计划.pdf
这款应用利用SQLite数据库技术,结合Android Studio的开发环境,以及Java编程语言,为用户提供了一个高效、便捷的方式来存储和复习新学的西班牙语单词。 首先,让我们深入了解一下Android-My-Spanish-Vocab的核心...
6. 太阳活动:太阳黑子是太阳活动的重要标志之一,与之相似的是耀斑,都是太阳表面能量释放的表现。 7. 太阳活动周期:从太阳黑子年际变化图中可以判断,2020年前后,如果黑子数量增多,代表太阳活动处于活跃期,...
2022九月新学年初一开学第一课教案多篇_教师工作计划.pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809121007).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809110647).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809142205).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809104751).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809110515).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809102654).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809100942).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809102150).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809100318).pdf
2022九月新学年初一开学第一课教案多篇_教师工作计划(20210809100343).pdf
该压缩包文件“基于Android的单词学习APP源码数据库.zip”包含了用于开发一款Android平台上的单词学习应用的源代码和数据库资源。这个项目可能是一个毕业设计项目,涉及到的技术栈包括Java、微信小程序以及...
中学新学年度工作思路汇报.doc