Android 上下滚动字幕实现

这篇文章详细介绍了如何在Android中创建一个自定义的VerticalRollingTextView组件,该组件实现了文本的垂直滚动效果,通过DataSetAdapter管理数据并控制滚动过程。作者强调了代码中的关键部分和优化技巧,以及开发高质量应用的重要性。
摘要由CSDN通过智能技术生成
  • 作者: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

小结

有了这么多优秀的开发工具,可以做出更高质量的Android应用。

当然了,“打铁还需自身硬”,想要写出优秀的代码,最重要的一点还是自身的技术水平,不然用再好的工具也不能发挥出它的全部实力。

在这里我也分享一份大佬自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现上下滚动的文字效果,我们可以使用TextView和动画来实现。下面是一种简单的实现方法: 1. 首先,在布局文件中添加一个TextView来显示滚动的文字: ```xml <TextView android:id="@+id/scrolling_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:marqueeRepeatLimit="marquee_forever" android:scrollHorizontally="true" android:text="这是要滚动的文字" android:textSize="20sp" /> ``` 2. 然后,在Java代码中找到这个TextView,并添加滚动动画: ```java TextView scrollingText = findViewById(R.id.scrolling_text); scrollingText.setSelected(true); // 设置文字可以滚动 // 创建一个动画对象,设置动画属性 TranslateAnimation animation = new TranslateAnimation(0, 0, 0, -300); // 设置垂直方向上的移动距离 animation.setDuration(3000); // 设置动画持续时间 animation.setRepeatCount(Animation.INFINITE); // 设置动画重复次数 // 将动画应用到TextView上 scrollingText.startAnimation(animation); ``` 在上面的代码中,我们首先通过findViewById()方法找到TextView,然后设置它可以滚动。接着创建一个TranslateAnimation对象,设置动画属性,比如垂直方向上的移动距离和动画持续时间。最后将动画应用到TextView上,调用startAnimation()方法开始滚动。 这样,当我们运行应用时,TextView中的文字就会以上下滚动的方式展示出来。可以根据需求调整布局和动画的属性来适应自己的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值