Android 文本滚动效果的几种实现方式(一)

最近项目用到文本滚动通知效果,首先想到了跑马灯可是限制太多不适用,就自己写了两种实现方式,本篇来介绍第一种滚动方式。


1.通过scrollTo()方法来实现。

这个方法原理是,需要一个承载TextView的父控件,我这里用到得是一个自定义RelativeLayout,在里面添加一个TextView。通过父控件RelativeLayout的不断scrollTo()方法,来实现TextView滚动效果。
重写自定义RelativeLayout的onDraw方法,在onDraw调用scrollTo滑动效果会比较流畅,下面是代码。

    /**
     * 自定义RelativeLayout构造方法,把textview加入布局中
     * @param context
     * @param width
     * @param height
     */
    public PlayNotifyInnerWindow(Context context) {
        super(context);
        mContext = context;
        // TODO Auto-generated constructor stub
        this.setLayoutParams(newLayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT));//设置大小

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.paly_notiry_text, null);
        tv = (TextView) view.findViewById(R.id.tv_notif);
        this.addView(view);//添加文本
    }

下面是文本样式设置:

            if (!"".equals(left)) {
                // layoutParams.leftMargin=Integer.parseInt(left);
                layoutParams.setMargins(Integer.parseInt(left),0, 0, 0);//设置边距
            }
            if (!"".equals(right)) {
                layoutParams.setMargins(0, 0, Integer.parseInt(right), 0);//设置边距
            }

            if (!"".equals(left) && !"".equals(right)) {
                layoutParams.setMargins(Integer.parseInt(left), 0,//设置边距
                        Integer.parseInt(right), 0);
            }
            if (!"".equals(bottom)) {
                layoutParams.topMargin = Integer.parseInt(bottom);//设置边距
            } else {
                layoutParams.topMargin = 0;
            }
            msp = new SpannableString(content);
            if (isB == true) {//是否加粗

                tv.getPaint().setFakeBoldText(true);
            } else {
                tv.getPaint().setFakeBoldText(false);
            }

            if (isI == true) {//是否斜体
                tv.getPaint().setTextSkewX(-0.5f);
            } else {
                tv.getPaint().setTextSkewX(0f);
            }
            if (isU == true) {//是否有下划线
                tv.getPaint().setUnderlineText(true);
            } else {
                tv.getPaint().setUnderlineText(false);

            }
            //播放速度
            if (mspeed != null && !"".equals(mspeed)) {
                speed = Integer.parseInt(mspeed);
            } else {
                speed = 5;
            }
            //循环次数
            if (cicrle != null && !"".equals(cicrle)) {
                cicle = Integer.parseInt(cicrle);
            } else {
                cicle = 10000;
            }
            //背景颜色
            if (bgColor != 0 && isTran == false) {

                this.setBackgroundColor(bgColor);
            } else {
                this.setBackgroundColor(Color.TRANSPARENT);
            }
            if (bgZiti != 0) {
                // 设置字体前景色
                msp.setSpan(new ForegroundColorSpan(bgZiti), 0,
                        content.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 设置前景色为洋红色

            } else {
                msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 0,
                        content.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 正常

            }
            //字体大小
            if (!"".equals(zihao)) {
                fontSize = Util.px2sp(mContext,
                        Util.sp2px(mContext, Integer.parseInt(zihao)) * rate);
                tv.setTextSize(fontSize);
            } else {
                fontSize = Util
                        .px2sp(mContext, Util.sp2px(mContext, 24) * rate);
                tv.setTextSize(fontSize);
            }
            if (!"".equals(ziti)) {
                Typeface tf = Util.choiceTypeface(ziti);
                tv.setTypeface(tf);// 设置字体

            } else {
                msp.setSpan(new TypefaceSpan("monospace"), 0, content.length(),
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            //设置文本,可设置有样式文本
            tv.setText(msp);
            //自定义文字样式,立体,悬浮,碑刻,套色
            FontEffects mFontEffects = new FontEffects(tv, null);
            mFontEffects.setFontEffects(effect);
            i = 0;//循环次数标志位

            this.startScroll();//开始滚动
// 开始滚动
        public void startScroll() {
            this.setVisibility(View.VISIBLE);
            isStop = false;
            invalidate();//重新绘制(执行onDraw)
        }
@Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        if (!isStop) {
            currentScrollX -= speed;// 滚动速度
            scrollTo(currentScrollX, 0);
            if (getScrollX() <= -(this.getWidth())) {// 如果滚动位置大于控件宽度说明已经滚动出去
                currentScrollX = textWidth;// 初始化位置
                // return;
                if (i >= cicle - 1) {// 判断是否到达循环次数
                    // reach max times
                    stopScroll();
                    // return;
                } else {
                    i++;
                }
            }
            invalidate();
        }
    }

//停止滚动
public void stopScroll() {
        isStop = true;
        this.setVisibility(View.GONE);
        // scrollTo(0, 0);
    }

以上就是第一种方法的实现,这种方法单独滚动没有问题,但是我们这个项目有很多动画是自定义控件重写OnDraw所以会有动画冲突,出现卡顿现象。所以有了后面两种方法。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现多线程的几种方式有以下几种方法。首先,可以使用Java的Thread类来创建和管理线程。这种方式需要手动创建线程对象,并在run()方法编写线程的逻辑。其次,可以使用Java的Runnable接口来实现多线程。这种方式需要创建一个实现了Runnable接口的类,并将其作为参数传递给Thread类的构造函数。然后,可以使用Handler类来实现多线程。通过Handler的post()或postDelayed()方法,可以将任务添加到主线程的消息队列,从而在主线程执行异步操作。此外,还可以使用AsyncTask类来实现多线程。AsyncTask是Android提供的一个封装好的线程池,可以方便地在后台执行耗时操作,并在主线程更新UI。通过重写AsyncTask的doInBackground()方法来执行耗时操作,并通过onPostExecute()方法来更新UI。需要注意的是,AsyncTask必须在主线程创建实例,并且execute()方法也必须在主线程调用。另外,Android 3.0之后,可以使用executeOnExecutor()方法来实现并发执行多个AsyncTask任务。总结起来,Android实现多线程的几种方式包括使用Thread类、Runnable接口、Handler类和AsyncTask类。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [Android——多线程的多种实现方式](https://blog.csdn.net/abliudede/article/details/104891324)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Android开发四种常用的多线程实现方式](https://blog.csdn.net/star_nwe/article/details/130140238)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值