来回滚动的背景在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"?>


   
       
       
       
       
       
   


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

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






更多相关文章

  1. Android布局之线性布局
  2. 自定义TextView跑马灯效果可控制启动/停止/速度
  3. Android系统联系人全特效实现(下),字母表快速滚动
  4. Android(安卓)ListView 设定背景图后拖动时整体背景变黑的解决
  5. Android简单实现滚动悬停效果
  6. ScrollView源码分析
  7. layout_gravity部局的一些问题
  8. Android(安卓)background背景图片平铺
  9. Android(安卓)CoordinatorLayout使用

随机推荐

  1. jQuery+PHP实现购物商城常用的星级评分效
  2. PHP-FPM与Swoole的比较
  3. Docker+LNMP+Jenkins+码云实现 PHP 代码
  4. 详解php soap实现web service接口服务
  5. 关于php中匿名函数与回调函数的详解
  6. php中异步执行的四种方式
  7. php实现队列的详细步骤
  8. 关于PHP中self关键字的用法详解
  9. php开发一个文件管理系统(附代码)
  10. 解决CentOS7中php-fpm进程数过多导致服务