Finally I have made my second app in android -paint app- I was so interested in making this app because I like drawing , It’s one of my hobbies.
now let start going into the project.
This is the final result of the project .
Before drawing
After drawing
Change color
Make new page, change the size of the brush ,use eraser change the size of it, save your drawing to the gallery.
Now I will start explaining the coding part
Firstly create new android project, exactly same as previous project.
And create user interface of the app add picture buttons insert background , add dimensions for brush/eraser sizes
<!-- Brush sizes --> <dimen name="small_brush">10dp</dimen> <integer name="small_size">10</integer> <dimen name="medium_brush">20dp</dimen> <integer name="medium_size">20</integer> <dimen name="large_brush">30dp</dimen> <integer name="large_size">30</integer>
,add strings for new page ,brush ,eraser,save, and paint.
<string name="start_new">New</string> <string name="brush">Brush</string> <string name="erase">Erase</string> <string name="save">Save</string> <string name="paint">Paint</string>
inside the activity_main.xml i had made LinearLayout as the main layout.and drag LinearLayout inside th main main layout and to make the rows of the color i have made this for first row
<LinearLayout android:id="@+id/paint_colors" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > </LinearLayout>
and second row
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > </LinearLayout>
the first row has an id because use in java class when the app starts the first default color as selected so that the user can start drawing straight away.i added a new xml file and named it "paint.xml" inside the drawable file and wrote the following code
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="rectangle" > <stroke android:width="4dp" android:color="#FF999999" /> <solid android:color="#00000000" /> <padding android:bottom="0dp" android:left="0dp" android:right="0dp" android:top="0dp" /> </shape> </item> <item> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <stroke android:width="4dp" android:color="#FF999999" /> <solid android:color="#00000000" /> <corners android:radius="10dp" /> </shape> </item> </layer-list>
it is a little complex than it looks at first glance. To create a rounded button appearance, we use two layered Shape drawables, one rectangle outline and theother a rounded stroke.The strokes have gray color , with transparency in the middle through which the background color for each button will be seen(the background color being the color represented by the button).
so, now for each color, i used the following ImageButton structure:
inside the first row LinearLayout
<ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF660000" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF660000" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FFFF0000" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FFFF0000" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FFFF6600" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FFFF6600" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FFFFCC00" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FFFFCC00" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF009900" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF009900" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF009999" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF009999" />
inside the second row LinearLayout
<ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF0000FF" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF0000FF" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF990099" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF990099" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FFFF6666" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FFFF6666" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FFFFFFFF" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FFFFFFFF" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF787878" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF787878" /> <ImageButton android:layout_width="@dimen/large_brush" android:layout_height="@dimen/large_brush" android:layout_margin="2dp" android:background="#FF000000" android:contentDescription="@string/paint" android:onClick="paintClicked" android:src="@drawable/paint" android:tag="#FF000000" />
i used one of the dimension values that i had defined for th color button.
after finishing the user interface i started to implement drawing on the canvas and choosing colors.
create new class named it DrawingView and extends View and then define all the variables that i will use:
//drawing path private Path drawPath; //drawing and canvas paint private Paint drawPaint, canvasPaint; //initial color private int paintColor = 0xFF660000; //canvas private Canvas drawCanvas; //canvas bitmap private Bitmap canvasBitmap;
when the user touches the screen and moves their finger to draw, I used a path to trace their drawing actin on the canvas.Both the canvas and the drawing on top of it are represented by paint objects. The initial paint color corresponds to the first color in the palette i had created before , which will be initiallly selected when the app launches. Finally i declared variables for the canvas and bitmap- the user paths drawn with drawPaint wil be drawn onto the canvas, which is drawn with canvasPaint.
added new method and named it setupDrawing and instantiate some of these variables to set set the class up for drawing .
first instantiate the drawing Path and Paint objects
next set the initial color
and then set the initail path properties:
drawPath = new Path(); drawPaint = new Paint(); //drawPaint.setColor(paintColor); drawPaint.setAntiAlias(true); drawPaint.setStrokeWidth(20); drawPaint.setStyle(Paint.Style.STROKE); drawPaint.setStrokeJoin(Paint.Join.ROUND); drawPaint.setStrokeCap(Paint.Cap.ROUND);
complete the setupDrawing method by instantiating the canvas Paint object:
canvasPaint = new Paint(Paint.DITHER_FLAG);
i set dithering by passing a parameter to constructor.
then override the couple of methods to make the custom view function as a drawing view.
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { //view given size super.onSizeChanged(w, h, oldw, oldh); canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); drawCanvas = new Canvas(canvasBitmap); } @Override protected void onDraw(Canvas canvas) { //draw view canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); canvas.drawPath(drawPath, drawPaint); }
when the drawing view is on the app screen, we want user touches on it to regester as drawing operations.
to do this we need to listen for touch events.
public boolean onTouchEvent(MotionEvent event) { //detect user touch float touchX = event.getX(); float touchY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: drawPath.moveTo(touchX, touchY); break; case MotionEvent.ACTION_MOVE: drawPath.lineTo(touchX, touchY); break; case MotionEvent.ACTION_UP: drawCanvas.drawPath(drawPath, drawPaint); drawPath.reset(); break; default: return false; } invalidate(); return true;//Calling invalidate will cause the onDraw method to execute. }
The MotionEvent parameter to the onTouchEvent method will let us respond to particular touch events. the actions we are interesteed in to implement drawing are down,move and up. Added a switch statement in the method to respond .
when the user touches the view, we move to that position to start drawing. when they move thier finger on the View wedraw the path along with their touch. when they lift their finger up off the view , we draw the path and reset it for the next drawing operation.
Let's now talk about implementing the ability for the user to choose colors from the palette.
inside main activity class inside onCreate methode i instantiated variables by retrieving a reference to it from the layout:
drawView = (DrawingView)findViewById(R.id.drawing); LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors); currPaint = (ImageButton)paintLayout.getChildAt(0); currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed)); smallBrush = getResources().getInteger(R.integer.small_size); mediumBrush = getResources().getInteger(R.integer.medium_size); largeBrush = getResources().getInteger(R.integer.large_size); drawBtn = (ImageButton)findViewById(R.id.draw_btn); drawBtn.setOnClickListener(this); drawView.setBrushSize(mediumBrush); eraseBtn = (ImageButton)findViewById(R.id.erase_btn); eraseBtn.setOnClickListener(this); newBtn = (ImageButton)findViewById(R.id.new_btn); newBtn.setOnClickListener(this); saveBtn = (ImageButton)findViewById(R.id.save_btn); saveBtn.setOnClickListener(this);
get the fir button and store it as the instance varable and use different drawable image on the button to show that it is currently selected:
currPaint = (ImageButton)paintLayout.getChildAt(0); currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
i added this new "paint_pressed.xml" file inside drawable file and wrote the following code
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="rectangle" > <stroke android:width="4dp" android:color="#FF333333" /> <solid android:color="#00000000" /> <padding android:bottom="0dp" android:left="0dp" android:right="0dp" android:top="0dp" /> </shape> </item> <item> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <stroke android:width="4dp" android:color="#FF333333" /> <solid android:color="#00000000" /> <corners android:radius="10dp" /> </shape> </item> </layer-list>
it is very similar to the"paint.xml"drawable we created last time, but with darker color around the paint.
I went go back to main activity class and added paintClicked method
public void paintClicked(View view){ //use chosen color if(view!=currPaint){ //update color ImageButton imgView = (ImageButton)view; String color = view.getTag().toString(); drawView.setColor(color); imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed)); currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint)); currPaint=(ImageButton)view; } }
first check that the user has clicked a paint color that is not the currently selected one,then retrieve the tag we set for each button in the layout , representing the chosen color.
then i needed to use the custom View class to set the color , so i added set color in side Drawing View class
public void setColor(String newColor){ //set color invalidate(); paintColor = Color.parseColor(newColor); drawPaint.setColor(paintColor); }
start by invalidating th View , then set the color for drawing, now going back to the main activity, in paintClicked method after retriving the color tag , call the new method on the custom drawing View object and then update th user interface to reflect the new chosen paint and set the previouse one back to the normal.
now i will discuss the last part of my project. About the ability to erase to create new drawing page ,to save a drawing to the gallary of your device.
in the previouse part i discussed about drawing on the canvas, then now i will discuss how to make the user choose a brush size. The brush size options will appear when the user presses the brush button I added t the interface. To respond to this, extend the opening line of in main activity class declaration to the implement the OnClickListener interface:
public class MainActivity extends Activity implements OnClickListeneroverride onClick method and check for clicks on the drawing button using if statement
@Override public void onClick(View view){ //respond to clicks if(view.getId()==R.id.draw_btn){ //draw button clicked final Dialog brushDialog = new Dialog(this); brushDialog.setTitle("Brush size:"); } }
there are another coditional blocks i will speak about them later.When the user clicks the button i already displayed a dialog presenting them with the three button sizes.Inside the if block, and create a dialog and set the titleThen i defined the dialog layout in "brush_chooser.xml" inside layout file and entering the following code and inside the Layout ,added a button for each size:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <ImageButton android:id="@+id/small_brush" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:contentDescription="@string/sml" android:src="@drawable/small" /> <ImageButton android:id="@+id/medium_brush" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:contentDescription="@string/med" android:src="@drawable/medium" /> <ImageButton android:id="@+id/large_brush" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:contentDescription="@string/lrg" android:src="@drawable/large" /> </LinearLayout>
then dd specified strings to "string.xml" Small ,Medium,Large then add three xml files for each of them
相关推荐
A Second Course in Stochastic Process A Second Course in Stochastic Process
本文将基于“Robotium_Test Android Sample App.pdf”这一文档,深入解析如何利用Robotium来测试Android应用,包括创建测试项目、编写测试用例、添加Robotium jar以及编写测试代码的具体步骤。 ### 一、创建测试...
Perfect for kids ages 10 and over who are ready to take a second step after Scratch, Coding Projects in Python teaches kids how to build amazing graphics, fun games, and useful apps. All they need is ...
根据提供的文件信息,“A Second Course in Stochastic Processes”是一本深入探讨随机过程理论与应用的专业书籍,由Samuel Karlin和Howard M. Taylor共同撰写。本书作为“Stochastic Processes”领域的进阶教材,...
【标题】"SecondProject:创建虚拟的Secondproject" 涉及的知识点主要围绕着软件开发中的项目管理和版本控制工具Git。在这个项目中,我们关注的是如何使用Git来创建和管理一个名为"SecondProject"的虚拟项目。 首先...
"Beginning Android Games, Second Edition offers everything you need to join the ranks of successful Android game developers, including Android tablet game app development considerations. You'll start...
App Inventor 2 Building Android Apps takes you step-by-step through the whole process of designing and creating your first two android apps using the free MIT App Inventor 2 software. The book is ...
标题“测试referrer的SecondApp的代码”表明这是一个针对名为 "SecondApp" 的Android应用进行的测试,目的是验证 `getReferrer()` 方法的功能。这通常发生在开发者想要确保从其他应用跳转到 "SecondApp" 时,能够...
Each recipe provides a clear solution and sample code you can use in your project right away. Among numerous topics, this cookbook helps you: Get started with the tooling you need for developing and...
Later in the second part the reader will learn RxJava 2.0 step-by-step by starting off with stock data processing and display. Together with this a developer will learn to choose appropriate ...
这里包括两个 eclipse 工程, 在一个工程FirstAndroid里调用另一个工程SecondAndroid里的Activity 和 Service,SecondAndroid只能通过别的app 来启动,它自己不能启动,因为它没有 android.intent.action.MAIN这个...
The first one is an android project,and the second is an intellij plugin project. You can see more information in the respective project,and I hope you can tell me your suggestions. Developed By ...
Sunshine is the companion Android app for the Udacity course Developing Android Apps: Android Fundamentals. Take the course to find out how to build this app a step at a time, and eventually create ...
应用调用应用程序调用是一个演示,用于显示Android和html页面中的...通过网络浏览器打开Android应用通过另一个应用程序打开Android应用程序申请者网页浏览器项目路径: app-call/web/ 发送带有查询参数的参数: href=...