Easy Tutorial
❮ Android Tutorial End Programmer Joke 17 ❯

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:

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 /**

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 Android Basic Tutorial

-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)

Follow on WeChat

❮ Android Tutorial End Programmer Joke 17 ❯