8.3.2 Practical Example of Drawing Classes
Category Android Basic Tutorial
Introduction to This Section:
>
In the previous two sections, we learned about Bitmap and some basic properties of drawing APIs as well as commonly used methods, but we always felt a bit uneasy, we always need to write something to deepen the impression, right? Well, in this section, we are going to write two simple examples:
- Implementation of a simple drawing board
- A simple implementation of helping a beauty wipe her clothes
Hehe, the second example is a small demo that Xiaozhu wrote when he just started learning Android ~ Hehe ~ Let's start the content of this section ~
1. Practical Example 1: Implementation of a Simple Drawing Board:
>
I believe everyone is familiar with this, many mobile phones will come with a drawing board for users to doodle, here we will write a simple example, first let's analyze the logic of implementing this thing:
Q1: Where is this drawing board placed?
Answer: In the View, we customize a View, complete the drawing in onDraw(), and the View also has a onTouchEvent method, we can obtain the user's gesture operation!
Q2. What needs to be prepared?
Answer: A brush (Paint), a canvas (Canvas), a path (Path) to record the user's drawing route; In addition, when drawing a line, it is always from the point where the last drag occurred to the point where this drag occurred! So the previously drawn content will be lost, in order to save the previously drawn content, we can introduce the so-called "double buffering" technology: In fact, it is not drawn directly to the Canvas each time, but first drawn to the Bitmap, and after the drawing on the Bitmap is finished, it is drawn to the View at one time!
Q3. What is the specific implementation process?
Answer: Initialize the brush, set the color and other parameters; create a Bitmap of the size of the View in the onMeasure() method of the View, and create a Canvas at the same time; obtain the X, Y coordinates in the onTouchEvent, draw the connection line, and finally invalidate() redraw, that is, call the onDraw method to draw the content of the bitmap to the Canvas!
Well, the logic is known, and then the code is on:
MyView.java :
/**
* Created by Jay on 2015/10/15 0015.
*/
public class MyView extends View {
private Paint mPaint; // The Path for drawing lines
private Path mPath; // Record the user's Path
private Canvas mCanvas; // The Canvas created in memory
private Bitmap mBitmap; // Cache the content of the drawing
private int mLastX;
private int mLastY;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPath = new Path();
mPaint = new Paint(); // Initialize the brush
mPaint.setColor(Color.GREEN);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND); // The joint is rounded
mPaint.setStrokeCap(Paint.Cap.ROUND); // Set the turning point to be rounded
mPaint.setStrokeWidth(20); // Set the brush width
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
// Initialize bitmap, Canvas
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
// Override this method to draw here
@Override
protected void onDraw(Canvas canvas) {
drawPath();
canvas.drawBitmap(mBitmap, 0, 0, null);
}
// Draw the line
private void drawPath() {
mCanvas.drawPath(mPath, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
mPath.moveTo(mLastX
ImageView imgMezi = new ImageView(mContext);
imgMezi.setImageResource(mData[position]); //Create an ImageView
imgMezi.setScaleType(ImageView.ScaleType.FIT_XY); //Set the scaling type of the ImageView
imgMezi.setLayoutParams(new Gallery.LayoutParams(250, 250)); //Set layout parameters for the ImageView
TypedArray typedArray = mContext.obtainStyledAttributes(R.styleable.Gallery);
imgMezi.setBackgroundResource(typedArray.getResourceId(R.styleable.Gallery_android_galleryItemBackground, 0));
return imgMezi;
}
}
Finally, in our Activity, it's quite simple, just setting the onSelected event for the gallery, and after clicking the button, passing the current selected Position to the next page!
**MainActivity.java** :
```java
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener,
View.OnClickListener {
private Context mContext;
private ImageView img_choose;
private Button btn_choose;
private Gallery gay_choose;
private int index = 0;
private MeiziAdapter mAdapter = null;
private int[] imageIds = new int[]
{
R.mipmap.pre1, R.mipmap.pre2, R.mipmap.pre3, R.mipmap.pre4,
R.mipmap.pre5, R.mipmap.pre6, R.mipmap.pre7, R.mipmap.pre8,
R.mipmap.pre9, R.mipmap.pre10, R.mipmap.pre11, R.mipmap.pre12,
R.mipmap.pre13, R.mipmap.pre14, R.mipmap.pre15, R.mipmap.pre16,
R.mipmap.pre17, R.mipmap.pre18, R.mipmap.pre19, R.mipmap.pre20,
R.mipmap.pre21
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
bindViews();
}
private void bindViews() {
img_choose = (ImageView) findViewById(R.id.img_choose);
btn_choose = (Button) findViewById(R.id.btn_choose);
gay_choose = (Gallery) findViewById(R.id.gay_choose);
mAdapter = new MeiziAdapter(mContext, imageIds);
gay_choose.setAdapter(mAdapter);
gay_choose.setOnItemSelectedListener(this);
btn_choose.setOnClickListener(this);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
img_choose.setImageResource(imageIds[position]);
index = position;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
@Override
public void onClick(View v) {
Intent it = new Intent(mContext, CaClothes.class);
Bundle bundle = new Bundle();
bundle.putCharSequence("num", Integer.toString(index));
it.putExtras(bundle);
startActivity(it);
}
}
Next is the page where we erase the girl's clothes, the layout is quite simple, FrameLayout + two ImageViews in front and back:
activity_caclothes.xml :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/img_after"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/img_before"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
Then comes the Java part of the code:
CaClothes.java :
```java /**
- Created by Jay on 2015/10/16 0016. */ public class CaClothes extends AppCompatActivity implements View.OnTouchListener {
private ImageView img_after;
private ImageView img_before;
private Bitmap alterBitmap;
private Canvas canvas;
private Paint paint;
private Bitmap after;
private Bitmap before;
private int position;
int[] imageIds1 = new int[]
{
R.mipmap.pre1, R.mipmap.pre2, R.mipmap.pre3, R.mipmap.pre4,
R.mipmap.pre5, R.mipmap.pre6, R.mipmap.pre7, R.mipmap.pre8,
R.mipmap.pre9, R.mipmap.pre10, R.mipmap.pre11, R.mipmap.pre12,
R.mipmap.pre13, R.mipmap.pre14, R.mipmap.pre15, R.mipmap.pre16,
R.mipmap.pre17, R.mipmap.pre18, R.mipmap.pre19, R.mipmap.pre20,
R.mipmap.pre21
};
int[] imageIds2 = new int[]
{
R.mipmap.after1, R.mipmap.after2, R.mipmap.after3, R.mipmap.after4,
R.mipmap.after5, R.mipmap.after6, R.mipmap.after7, R.mipmap.after8,
R.mipmap.after9, R.mipmap.after10, R.mipmap.after11, R
img_before = (ImageView) findViewById(R.id.img_before);
BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 1; after = BitmapFactory.decodeResource(getResources(), imageIds2[position], opts); before = BitmapFactory.decodeResource(getResources(), imageIds1[position], opts); // The defined image is read-only
alterBitmap = Bitmap.createBitmap(before.getWidth(), before.getHeight(), Bitmap.Config.ARGB_4444); canvas = new Canvas(alterBitmap); paint = new Paint(); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeWidth(5); paint.setColor(Color.BLACK); paint.setAntiAlias(true); canvas.drawBitmap(before, new Matrix(), paint); img_after.setImageBitmap(after); img_before.setImageBitmap(before); img_before.setOnTouchListener(this);
@Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: int newX = (int) event.getX(); int newY = (int) event.getY(); // The setPixel method sets a pixel to a color, and here we set it to transparent // In addition, a nested for loop is used to set the 20*20 pixels in the finger touch area to transparent for (int i = -20; i < 20; i++) { for (int j = -20; j < 20; j++) { if (i + newX >= 0 && j + newY >= 0 && i + newX < before.getWidth() && j + newY < before.getHeight()) alterBitmap.setPixel(i + newX, j + newY, Color.TRANSPARENT); } } img_before.setImageBitmap(alterBitmap); break; } return true; }
The code is not difficult to understand, it's quite simple, right? Well, just look at the effect, don't do too many right-hand helix rules...
3. Download the code example:
DrawDemo1.zip The project is quite large, over 20M, with many image resources, you know~
Summary of this section:
.
-1.0.1 Latest Android Basic Tutorial Catalog for 2015
-1.1 Background and System Architecture Analysis
-1.2 Development Environment Setup
-1.2.1 Developing Android APP with Eclipse + ADT + SDK
-1.2.2 Developing Android APP with Android Studio
-1.3 Solving SDK Update Issues
-1.4 Genymotion Emulator Installation
-1.5.1 Git Tutorial on Basic Operations of Local Repositories
-1.5.2 Git: Setting Up a Remote Repository with GitHub
-1.6 How to Play with 9 (Nine Sister) Images
-1.7 Interface Prototype Design
-1.8 Project Related Analysis (Various Files, Resource Access)
-1.9 Android Program Signing and Packaging
-1.11 Decompiling APK to Retrieve Code & Resources
-2.1 The Concept of View and ViewGroup
-2.2.1 LinearLayout (Linear Layout)
-2.2.2 RelativeLayout (Relative Layout)
-2.2.3 TableLayout (Table Layout)
-2.2.4 FrameLayout (Frame Layout)
-2.2.5 GridLayout (Grid Layout)
-2.2.6 AbsoluteLayout (Absolute Layout)
-2.3.1 TextView (Text Box) Detailed Explanation
-2.3.2 EditText (Input Box) Detailed Explanation
-2.3.3 Button (Button) and ImageButton (Image Button)
-[2.3.4 ImageView (Image View)
2.6.4 Simple Usage of DrawerLayout (Official Side-Slide Menu)
3.6 Responding to System Setting Events (Configuration Class)
4.4.2 Further Exploration of ContentProvider - Document Provider
5.2.1 Detailed Explanation of Fragment Example - Implementation of Bottom Navigation Bar (Method 1)
5.2.2 Detailed Explanation of Fragment Example - Implementation of Bottom Navigation Bar (Method 2)
5.2.3 Detailed Explanation of Fragment Example - Implementation of Bottom Navigation Bar (Method 3)
5.2.4 Detailed Explanation of Fragment Example - Bottom Navigation Bar + ViewPager Page Switching
6.2 Data Storage and Access - SharedPreferences for Saving User Preferences
7.1.1 What to Learn in Android Network Programming and Http Protocol Study
7.1.2 Learning about Android Http Request and Response Headers
[7.3.3 Android
8.3.14 Paint Enum/Constant Values and ShadowLayer Shadow Effects
8.3.17 Detailed Explanation of Canvas API (Part 2) - Collection of Clipping Methods
8.3.18 Detailed Explanation of Canvas API (Part 3) - Matrix and drawBitmapMesh
8.4.3 Android Animation Collection - Property Animation - First Encounter
8.4.4 Android Animation Collection - Property Animation - Another Encounter
11.0 "2015 Latest Android Basic Tutorial" Concludes with Fireworks~
12.2 DrySister Girl Viewing App (First Edition) - 2. Parsing Backend Data
12.4 DrySister Girl Viewing App (First Edition) - 4. Adding Data Caching (Integrating SQLite)