上下滚动文字自定义控件

来源:互联网 发布:龟头增大知乎 编辑:程序博客网 时间:2024/05/21 12:39

创建自定义控件VerticalRollingTextView

public class VerticalRollingTextView extends View {    DataSetAdapter mDataSetAdapter;    private final Paint mPaint;    private int mCurrentIndex;    private int mNextIndex;    Rect bounds = new Rect();    private float mCurrentOffsetY;    private float mOrgOffsetY = -1;    private final float mTextTopToAscentOffset;    private float mOffset;    private InternalAnimation mAnimation = new InternalAnimation();    /*防止动画结束的回调触发以后动画继续进行出现的错乱问题*/    private boolean mAnimationEnded;    private boolean isRunning;    /*动画时间*/    private int mDuration = 1000;    /*动画间隔*/    private int mAnimInterval = 2000;    public VerticalRollingTextView(Context context, AttributeSet attrs) {        super(context, attrs);        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setColor(Color.BLACK);        mPaint.setTypeface(Typeface.DEFAULT);        parseAttrs(context, attrs);        Paint.FontMetricsInt metricsInt = mPaint.getFontMetricsInt();        mTextTopToAscentOffset = metricsInt.ascent - metricsInt.top;        mAnimation.setDuration(mDuration);    }    private void parseAttrs(Context context, AttributeSet attrs) {        float density = getResources().getDisplayMetrics().density;        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerticalRollingTextView);        mPaint.setColor(typedArray.getColor(R.styleable.VerticalRollingTextView_android_textColor, Color.BLACK));        mPaint.setTextSize(typedArray.getDimensionPixelOffset(R.styleable.VerticalRollingTextView_android_textSize, (int) (density * 14)));        mDuration = typedArray.getInt(R.styleable.VerticalRollingTextView_android_duration, mDuration);        mAnimInterval = typedArray.getInt(R.styleable.VerticalRollingTextView_animInterval, mAnimInterval);        typedArray.recycle();    }    @Override    protected void onDraw(Canvas canvas) {        // 绘制文本        if (mDataSetAdapter == null || mDataSetAdapter.isEmpty()) {            return;        }        String text1 = mDataSetAdapter.getText(mCurrentIndex);        String text2 = mDataSetAdapter.getText(mNextIndex);        //只需要进行一次测量        if (mOrgOffsetY == -1) {            mPaint.getTextBounds(text1, 0, text1.length(), bounds);            mOffset = (getHeight() + bounds.height()) * 0.5f;            mOrgOffsetY = mCurrentOffsetY = mOffset - mTextTopToAscentOffset;            mAnimation.updateValue(mOrgOffsetY, -2 * mTextTopToAscentOffset);        }        canvas.drawText(text1, 0, mCurrentOffsetY, mPaint);        canvas.drawText(text2, 0, mCurrentOffsetY + mOffset + mTextTopToAscentOffset, mPaint);    }    public void setDataSetAdapter(DataSetAdapter dataSetAdapter) {        mDataSetAdapter = dataSetAdapter;        confirmNextIndex();        invalidate();    }    /**     * 开始转动,界面可见的时候调用     */    public void run() {        if (isRunning) {            return;        }        isRunning = true;        mAnimation.updateValue(mCurrentOffsetY, -2 * mTextTopToAscentOffset);        post(mRollingTask);    }    /**     * @return true代表正在转动     */    public boolean isRunning() {        return isRunning;    }    /**     * 停止转动,界面不可见的时候调用     */    public void stop() {        isRunning = false;        removeCallbacks(mRollingTask);    }    Runnable mRollingTask = new Runnable() {        @Override        public void run() {            mAnimationEnded = false;            startAnimation(mAnimation);            postDelayed(this, mAnimInterval);        }    };    public void animationEnd() {        //1.角标+1        mCurrentIndex++;        //2.计算出正确的角标        mCurrentIndex = mCurrentIndex < mDataSetAdapter.getItemCount() ? mCurrentIndex : mCurrentIndex % mDataSetAdapter.getItemCount();        //3.计算下一个待显示文字角标        confirmNextIndex();        //3.位置复位        mCurrentOffsetY = mOrgOffsetY;        mAnimationEnded = true;    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        removeCallbacks(mRollingTask);        if (isRunning()) {            mAnimation.cancel();        }    }    /**     * 计算第二个角标     */    private void confirmNextIndex() {        //3.计算第二个角标        mNextIndex = mCurrentIndex + 1;        //4.计算出正确的第二个角标        mNextIndex = mNextIndex < mDataSetAdapter.getItemCount() ? mNextIndex : 0;    }    /**     * float估值器     *     * @param fraction     * @param startValue     * @param endValue     * @return     */    float evaluate(float fraction, float startValue, float endValue) {        return startValue + fraction * (endValue - startValue);    }    @Override    public void setOnClickListener(OnClickListener l) {    }    public void setOnItemClickListener(final OnItemClickListener onItemClickListener) {        super.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                onItemClickListener.onItemClick(VerticalRollingTextView.this, mCurrentIndex);            }        });    }    public interface OnItemClickListener {        void onItemClick(VerticalRollingTextView view, int index);    }    class InternalAnimation extends Animation {        float startValue;        float endValue;        @Override        protected void applyTransformation(float interpolatedTime, Transformation t) {            if (mAnimationEnded) return;            mCurrentOffsetY = evaluate(interpolatedTime, startValue, endValue);            if (mCurrentOffsetY == endValue) {                animationEnd();            }            postInvalidate();        }        public void updateValue(float startValue, float endValue) {            this.startValue = startValue;            this.endValue = endValue;        }    }}

然后在values文件夹下创建attrs,自定义属性

<resources>    <declare-styleable name="VerticalRollingTextView">        <!--文字颜色-->        <attr name="android:textColor"/>        <!--文字大小-->        <attr name="android:textSize"/>        <!--滚动动画时长-->        <attr name="android:duration"/>        <!--两次动画之间的间隔-->        <attr name="animInterval" format="integer"/>    </declare-styleable></resources>

最后在布局中调用

            <com.bawei.redchild.view.VerticalRollingTextView                    android:id="@+id/home_rolling_tv"                    android:layout_height="40dp"                    android:layout_width="match_parent"                    android:layout_alignParentLeft="true"                    myattrs:animInterval="3000"                    android:layout_marginLeft="75dp"                    android:layout_marginTop="8dp"                    android:textSize="18sp"                />                <!-- animInterval 滚动间隔时间 -->

在代码中获取控件,并给控件设置数据

mVerticalRollingView.setDataSetAdapter(new DataSetAdapter<String>(Arrays.asList(mStrs)) {            @Override            protected String text(String s) {                return s;            }        });

可以设置点击监听

        mVerticalRollingView.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onItemClick(VerticalRollingTextView view, int index) {                Toast.makeText(MainActivity.this, mStrs[index], Toast.LENGTH_SHORT).show();            }        });

最后开始,或者停止这个滚动字幕

        if (mVerticalRollingView.isRunning()) {            //停止滚动            mVerticalRollingView.stop();            button.setText("滚动");        } else {            //开始滚动            mVerticalRollingView.run();            button.setText("停止");        }
0 0
原创粉丝点击