2015年10月14日 星期三

制作自定義的View3-提取和封裝自定義View


上次已完成的自定義View


public class LogicView extends View {
    private Paint paint = new Paint();
    private int rx = 0;
    private MyThread myThread = null;
    private String showString = "show me";
    private RectF rectF = new RectF(0, 40, 600, 640);
    private float sweepAngle = 0;

    public LogicView(Context context) {
        super(context);
    }


    public LogicView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setTextSize(200);
        canvas.drawText(showString, rx, 300, paint);
        canvas.drawArc(rectF, 0, sweepAngle, true, paint);//why true?
        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        }
        //invalidate(); //cal by ui thread
        //postInvalidate();
        //canvas.drawText("hi",rx,300,paint);
    }

    class MyThread extends Thread {

        @Override
        public void run() {
            Random random = new Random();
            super.run();

            while (true) {
                if (rx > getWidth()) {
                    rx = 0 - (int) paint.measureText(showString);
                }
                if (sweepAngle > 360) {
                    sweepAngle = 0;
                }

                paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
                rx = rx + 20;
                sweepAngle += 2;
                postInvalidate();//call by non-UI thread
                try {
                    Thread.sleep(30);//important !!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

}



但要修改和重用會好難,所以要提取和封裝
0.change the name to BaseView
1. 在onDraw中,把


取出,put in to the new Method logic drawsub

void drawsub(Canvas canvas){
        paint.setTextSize(200);
        canvas.drawText(showString, rx, 300, paint);
        canvas.drawArc(rectF, 0, sweepAngle, true, paint);//why true?
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawsub(canvas);
        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        }
        //invalidate(); //cal by ui thread
        //postInvalidate();
        //canvas.drawText("hi",rx,300,paint);
    }



2.in the MyThread run() method

pull out


if (rx > getWidth()) {
                    rx = 0 - (int) paint.measureText(showString);
                }
                if (sweepAngle > 360) {
                    sweepAngle = 0;
                }

                paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
                rx = rx + 20;
                sweepAngle += 2;


put into logic method


void logic(){
    if (rx > getWidth()) {
        rx = 0 - (int) paint.measureText(showString);
    }
    if (sweepAngle > 360) {
        sweepAngle = 0;
    }

    paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
    rx = rx + 20;
    sweepAngle += 2;
}

public void run() {
            super.run();
            while (running) {
                logic();
                postInvalidate();//call by non-UI thread
                System.out.println("thread still running");
                try {
                    Thread.sleep(30);//important !!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }


3. add protected abstract inforant of the logic and drawsub method


 protected abstract void drawsub(Canvas canvas);
 protected abstract void logic();


4.Finally .BaseView


package pom.poly.com.trymakeviewbymyself.myView.v3;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by User on 14/10/2015.
 */
public abstract class BasicView extends View {

    private MyThread myThread = null;
    private boolean running = true;


    public BasicView(Context context) {
        super(context);
    }

    public BasicView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected abstract void drawsub(Canvas canvas);

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        } else {
            drawsub(canvas);
        }
        //invalidate(); //cal by ui thread
        //postInvalidate();
        //canvas.drawText("hi",rx,300,paint);
    }

    protected abstract void logic();

    @Override
    protected void onDetachedFromWindow() {
        running=false;
        super.onDetachedFromWindow();
        System.out.println("in onDetachedFromWindow");
    }

    class MyThread extends Thread {

        @Override
        public void run() {
            super.run();
            while (running) {
                logic();
                postInvalidate();//call by non-UI thread
                System.out.println("thread still running");
                try {
                    Thread.sleep(30);//important !!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

5. craet LogicView, extends Basae View, overide the logic and drawsub


package pom.poly.com.trymakeviewbymyself.myView.v3;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;

import java.util.Random;

/**
 * Created by User on 14/10/2015.
 */
public class LogicView extends BasicView {
    private Paint paint = new Paint();
    private int rx = 0;
    private Random random = new Random();
    private String showString = "show me";
    private RectF rectF = new RectF(0, 40, 600, 640);
    private float sweepAngle = 0;

    public LogicView(Context context) {
        super(context);
    }

    public LogicView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void drawsub(Canvas canvas) {
        paint.setTextSize(200);
        canvas.drawText(showString, rx, 300, paint);
        canvas.drawArc(rectF, 0, sweepAngle, true, paint);//why true?
    }

    @Override
    protected void logic() {
        if (rx > getWidth()) {
            rx = 0 - (int) paint.measureText(showString);
        }
        if (sweepAngle > 360) {
            sweepAngle = 0;
        }

        paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
        rx = rx + 20;
        sweepAngle += 2;
    }
}



Now,the view is more easy to change .
The finall important thing is , How to prevent the thread that we create keep run after exit then app?


protected void onDetachedFromWindow() {
        running=false;
        super.onDetachedFromWindow();
        System.out.println("in onDetachedFromWindow");
    }

onDetachedFromWindow call when view detach from the window
at this method,when we seat the boolean to false, the thread stop to loop.