android垂直滚动显示,Android 上下滚动字幕实现

首先values文件夹下添加或创建attrs文件,如下:

1、自定义上下滚动字幕textview、VerticalRollingTextView

/**

* 作者:created by meixi

* 邮箱:13164716840@163.com

* 日期:2018/8/30 10

*/

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 = 5000;

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) {

try {

animationEnd();

}catch (Exception e) {

e.printStackTrace();

}

}

postInvalidate();

}

public void updateValue(float startValue, float endValue) {

this.startValue = startValue;

this.endValue = endValue;

}

}

}

2、layout.xml文件

3、activity调用自定义textview赋值

VerticalRollingTextView verticalRollingTextView = (VerticalRollingTextView)findViewById(R.id.myvtext);

TestEntity testEntity = new TestEntity();

testEntity.setHttps("baidu.com");

testEntity.setTitle("百度。com");

TestEntity testEntity1 = new TestEntity();

testEntity1.setTitle("谷歌。com");

testEntity1.setHttps("guge.com");

testEntities.add(testEntity);

testEntities.add(testEntity1);

verticalRollingTextView.setDataSetAdapter(new DataSetAdapter(testEntities) {

@Override

protected String text(TestEntity s) {

return s.getTitle();

}

});

verticalRollingTextView.run();

verticalRollingTextView.setOnItemClickListener(new VerticalRollingTextView.OnItemClickListener() {

@Override

public void onItemClick(VerticalRollingTextView view, int index) {//点击链接

String url = testEntities.get(index).getHttps();

Toast.makeText(MainActivity.this,url,Toast.LENGTH_LONG).show();

}

});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值