天天看點

Android自定義View --來復原動背景

來復原動的背景在Android在Android 可謂是很常見了,今天自己寫了一個,有參考别人的代碼,修複了記憶體洩露問題,marqueeImage會根據view大小和背景圖的大小選則是橫向滾動還是豎着滾動,如果寫的有什麼不足或者漏洞歡迎批評指正,如果覺得寫的好的話,支付寶走一波哈哈,自己寫的一些view 也會繼續更新 謝謝大家 嘿嘿

拷貝下面的代碼和attr.xml檔案到項目中就可以用了

public class MarqueeImageView extends View {

    private static final String TAG = "MarqueeImageView";

    //region

    private Thread thread =  new Thread(

            new Runnable() {

                @Override

                public void run() {

                    while (start) {

                        try {

                            Thread.sleep(time);

                        } catch (InterruptedException e) {

                            e.printStackTrace();

                        }

                        handler.sendEmptyMessage(0x123);

                    }

                }

            }

    );

    //endregion

    private Handler handler = new Handler() {

        @Override

        public void handleMessage(Message msg) {

            super.handleMessage(msg);

            switch (msg.what) {

                case 0x123:

                    invalidate();//重繪

                    break;

            }

        }

    };

    private boolean start = true;//用來記錄是否滾動

    enum DirectionEnum {

        left, right,up,down//方向枚舉

    }

    enum Orientation{

        horizontal, vertical//水準,垂直

    }

    private Bitmap background = null;

    private int nowX = 0, nowY = 0;

    private int backWidth, backHeight;//背景圖寬,高

    private int time = 40;

    private int MViewHeight = 0,MViewWidth = 0;

    private Orientation orientation;//方向

    private int speed;//速度

    private DirectionEnum direction = DirectionEnum.left;//向左

    public MarqueeImageView(Context context) {

        super(context);

    }

    public MarqueeImageView(Context context, @Nullable AttributeSet attrs) {

        super(context, attrs);

        getAttr(attrs);

    }

    @Override

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);

        MViewHeight = h;

        MViewWidth = w;

        init();

    }

    public void init() {

        int h = background.getHeight();

        int w = background.getWidth();

        Log.d(TAG, "init: h" + h);

        Log.d(TAG, "init: w" + w);

        Log.d(TAG, "init: (float)(w/MViewWidth) " + (float)(w/MViewWidth));

        //水準滾動

        if ((float)(w/MViewWidth) > (float)(h/MViewHeight)){

            orientation = Orientation.horizontal;

            int imageW = (int) ((float) MViewHeight/ h * w);

            Log.d(TAG, "init: imageW" + imageW);

            background = Bitmap.createScaledBitmap(background, imageW, MViewHeight, true);

            backWidth = background.getWidth();//背景寬

            Log.d(TAG, "start: backWidth" + backWidth);

        }

        else {

            orientation = Orientation.vertical;//那就垂直滾動吧

            int imageH = (int) ((float)MViewWidth/w * h);

            Log.d(TAG, "init: imageH " + imageH);

            background = Bitmap.createScaledBitmap(background, MViewWidth, imageH, true);

            backHeight = background.getHeight();//背景圖寬

            Log.d(TAG, "init: backHeight " + backHeight);

        }

        start();//調用下這個方法

    }

    public void start() {

        start = true;

        handler.sendEmptyMessage(0x123);

        thread.start();

    }

    private void getAttr(AttributeSet attrs) {

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MarqueeImageView);

        speed = typedArray.getInteger(R.styleable.MarqueeImageView_speed, 1);

        time = typedArray.getInteger(R.styleable.MarqueeImageView_time, 40);

        int resourceId = typedArray.getResourceId(R.styleable.MarqueeImageView_image, R.drawable.marquee_task);

        background = BitmapFactory.decodeResource(getResources(), resourceId);

        typedArray.recycle();

    }

    @Override

    protected void onDraw(Canvas canvas) {

        if (background == null) //如果背景圖為空直接傳回

            return;

        //如果是水準滾動

        if (orientation == Orientation.horizontal){

            if (nowX <= 0) {

                nowX += speed;

                direction = DirectionEnum.left;//向左移動

            }

            else if (nowX >= backWidth - MViewWidth - speed) {

                nowX -= speed;

                direction = DirectionEnum.right;//左邊走到頭開始向又走

            }

            else {

                if (direction == DirectionEnum.right) {

                    nowX -= speed;

                } else {

                    nowX += speed;

                }

            }

        }

        else{

            if (nowY <= 0) {

                nowY += speed;

                direction = DirectionEnum.up;//向上

            } else if (nowY >= backHeight - MViewHeight - speed) {

                nowY -= speed;//減去速度

                direction = DirectionEnum.down;//向下移動

            } else {

                if (direction == DirectionEnum.up)//如果方向是向上

                    nowY += speed;

                else

                    nowY -= speed;

            }

        }

        //當水準滾動時,nowY為0, 垂直滾動時nowX為0

        Bitmap bitmap = Bitmap.createBitmap(background, nowX, nowY, MViewWidth, MViewHeight);

        canvas.drawBitmap(bitmap, 0, 0, null);

        Log.d(TAG, "onDraw: ");

    }

    //從視窗分離出來

    @Override

    protected void onDetachedFromWindow() {

        super.onDetachedFromWindow();

        Log.d(TAG, "onDetachedFromWindow: ");

        start = false;//線程就不要執行了

    }

}

attr.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <declare-styleable name="MarqueeImageView">

        <attr name="speed" format="integer">

        </attr>

        <!--背景圖-->

        <attr name="image" format="reference"></attr>

        <attr name="time" format="integer"></attr>

    </declare-styleable>

</resources>

MarqueeImageView 如果不指定的話預設會有一個背景圖名稱為 marquee_task.jpg,記得放在drawable檔案夾内

Android自定義View --來復原動背景

如果你覺得寫的好的話,支付包走一波喽,嘿嘿

Android自定義View --來復原動背景