Android(安卓)文本滚动效果的几种实现方式(二)
16lz
2021-01-25
这一篇文章介绍了通过自定义surfaceview方法来实现通知滚动效果。这个方法的好处就是可以不受主线程影响,大家应该都知道Android所有绘制界面操作都是只允许在主线程中,但是surfaceview可以在子线程中绘制。为了避免主线程绘制工作量大出现卡顿现象,所以有了用surfaceview来实现滚动的念头。
通过自定义surfaceview实现滚动效果
这个方法比较简单,就是自定义一个surfaceview,通过SurfaceHolder获取画布来通过子线程不断绘制文字。直接上代码。
public class PlayNotifyInnerWindow extends SurfaceView implements SurfaceHolder.Callback { /** * 初始化字体 */ public static Typeface addTypeface; public static Typeface berTypeface; public static Typeface daiTypeface; public static Typeface dejTypeface; public static Typeface droTypeface; SurfaceHolder holder; public PlayNotifyInnerWindow(Context context, int width, int height) { super(context); mContext = context; // TODO Auto-generated constructor stub rate = (((float) 1920) / ((float) 1080)) / (((float) height) / ((float) width)); this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); holder = getHolder(); holder.addCallback(this); // 设置Surface生命周期回调 } public void setPath(String path) { this.setVisibility(View.VISIBLE); paint = new Paint(); isStop = true; i = 0; currentScrollX = 0; if (timer != null) timer.cancel(); LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); try { filePath = path; manager = getContext().getAssets(); String fileContent = readFile(path);//读取本地配置文件,json格式 JSONObject object = new JSONObject(fileContent); content = object.getString("content") + " "; left = object.getString("left"); right = object.getString("right"); mspeed = object.getString("speed"); bottom = object.getString("bottom"); cicrle = object.getString("cicrle"); isTran = object.getBoolean("isTransparent"); stopTime = object.getInt("stoptime"); isB = object.getBoolean("isBold"); isI = object.getBoolean("isItalic"); isU = object.getBoolean("isUnderline"); bgColor = object.getInt("bgColor"); bgZiti = object.getInt("bgFont"); zihao = object.getString("fontsize"); ziti = object.getString("font"); effect = object.getInt("effect"); 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.bottomMargin = Integer.parseInt(bottom); } else { layoutParams.bottomMargin = 0; } msp = new SpannableString(content); if (isB == true) { paint.setFakeBoldText(true); } else { paint.setFakeBoldText(false); } if (isI == true) { paint.setTextSkewX(-0.5f); } else { paint.setTextSkewX(0f); } if (isU == true) { paint.setUnderlineText(true); } else { paint.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 (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 = px2sp(mContext, sp2px(mContext, Integer.parseInt(zihao)) * rate); paint.setTextSize(fontSize); } else { fontSize = px2sp(mContext, sp2px(mContext, 24) * rate); paint.setTextSize(fontSize); } if (!"".equals(ziti)) { Typeface tf; tf = choiceTypeface(ziti);// 根据路径得到Typeface paint.setTypeface(tf);// 设置字体 } else { msp.setSpan(new TypefaceSpan("monospace"), 0, content.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } FontEffects mFontEffects = new FontEffects(paint, null); mFontEffects.setFontEffects(effect); i = 0; this.setVisibility(View.VISIBLE); isStop = false; new Thread(new ScrollRunnable()).start(); this.setLayoutParams(layoutParams); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 开始滚动 public void startScroll() { Canvas c = null; while (!isStop) { currentScrollX += 10;// 滚动速度 synchronized (holder) { paint.setColor(bgZiti); c = holder.lockCanvas(); c.drawColor(bgColor); //重新绘制画布颜色,清空画布。 c.drawText(content, currentScrollX, 100, paint);//绘制文本,改变绘制位置 holder.unlockCanvasAndPost(c); } if (currentScrollX >= this.getWidth()) { currentScrollX = 0; // return; if (i >= cicle) { isStop = true; } else { i++; } } } } class ScrollRunnable implements Runnable { @Override public void run() { // TODO Auto-generated method stub startScroll(); } } public void stopScroll() { isStop = true; this.setVisibility(View.GONE); // scrollTo(0, 0); // File file = new File(filePath); // if (file.exists()) { // file.delete(); // } } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder arg0) { // TODO Auto-generated method stub setPath("/mnt/external_sd/notify/notify_android.xml"); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub }
更多相关文章
- android源码解析(十七)-->Activity布局加载流程
- Android(安卓)Hook Activity 的几种姿势
- 十分钟学会kotlin实现Android(安卓)MVP模式开发
- Android(安卓)Fragment学习笔记(二)----Fragment界面添加和管理
- 线程方法Android:异步调用详解
- Android查看数据库方法及工具
- [转]android解决apk编译方法数超过64k的问题
- Android(安卓)Handler 作用以及使用
- Android(安卓)四大组件 ————Service(生命周期)