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




   
       
       

       
       
       
   


MarqueeImageView 如果不指定的话默认会有一个背景图名称为 marquee_task.jpg,记得放在drawable文件夹内

Android自定义View --来回滚动背景_第1张图片

如果你觉得写的好的话,支付包走一波喽,嘿嘿

Android自定义View --来回滚动背景_第2张图片





你可能感兴趣的:(Android,自定义View)