Android 跑马灯 文字滚动

来源:互联网 发布:手机必备实用软件 编辑:程序博客网 时间:2024/05/20 17:41

转载请注明出处
http://blog.csdn.net/u014513456/article/details/53726705
ruanjianjiagou@163.com

跑马灯有几种滚动方法
1.横向滚动 (从左至右)
2.横向滚动 (从右至左)
3.纵向滚动(从上到下)
4.纵向滚动(从下到上)
纵向滚动还涉及是否完全显示所有文字
1.横向滚动 (从左至右)

import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.os.Build;import android.util.AttributeSet;import android.widget.TextView;/** * Author:xuqiliang * Email:ruanjianjiagou@163.com * * @data:16/12/18 下午12:40 * @Description:${todo} */public class LeftToRightTextView extends TextView implements Runnable {    private int currentScrollX;// 当前滚动的位置    private boolean isStop = false;    private int textWidth;    private boolean isMeasure = false;    public LeftToRightTextView(Context context) {        super(context);    }    public LeftToRightTextView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public LeftToRightTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public LeftToRightTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (!isMeasure) {            getTextWidth();            isMeasure = true;        }    }    private void getTextWidth() {        Paint paint = this.getPaint();        String str = this.getText().toString();        textWidth = (int) paint.measureText(str);    }    @Override    public void setText(CharSequence text, BufferType type) {        super.setText(text, type);        this.isMeasure = false;    }    /**     * Starts executing the active part of the class' code. This method is     * called when a thread is started that has been created with a class which     * implements {@code Runnable}.     */    @Override    public void run() {        currentScrollX -= 2;// 滚动速度        scrollTo(currentScrollX, 0);        if (isStop) {            return;        }        if (getScrollX() <= -(this.getWidth())) {            scrollTo(textWidth, 0);            currentScrollX = textWidth;            // return;        }        postDelayed(this, 5);    }    /**     * 在Activity 或者Fragment OnResume 方法中调用     * mLeftToRightTextView.onStart();     * 开始滚动     */    public void onStart() {        isStop = false;        this.removeCallbacks(this);        post(this);    }    public void onStop() {        isStop = true;    }    /**     * 从0开始滚动     */    public void onStartZero() {        currentScrollX = 0;        onStart();    }}

2.横向滚动 (从右至左)

import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.os.Build;import android.util.AttributeSet;import android.widget.TextView;/** * Email:ruanjianjiagou@163.com * * @data:16/12/18 上午11:49 * @Description:${todo} */public class MarqueeTextView extends TextView implements Runnable {    private int currentScrollX;// 当前滚动的位置    private boolean isStop = false;    private float textWidth;    private boolean isMeasure = false;    public MarqueeTextView(Context context) {        super(context);    }    public MarqueeTextView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (!isMeasure) {            getTextWidth();            isMeasure = true;        }    }    public float getTextWidth() {        Paint paint = this.getPaint();        String mText = this.getText().toString();        textWidth = paint.measureText(mText);        return textWidth;    }    @Override    public void setText(CharSequence text, BufferType type) {        super.setText(text, type);        this.isMeasure = false;    }    /**     * Starts executing the active part of the class' code. This method is     * called when a thread is started that has been created with a class which     * implements {@code Runnable}.     */    @Override    public void run() {        currentScrollX += 1;        scrollTo(currentScrollX, 0);        if (isStop) {            return;        }        if (getScrollX() >= textWidth) {            scrollTo(-this.getWidth(), 0);            currentScrollX = -this.getWidth();        }        postDelayed(this, 10);    }    public void onStart() {        isStop = false;        this.removeCallbacks(this);        post(this);    }    public void onStop() {//        currentScrollX = 0;        isStop = true;    }    public void onStartZero() {        currentScrollX = 0;        onStart();    }}

使用方法

布局文件如下  <com.ruanjianjiagou.view.text.MarqueeText                    android:id="@+id/marquee_view"                    android:layout_width="0dp"                    android:layout_height="40dp"                    android:layout_weight="1"                    android:text="我是跑马灯"                    android:gravity="center_vertical"             android:textColor="@color/new_orange_color"             android:textSize="@dimen/font_size_13">   </com.ruanjianjiagou.view.text.MarqueeText>   com.ruanjianjiagou.view.text 为类所在的包名称。   以上控件可以放在任何容器布局中
Activity或fragment中 使用如下
private MarqueeTextView marquee_view;  //声明全局变量marquee_view = (MarqueeText)mRootView.findViewById(R.id.marquee_view);marquee_view.setText("")//此处可以是任何时候取到数据了放入的要滚动的字符串   @Override    public void onResume() {        marquee_view.onStart(); //启动跑马灯     }    @Override    public void onPause() {        super.onPause();        marquee_view.onStop();    }

3&4 垂直跑马灯

package com.viclee.verticalswitchtextview;import android.animation.Animator;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.text.TextUtils;import android.util.AttributeSet;import android.view.View;import android.widget.TextView;import java.util.ArrayList;import java.util.List;public class VerticalSwitchTextView extends TextView implements View.OnClickListener {    private static final int DEFAULT_SWITCH_DURATION = 500;    private static final int DEFAULT_IDLE_DURATION = 2000;    public static final int TEXT_ALIGN_CENTER = 0;    public static final int TEXT_ALIGN_LEFT = 1;    public static final int TEXT_ALIGN_RIGHT = 2;    private Context mContext;    private List<String> lists;//会循环显示的文本内容    private List<String> ellipsisLists;    private int contentSize;    private String outStr;//当前滑出的文本内容    private String inStr;//当前滑入的文本内容    private float textBaseY;//文本显示的baseline    private int currentIndex = 0;//当前显示到第几个文本    private String ellipsis;    private float ellipsisLen = 0;    private int switchDuaration = DEFAULT_SWITCH_DURATION;//切换时间    private int idleDuaration = DEFAULT_IDLE_DURATION;//间隔时间    private int switchOrientation = 0;    private int alignment = TEXT_ALIGN_CENTER;    /**     * 文本中轴线X坐标     */    private float inTextCenterX;    private float outTextCenterX;    private float currentAnimatedValue = 0.0f;    private ValueAnimator animator;    private TextUtils.TruncateAt mEllipsize;    private int verticalOffset = 0;    private int mWidth;    private int mHeight;    private int paddingLeft = 0;    private int paddingBottom = 0;    private int paddingTop = 0;    private int paddingRight = 0;    private Paint mPaint;    //回调接口,用来通知调用者控件当前的状态    public VerticalSwitchTextViewCbInterface cbInterface;    public VerticalSwitchTextView(Context context) {        this(context, null);    }    public VerticalSwitchTextView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public VerticalSwitchTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.VerticalSwitchTextView);        try {            switchDuaration = array.getInt(R.styleable.VerticalSwitchTextView_switchDuaration, DEFAULT_SWITCH_DURATION);            idleDuaration = array.getInt(R.styleable.VerticalSwitchTextView_idleDuaration, DEFAULT_IDLE_DURATION);            switchOrientation = array.getInt(R.styleable.VerticalSwitchTextView_switchOrientation, 0);            alignment = array.getInt(R.styleable.VerticalSwitchTextView_alignment, TEXT_ALIGN_CENTER);        } finally {            array.recycle();        }        init();    }    private void init() {        setOnClickListener(this);        mPaint = getPaint();        mPaint.setTextAlign(Paint.Align.CENTER);        ellipsis = getContext().getString(R.string.ellipsis);        ellipsisLen = mPaint.measureText(ellipsis);        mEllipsize = getEllipsize();        animator = ValueAnimator.ofFloat(0f, 1f).setDuration(switchDuaration);        animator.setStartDelay(idleDuaration);        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                currentAnimatedValue = (float) animation.getAnimatedValue();                if (currentAnimatedValue < 1.0f) {                    invalidate();                }            }        });        animator.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animation) {            }            @Override            public void onAnimationEnd(Animator animation) {                currentIndex = (++currentIndex) % contentSize;                if (cbInterface != null) {                    cbInterface.showNext(currentIndex);                }                outStr = lists.get(currentIndex);                inStr = lists.get((currentIndex + 1) % contentSize);                animator.setStartDelay(idleDuaration);                animator.start();            }            @Override            public void onAnimationCancel(Animator animation) {            }            @Override            public void onAnimationRepeat(Animator animation) {            }        });    }    /**     * 设置循环显示的文本内容     *     * @param content 内容list     */    public void setTextContent(List<String> content) {        lists = content;//        lists.clear();//        lists = new ArrayList<>();//        lists.add("1适当放松放松放松点水电费水电费史蒂夫水电费水电费");//        lists.add("2适当放松放松放松点水电费水电费史蒂夫水电费水电费");//        lists.add("3适当放松放");//        lists.add("3适当放松放1111222333");        if (lists == null || lists.size() == 0) {            return;        }        contentSize = lists.size();        if (contentSize > 0) {            animator.start();        }    }    private void generateEllipsisText() {        if (ellipsisLists != null) {//防止重复计算            return;        }        ellipsisLists = new ArrayList<>();        if (lists != null && lists.size() != 0) {            for (String item : lists) {                int avail = mWidth - paddingLeft - paddingRight;                float remaining = avail - ellipsisLen;                if (avail <= 0) {                    ellipsisLists.add("");                } else {                    float itemWidth = mPaint.measureText(item, 0, item.length());                    if (itemWidth < avail) {                        ellipsisLists.add(item);                    } else if (remaining <= 0) {                        ellipsisLists.add(ellipsis);                    } else {                        int len = item.length();                        float[] widths = new float[len];                        mPaint.getTextWidths(item, 0, item.length(), widths);                        if (mEllipsize == TextUtils.TruncateAt.END) {                            float blockWidth = 0f;                            for (int i = 0; i < len; i++) {                                blockWidth += widths[i];                                if (blockWidth > remaining) {                                    ellipsisLists.add(item.substring(0, i) + ellipsis);                                    break;                                }                            }                        } else if (mEllipsize == TextUtils.TruncateAt.START) {                            float blockWidth = 0f;                            for (int i = len - 1; i >= 0; i--) {                                blockWidth += widths[i];                                if (blockWidth > remaining) {                                    ellipsisLists.add(ellipsis + item.substring(i, len - 1));                                    break;                                }                            }                        } else if (mEllipsize == TextUtils.TruncateAt.MIDDLE) {                            float blockWidth = 0f;                            for (int i = 0, j = len - 1; i < j; i++, j--) {                                blockWidth += (widths[i] + widths[j]);                                if (blockWidth > remaining) {                                    if (blockWidth - widths[j] < remaining) {                                        ellipsisLists.add(item.substring(0, i + 1) + ellipsis + item.substring(j, len - 1));                                    } else {                                        ellipsisLists.add(item.substring(0, i) + ellipsis + item.substring(j, len - 1));                                    }                                    break;                                }                            }                        }                    }                }            }        }        lists = ellipsisLists;    }    /**     * 主要用来调整TextView的高度     *     * @param widthMeasureSpec     * @param heightMeasureSpec     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        mWidth = MeasureSpec.getSize(widthMeasureSpec);        Rect bounds = new Rect();        if (contentSize <= 0) {            return;        }        String text = lists.get(0);        mPaint.getTextBounds(text, 0, text.length(), bounds);        int textHeight = bounds.height();        paddingLeft = getPaddingLeft();        paddingRight = getPaddingRight();        paddingBottom = getPaddingBottom();        paddingTop = getPaddingTop();        if (mEllipsize != null) {            generateEllipsisText();        }        outStr = lists.get(0);        if (contentSize > 1) {            inStr = lists.get(1);        } else {            inStr = lists.get(0);        }        mHeight = textHeight + paddingBottom + paddingTop;        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();        //计算文字高度        float fontHeight = fontMetrics.bottom - fontMetrics.top;        //计算文字的baseline        textBaseY = mHeight - (mHeight - fontHeight) / 2 - fontMetrics.bottom;        setMeasuredDimension(mWidth, mHeight);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (contentSize <= 0) {            return;        }        //计算绘制的文字中心位置        switch (alignment) {            case TEXT_ALIGN_CENTER:                inTextCenterX = outTextCenterX = (mWidth - paddingLeft - paddingRight) / 2 + paddingLeft;                break;            case TEXT_ALIGN_LEFT:                inTextCenterX = paddingLeft + mPaint.measureText(inStr) / 2;                outTextCenterX = paddingLeft + mPaint.measureText(outStr) / 2;                break;            case TEXT_ALIGN_RIGHT:                inTextCenterX = mWidth - paddingRight - mPaint.measureText(inStr) / 2;                outTextCenterX = mWidth - paddingRight - mPaint.measureText(outStr) / 2;                break;        }        //直接使用mHeight控制文本绘制,会因为text的baseline的问题不能居中显示        verticalOffset = Math.round(2 * textBaseY * (0.5f - currentAnimatedValue));//        L.d("verticalOffset is " + verticalOffset);        if (switchOrientation == 0) {//向上滚动切换            if (verticalOffset > 0) {                canvas.drawText(outStr, outTextCenterX, verticalOffset, mPaint);            } else {                canvas.drawText(inStr, inTextCenterX, 2 * textBaseY + verticalOffset, mPaint);            }        } else {            if (verticalOffset > 0) {//向下滚动切换                canvas.drawText(outStr, outTextCenterX, 2 * textBaseY - verticalOffset, mPaint);            } else {                canvas.drawText(inStr, inTextCenterX, -verticalOffset, mPaint);            }        }    }    @Override    public void onClick(View v) {        if (contentSize > currentIndex) {            if (cbInterface != null) {                cbInterface.onItemClick(currentIndex);            }        }    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        mContext = null;        if (animator != null) {            animator.cancel();        }    }    //回调接口,用来通知调用者控件当前的状态,index表示开始显示哪一个文本内容    public interface VerticalSwitchTextViewCbInterface {        void showNext(int index);        void onItemClick(int index);    }    public void setCbInterface(VerticalSwitchTextViewCbInterface cb) {        cbInterface = cb;    }}

垂直跑马灯部分转自

http://blog.csdn.net/goodlixueyong/article/details/50785032

0 0
原创粉丝点击