锤子滚动的textview

public class VerticalMarqueeView extends View {
    // 滚动时间
    public static final int               DURATION_SCROLL   = 3000;
    // 动画时间
    public static final int               DURATION_ANIMATOR = 1000;
    // 广告颜色
    private             int               color             = Color.BLACK;
    private             int               textSize          = 30;
    // 广告行数
    private             int               row               = 1;
    // 数据源
    private             ArrayList<String> datas             = new ArrayList<>();
    // 当前点击的位置
    private             int               index             = 0;

    private int width;
    private int height;
    private int centerX;
    private int centerY;

    private List<TextBlock> blocks       = new ArrayList<TextBlock>();
    private Paint           paint        = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Handler         handler      = new Handler();
    private boolean         isStopScroll = true;
    // 控制滚动的Runnable
    private Runnable runnable;

    public VerticalMarqueeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

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

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

    public VerticalMarqueeView color(int color) {
        this.color = color;
        return this;
    }

    public VerticalMarqueeView textSize(int textSize) {
        this.textSize = textSize;
        return this;
    }

    public VerticalMarqueeView datas(ArrayList<String> data) {
        LogUtils.d("传输大小--》" + data.size());
        this.blocks.clear();
        this.datas.clear();
        this.datas.addAll(data);
        return this;
    }

    public ArrayList<String> getDatas() {
        return datas;
    }

    public VerticalMarqueeView row(int row) {
        this.row = row;
        return this;
    }

    public void commit() {
        if (this.datas == null || datas.size() == 0) {
            Log.e("VerticalMarqueeView", "the datas's length is illegal");
            throw new IllegalStateException("may be not invoke the method named datas(String[])");
        }
        paint.setColor(color);
        paint.setTextSize(textSize);
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (this.datas == null || this.datas.size() == 0) {
            Log.e("VerticalMarqueeView", "the datas's length is illegal");
            return;
        }

        if (datas.size() < row) {
            Log.e("VerticalMarqueeView", "行数不能大于数据大小");
            return;
        }
        width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        // 计算每一项的高
        height = (MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom()) / row;
        // 如果需要居中,这里除以2
        centerX = width / 2;
        centerY = height / 2;
        blocks.clear();
        //添加显示区域的文字块
        for (int i = 0; i <= row; i++) {
            TextBlock block = new TextBlock(width, height, paint);
            block.reset(datas.get(i), centerX, centerY + height * i, i);
            blocks.add(block);
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                LogUtils.d("高:" + getHeight() + "Y:" + event.getY() + "position:" + (event.getY() / ((getHeight() - row) / row)));
                index = (int) (event.getY() / ((getHeight() - row) / row));
                break;

            case MotionEvent.ACTION_UP:
                if (listener != null) {
                    listener.onItemClick(blocks.get(index)
                            .getPosition());
                }
                break;
        }
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        for (int i = 0; i < blocks.size(); i++) {
            blocks.get(i)
                    .draw(canvas);
        }
    }

    public void startScroll() {
        isStopScroll = false;
        if (datas == null || datas.size() == 0 || datas.size() == 1) {
            Log.e("VerticalMarqueeView", "the datas's length is illegal");
            return;
        }
        if (!isStopScroll) {
            if (runnable == null) {
                runnable = new Runnable() {

                    @Override
                    public void run() {
                        scroll();
                        if (!isStopScroll) {
                            handler.postDelayed(this, DURATION_SCROLL);
                        }
                    }
                };
                handler.postDelayed(runnable, DURATION_SCROLL);
            }

        }
    }

    public boolean isStopScrolling() {
        return isStopScroll;
    }

    public void stopScroll() {
        this.isStopScroll = true;
    }

    private void scroll() {
        LogUtils.d("滚动");
        ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(PropertyValuesHolder.ofInt("scrollY", centerY, centerY - height));
        animator.setDuration(DURATION_ANIMATOR);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int scrollY = (int) animation.getAnimatedValue("scrollY");
                for (int i = 0; i < blocks.size(); i++) {
                    blocks.get(i)
                            .reset(scrollY + height * i);
                }
                invalidate();
            }
        });
        animator.addListener(new AnimatorListener() {

            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (blocks.size() == 0) {
                    return;
                }
                //移除第一块
                int position = blocks.get(row)
                        .getPosition();
                TextBlock textBlock = blocks.remove(0);
                //最后一个
                if (position == datas.size() - 1) {
                    position = 0;
                } else {
                    position++;
                }
                textBlock.reset(datas.get(position), centerY + height * (position + row), position);
                blocks.add(textBlock);
                invalidate();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }
        });
        animator.start();
    }

    public int getCurrentPosition() {
        if (datas == null || datas.size() == 0) {
            return -1;
        }
        if (datas.size() == 1 && blocks.size() == 1) {
            return 0;
        }
        return blocks.get(0)
                .getPosition();
    }

    public class TextBlock {
        private int    width;
        private int    height;
        private String text;
        private int    drawX;
        private int    drawY;
        private int    pointDrawX;
        private int    pointDrawY;
        private Paint  paint;
        private Paint  pointPaint;
        private int    position;

        public TextBlock(int width, int height, Paint paint) {
            this.width = width;
            this.height = height;
            this.paint = paint;
            this.pointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            pointPaint.setColor(paint.getColor());
            pointPaint.setTextSize(paint.getTextSize());
        }

        public void reset(int centerY) {
            reset(text, centerX, centerY, position);
        }

        public void reset(String text, int centerY) {
            reset(text, centerX, centerY, position);
        }

        public void reset(String text, int centerY, int position) {
            reset(text, centerX, centerY, position);
        }

        public void reset(String text, int centerX, int centerY, int position) {
            this.text = text;
            this.position = position;
            // 先绘制点•
            int pointWidth = (int) pointPaint.measureText("•");
            pointDrawX = 0;
            FontMetrics pointMetrics = pointPaint.getFontMetrics();
            pointDrawY = (int) (centerY + (pointMetrics.bottom - pointMetrics.top) / 2 - pointMetrics.bottom);

            // 绘制正文
            int measureWidth = (int) paint.measureText(text);

            // 当文字长度超过控件宽度,截取文字,并添加省略号
            if (!TextUtils.isEmpty(text)) {
                float textWidth = paint.measureText(text);
                if (textWidth > width) {
                    int subIndex = paint.breakText(text, 0, text.length(), true, width, null);
                    this.text = text.substring(0, subIndex - 2) + "...";
                }
            }
            // 居中
            // drawX = (width - measureWidth) / 2;
            // 左侧对齐
            drawX = (int) pointPaint.measureText("0");
            FontMetrics metrics = paint.getFontMetrics();
            drawY = (int) (centerY + (metrics.bottom - metrics.top) / 2 - metrics.bottom);
        }

        public int getPosition() {
            return position;
        }

        public void draw(Canvas canvas) {
            canvas.drawText("•", pointDrawX, pointDrawY, pointPaint);
            canvas.drawText(text, drawX, drawY, paint);
        }

        @Override
        public String toString() {
            return "TextBlock{" + "width=" + width + ", height=" + height + ", text='" + text + '\'' + ", drawX=" + drawX + ", drawY=" + drawY + ", pointDrawX=" + pointDrawX + ", pointDrawY=" + pointDrawY + ", paint=" + paint + ", pointPaint=" + pointPaint + ", position=" + position + '}';
        }
    }

    private OnItemClickListener listener;

    public OnItemClickListener getOnItemClickListenerr() {
        return listener;
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    public interface OnItemClickListener {
        void onItemClick(int position);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值