用SurfaceView实现级联分层图(粗略篇)
来源:互联网 发布:淘宝装修教程 编辑:程序博客网 时间:2024/06/06 03:08
先看效果图
实际运行很流畅,运行内存1M左右
最近脑抽,想实现一个亲戚关系图谱的应用,但始终没有找到合适的开源控件,于是就看到一篇《利用递归算法和堆栈实现android思维导图大纲图的动态绘制》实现类似效果的文章,并附上效果图
于是就想,想这种的自定义控件貌似在线上很少可看到(我自己是没有看到过)
那么在Android端实现起来,需要怎么写
经过一番思考
1.继承ViewGroup来写?然后线怎么绘制。。
2.线的绘制需要Canvas,用到画布画笔
3.有了画布画笔,线的绘制需要开始xy,结束xy
4.绘制是动态的,ViewGroup的话需要用到异步来绘制
5.Canvas异步绘制?那绘制时的数据怎么保证同步
6.于是有了这些条件:异步绘制,数据同步,用到画布,那不就是SurfaceView的宿命吗
不了解SurfaceView的同学请补一下SurfaceView的基础用法
有了这些基础和条件之后,就开始写代码了
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { public LoopThread loopThread; public static final int START_X = 150; public static final int START_Y = 500; public MySurfaceView(Context context) { super(context); SurfaceHolder holder = getHolder(); holder.addCallback(this); loopThread = new LoopThread(holder, context); } public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); } public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void surfaceCreated(SurfaceHolder holder) { loopThread.isRunning = true; loopThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { loopThread.isRunning = false; try { loopThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } public class LoopThread extends Thread { final SurfaceHolder holder; Context context; Paint paint; //是否停止绘制 boolean isRunning = false; float radius = 10f, radius2 = 10f, length = 10f, height = 10f, secondLength = 10f; float maxRadius = 120, maxRadius2 = 90, maxLength = 150, maxHeight = maxRadius * 2; LoopThread(SurfaceHolder holder, Context context) { this.holder = holder; this.context = context; paint = new Paint(); paint.setColor(Color.GREEN); paint.setStyle(Paint.Style.FILL); } @Override public void run() { Canvas c = null; while (isRunning) { try { synchronized (holder) { c = holder.lockCanvas(null); draw(c);// Thread.sleep(100); } } finally { holder.unlockCanvasAndPost(c); } } } private void draw(Canvas canvas) { //clear screen canvas.drawColor(Color.WHITE); if (radius <= maxRadius) {//画第一个圆 canvas.translate(START_X, START_Y); canvas.drawCircle(0, 0, radius += 10, paint); Paint paint1 = new Paint(); paint1.setColor(Color.RED); paint1.setStyle(Paint.Style.FILL); paint1.setTypeface(Typeface.DEFAULT_BOLD); paint1.setTextSize(radius > maxRadius / 2 ? maxRadius / 2 : radius); canvas.drawText("hello", radius > maxRadius / 2 ? -maxRadius / 2 : -radius, radius > maxRadius / 2 ? maxRadius / 5 : radius, paint1); } else if (radius > maxRadius && length < maxLength) {//画横 canvas.translate(START_X, START_Y); canvas.drawCircle(0, 0, maxRadius, paint); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(maxRadius / 2); canvas.drawText("hello", -maxRadius / 2, maxRadius / 5, paint); canvas.translate(radius, 0); Paint paint1 = new Paint(); paint1.setColor(Color.BLUE); paint1.setStyle(Paint.Style.FILL); paint1.setStrokeWidth(5f); canvas.drawLine(0, 0, length += 30, 0, paint1); } else if (height <= maxHeight) {//画竖线 canvas.translate(START_X, START_Y); canvas.drawCircle(0, 0, radius, paint); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(maxRadius / 2); canvas.drawText("hello", -maxRadius / 2, maxRadius / 5, paint); canvas.translate(radius, 0); Paint paint1 = new Paint(); paint1.setColor(Color.BLUE); paint1.setStyle(Paint.Style.FILL); paint1.setStrokeWidth(5f); canvas.drawLine(0, 0, length, 0, paint1); canvas.translate(length, 0); canvas.drawLine(0, -height / 2, 0, height += 50, paint1); } else if (secondLength <= maxLength) {//画3横 canvas.translate(START_X, START_Y); canvas.drawCircle(0, 0, radius, paint); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(maxRadius / 2); canvas.drawText("hello", -maxRadius / 2, maxRadius / 5, paint); canvas.translate(radius, 0); Paint paint1 = new Paint(); paint1.setColor(Color.BLUE); paint1.setStyle(Paint.Style.FILL); paint1.setStrokeWidth(5f); canvas.drawLine(0, 0, length, 0, paint1); canvas.translate(length, 0); canvas.drawLine(0, -(START_Y + height) / 2, 0, (START_Y + height) / 2, paint1); canvas.translate(0, -(START_Y + height) / 2); canvas.drawLine(0, 0, secondLength += 30, 0, paint1); canvas.translate(0, (START_Y + height) / 2); canvas.drawLine(0, 0, secondLength, 0, paint1); canvas.translate(0, (START_Y + height) / 2); canvas.drawLine(0, 0, secondLength, 0, paint1); } else {//画3圆 canvas.translate(START_X, START_Y); canvas.drawCircle(0, 0, radius, paint); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(maxRadius / 2); canvas.drawText("hello", -maxRadius / 2, maxRadius / 5, paint); canvas.translate(radius, 0); Paint paint1 = new Paint(); paint1.setColor(Color.BLUE); paint1.setStyle(Paint.Style.FILL); paint1.setStrokeWidth(5f); canvas.drawLine(0, 0, length, 0, paint1); canvas.translate(length, 0); canvas.drawLine(0, -(START_Y + height) / 2, 0, (START_Y + height) / 2, paint1); canvas.translate(0, -(START_Y + height) / 2); canvas.drawLine(0, 0, secondLength, 0, paint1); canvas.translate(0, (START_Y + height) / 2); canvas.drawLine(0, 0, secondLength, 0, paint1); canvas.translate(0, (START_Y + height) / 2); canvas.drawLine(0, 0, secondLength, 0, paint1); //第二层第1个圆 canvas.translate(radius2 + secondLength, -(START_Y + height)); canvas.drawCircle(0, 0, radius2 += 30, this.paint); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(radius2 > maxRadius2 / 2 ? maxRadius2 / 2 : radius2); canvas.drawText("haha", radius2 > maxRadius2 / 2 ? -maxRadius2 / 2 : -radius2, maxRadius2/5, paint); //第二层第2个圆 canvas.translate(0, (START_Y + height) / 2); canvas.drawCircle(0, 0, radius2, this.paint); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(radius2 > maxRadius2 / 2 ? maxRadius2 / 2 : radius2); canvas.drawText("haha", radius2 > maxRadius2 / 2 ? -maxRadius2 / 2 : -radius2, maxRadius2/5, paint); //第二层第3个圆 canvas.translate(0, (START_Y + height) / 2); RectF rectF = new RectF(); rectF.left = -maxRadius2; rectF.right = maxRadius2; rectF.top = -maxRadius2; rectF.bottom = maxRadius2; canvas.drawRoundRect(rectF, 10, 10, this.paint); paint.setStyle(Paint.Style.FILL); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setTextSize(radius2 > maxRadius2 / 2 ? maxRadius2 / 2 : radius2); canvas.drawText("haha", radius2 > maxRadius2 / 2 ? -maxRadius2 / 2 : -radius2, maxRadius2/5, paint); if (radius2 > 90) { isRunning = false; } } } }}
代码都是很基本的绘制,没有什么特别的
目前该控件的缺点很多很多,以后有可能拓展的方向:可拖拽缩放大小 、动态绘制分级并画线、添加控件的点击事件
1 0
- 用SurfaceView实现级联分层图(粗略篇)
- Android实现无序树形结构图,类似思维导图和级联分层图(无序,随机位置)
- zab粗略实现
- 实现pi粗略计算
- 智能指针粗略实现
- jquery用ajax实现级联
- 用js实现级联显示
- 用触发器来实现级联更新级联删除
- 粗略实现以下string 类
- C++ Prefix Tree 粗略实现
- TCP/IP粗略图
- 用SurfaceView实现Android游戏摇杆
- 用SurfaceView实现写字板的效果
- 用SurfaceView实现Android游戏摇杆
- Android实时取景:用SurfaceView实现 -- Camera
- 用jquery实现网页分块,分层,筛选
- 用分层思想实现程序结构优化
- Android提高第二篇之SurfaceView(上) --用SurfaceView画图
- Linux中硬盘物理扇区 与文件系统文件对应关系
- 插入排序
- 设置电脑每天几点自动关机 windows10系统
- Protel99SE SP6 绿色精简版7.5M
- unity 杂记
- 用SurfaceView实现级联分层图(粗略篇)
- Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
- 【新手建站三部曲之一】——一块钱搭建自己的服务器(LAMP)
- 数据结构之大小堆&&优先级队列
- IOS UICollectionView使用
- 二叉树的递归遍历
- Android 通过ViewPager实现点击和滑动切换Fragment标签页
- 开发者的Facebook | GitHub投资人寻求退出?Microsoft意图收购?
- Git部分命令介绍