![](https://img-blog.csdnimg.cn/20201014180756919.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
自定义控件
PYJTLK
这个作者很懒,什么都没留下…
展开
-
Android思维导图布局:效果展示及使用方法
思维导图布局的前身是树形布局,对树形布局基本使用还不太了解的朋友可以先看看我写的树形布局系列教程,了解了树形布局的使用方法后再来阅读本文章。先睹为快来看看效果吧,横向效果如下:纵向效果如下:(布局可拖拽,后面会讲解)基本使用为了方便讲解,下面来实现如下的效果,先写布局代码。注意下面的代码,MindMapLayout是思维导图布局,TreeLayout是树形布局。一定要按照如下的方式摆放,否则会报错。左树 + 根 + 右树 或者 上树 + 根 + 下树app:orientati原创 2020-07-07 18:10:12 · 919 阅读 · 4 评论 -
自定义布局之树形布局(十):遍历监听器
上一篇讲解了如何通过装饰模式和简单工厂模式来优化拓展树形布局。本篇讲解如何给树形布局添加遍历监听器。说到遍历树这种数据结构,最常见的就是深度优先遍历(dfs)和广度优先遍历(bfs)。我们可以给树形布局添加一个遍历监听器,在布局遍历子控件的时候做一些事情。定义遍历监听器为了能在遍历每个结点的时候做我们想做的事情,需要定义一个监听器来回调访问结点时的方法,代码如下: /** * 遍历监听器 */ public interface SearchListener{原创 2020-07-03 13:44:20 · 213 阅读 · 0 评论 -
自定义布局之树形布局(九):策略模式+装饰模式+工厂方法模式
上一篇讲述如何优化Padding使其在树形布局内部拖拽时也能生效。本篇讲解如何通过两种设计模式来极大地增加布局的拓展性。前期准备在真正开始之前我们首先要熟悉两种设计模式。1.装饰模式装饰模式是一种结构型设计模式,这种设计模式可以动态地拓展原有对象的功能,代替类的继承。下面举个例子。//车辆类,抽象类abstract class Vehicle{ abstract void run();}//汽车类class Car extends Vehicle{ @Override void r原创 2020-07-02 23:54:37 · 597 阅读 · 0 评论 -
自定义布局之树形布局(八):优化支持Padding
上一篇从树的分支这个角度对代码进行了拓展优化,使其能够支持n叉树有效性的检查。本篇来讲解如何更好地支持树形布局的Padding。View是不支持Padding的,而ViewGroup是支持Padding的。在给属性布局添加Padding参数时“意外地”发现了一个Bug。可以看到继承自ViewGroup的树形布局本身是可以让子控件支持Padding的,但是绘制的连接线却不支持Padding。这是因为在绘制连接线的时候并没有把Padding考虑进去。这里首先需要了解三个关键的方法,save,restor原创 2020-07-01 00:48:22 · 265 阅读 · 0 评论 -
自定义布局之树形布局(七):分支数限制
上一篇讲解了树形布局拖拽效果的实现,到上一篇为止树形布局的功能就基本实现了。本篇从树的分支这个角度来对树形布局的代码进行优化。思路解析以三叉树为例,三叉树所有结点的分支数都在0~3这个范围内。某结点有三个分支,如果再插入一个子结点就破坏了三叉树的定义。在树形布局里,我们也可以给它添加这样的检查机制,使之成为严格的n叉树,在运行的时候如果破坏了这种分支数限制就抛出异常,这样就可以让开发者严格遵守n叉树的规则了。基本实现首先先定义分支数属性。<resources> <dec原创 2020-06-30 22:11:22 · 568 阅读 · 0 评论 -
自定义布局之树形布局(六):事件拦截与拖拽效果
上一篇讲解了树形布局绘制结点连接线的相关内容。本文来讲解布局的事件拦截及拖拽效果的实现。思路分析布局拖拽会产生一系列屏幕触摸事件。那问题来了,要是树形布局里有对滑动事件敏感的子控件(如ScrollView),这一系列事件该由谁处理呢?其实思路很简单,我们给TreeLayout定义一个锁定标记。树形布局被锁定时,滑动事件交给子控件处理,而树形布局解锁时,它把拦截滑动事件拦截下来自己处理。下面来看看是怎么实现的。重写onInterceptTouchEvent方法这个方法只有布局类控件才有,它是用来拦截原创 2020-06-30 16:14:49 · 265 阅读 · 0 评论 -
自定义布局之树形布局(五):绘制结点连接线
上一篇以从左到右方向为例讲解了树形布局中子控件的摆放,本篇讲解结点间连接线的绘制。前期准备一般情况下布局类控件其实更关注于子控件的测量和摆放(例如LinearLayout和RelativeLayout),而在绘制上做相对较少的事情,因为它们本身其实没有太多需要花的东西,这里不妨深入ViewGroup的draw方法看看它到底绘制了什么。其实ViewGroup并没有重写draw方法,而是直接沿用View的draw方法。public void draw(Canvas canvas) { .原创 2020-06-30 13:59:52 · 840 阅读 · 0 评论 -
自定义布局之树形布局(四):子控件摆放
上一篇以水平方向为例讲解了树形布局的宽高测量,本篇讲解子控件的摆放。水平树的摆放原理和竖直方向的摆放原理是一样的,这里就继续顺着水平树的思路进行。重写onLayout方法不同于一般的自定义控件,布局类控件除了考虑自身的情况,还得考虑到各个子控件。onMeasure方法只是完成了尺寸大小的测量工作,布局控件还得运行onLayout方法把各个子控件摆放到指定的位置上去。水平方向摆放方式有两种:从右到左和从左到右,这里以从左到右为例来讲解。根结点摆放的方式:竖直方向居中(黄色方框高度的一半),水平方向居原创 2020-06-30 10:50:49 · 487 阅读 · 0 评论 -
自定义布局之树形布局(三):测量宽高
上一篇讲了总体的思路及自定义属性的声明,本篇讲解树形布局的宽高测量。前面讲到树形布局分为水平方向和竖直方向(类似于LinearLayout),这里以水平方向为例来讲解。总体思路红色是根结点,绿色是子结点,其中子结点是竖直方向线性摆放的。而蓝色就是整个TreeLayout的宽高范围。如此一来,TreeLayout的宽度如下:(根结点的宽度 + 根结点的水平方向Margin) + (层级间隔LevelInterval) + (最宽子结点的宽度 + 它的水平方向Margin)TreeLayout的高度分原创 2020-06-30 00:01:41 · 303 阅读 · 0 评论 -
自定义布局之树形布局(二):总体思路及自定义属性
上一篇展示了树形布局的效果及使用方法,本篇讲解设计这个树形布局的总体思路及它的自定义属性。总体思路1.递归(作为一个程序员)提到树,相信大家第一时间想到的是数据结构里的各种树(二叉树,哈夫曼树、红黑树等)。树这种数据结构有很强的递归性,遍历树、查询高度等等操作其实都可以递归的方式来实现。简言之就是树—>树的子树—>子树的子树…利用这种递归的思想,在设计树形布局时我们就可以不必总是担心整棵树的各种变量。关心局部,做好局部就行了(有点像贪心算法)。本树形布局其实很简单,1号为根结点,2、3原创 2020-06-29 22:42:06 · 619 阅读 · 1 评论 -
自定义布局之树形布局(一):效果展示及使用方法
先来展示一下效果吧。基本使用先导入此布局控件。allprojects { repositories { ... maven { url 'https://jitpack.io' } } }dependencies { ... implementation 'com.github.PYJTLK:MindMapViewTest:1.0' }布局代码如下。<com.pyjtlk.widget.TreeLayout android:id="原创 2020-06-29 20:53:14 · 1262 阅读 · 0 评论 -
Android自定义控件教程目录
这里有Android自定义控件的基础教程和进阶教程以及自定义控件的Github链接原创 2020-06-21 17:25:35 · 270 阅读 · 0 评论 -
手把手写Android自定义控件(四):添加状态监听器
上一篇讲解了控件的测量与绘制,难度一下子上来了。本篇来讲解点击事件和开关状态获取,相比于上一篇,这部分的内容相对简单一点。设置与获取开关状态回顾一下上一篇的init方法。private void init(){ mPaint = new Paint(); mPaint.setAlpha(255); mPaint.setAntiAlias(true); //1 switchOn = false; setOnC原创 2020-06-21 13:52:23 · 691 阅读 · 0 评论 -
手把手写Android自定义控件(三):测量宽高与绘制
上一篇讲解了自定义属性的相关操作,本篇来讲解如何测量控件。相比于前面的步骤,测量工作的复杂了许多,在这个阶段建议准备一张草稿纸记录各种思路,这样不容易乱。下面是我在设计WaveLoadingView时的草稿。认识MeasureSpec在正式开始写测量代码前,首先需要知道一个重要的参数,MeasureSpec。它是一个32位的整型数据,由 模式 和 长度 组成,它的结构如下。其中0 ~ 29位封装了具体的尺寸值(像素个数),30 ~ 31位封装了模式。模式有三种:EXACTLY,AT_MOST原创 2020-06-21 12:41:11 · 654 阅读 · 0 评论 -
手把手写Android自定义控件(二):自定义属性的定义与获取
上一篇讲解了如何创建项目和库,本篇来讲解如何给自定义控件定义属性。属性定义首先我们在widgetlib的下创建一个类叫Switch(开关),继承于View,让它继承View的全部构造函数。接着在values文件夹下创建一个属性声明文件,名字叫attr_switch,一般命名的规则是attr_xxx,表示某控件的属性声明。文件创建好了,接下我们想想这个控件需要定义什么属性,结合下面的图片来看看。1.开关打开的颜色(蓝色部分)2.开关关闭的颜色(灰色部分)3.开关的底色(红色)4.开关凹槽原创 2020-06-20 21:07:21 · 506 阅读 · 0 评论 -
手把手写Android自定义控件(一):项目创建与配置
手把手写自定义控件系列意在让Android初学者快速学习自定义控件开发,感兴趣的朋友快来看看吧。基本配置这里我使用的是Android Studio3.5。Android Studio版本还停留在1和2的朋友建议先升级到3.0以上。我们先创建一个项目,这里选择Empty Activity,空的Activity简洁一些。接下来语言这里选用Java。其次需要把红色方框的选项选上,因为Google已经不再对support库进行更新了,现在的推荐使用androidx的库。刚升级到Android Studio原创 2020-06-20 19:11:07 · 574 阅读 · 0 评论 -
Android自定义控件-雷达图
效果展示先来看看效果。基本使用先在Gradle上导入控件。allprojects { repositories { ... maven { url 'https://jitpack.io' } } }dependencies { ... implementation 'com.github.PYJTLK:RadarViewTest:1.0' }接着在布局文件上摆放雷达图控件,控件推荐长宽一致。<com.pyjtlk.radarview.原创 2020-06-20 18:07:54 · 437 阅读 · 0 评论 -
波形自定义控件(六):原理解析之监听器
上一篇讲解了如何在自定义控件中进行性能优化,本篇来讲解如何给自定义控件添加监听器。基本方法说到监听器,相信OnClickListener是大家所熟知的,控件被点击后就会调用OnCLickListener的回调方法。按照这个原理我们也可以自己为自定义控件设计一种监听器。首先我们要想好要监听什么,明确了这一点才能开始动工。拿我之前写的弹性指示器做例子。现在要设计一个监听器,用来监听小圆点出发事件和尾巴到达终点的事件。可以在控件里写一个静态接口。public static interface Poin原创 2020-06-17 20:42:30 · 182 阅读 · 0 评论 -
波形自定义控件(五):原理解析之性能优化
上一篇讲解了自定义控件的绘制及动画效果的实现原理,不过示例代码还有很多很多需要改进的地方,本篇来讲解几个优化的技巧。优化1:减少在onDraw方法上的计算和对象创建在上一篇文章我们知道,控件要多次调用onDraw方法才能实现动画效果。如果在onDraw方法上做过于耗时的事情,就会导致动画看起来很卡顿,严重的话甚至导致ANR。其次,由于频繁调用onDraw方法,如果在上面创建对象,会产生大量临时的对象,进而导致GC频繁。回顾一下上一篇写的onDraw方法。@Overrideprotected vo原创 2020-06-17 19:31:11 · 214 阅读 · 0 评论 -
波形自定义控件(四):原理解析之控件绘制与动画效果
上一篇讲解了WaveLoadingView的测量步骤,本篇将讲解它的绘制原理。前期准备在讲解Android自定义控件绘制之前,我们首先需要知道动画效果是怎么实现的。下面这张图小球从左沿着一条弧线的轨迹运动到右边。把它的动作分解一下。我们称每一张图片为帧,小球运动的动画效果其实就是帧1~帧5快速切换产生的。动作分解的越细,动画的效果也越好,当然帧数变多了,动画的体积也就跟着变大了。onDraw方法上一篇我们完成了控件的测量工作,但此时如果我们把控件拿来使用估计什么都不会显示。那是因为onMe原创 2020-06-17 18:00:52 · 332 阅读 · 0 评论 -
波形自定义控件(三):原理解析之测量宽高
上一篇讲解了自定义控件初始化的相关步骤,本篇来讲解自定义控件的宽高测量。重写onMeasure方法我们从布局文件上获取到了相关的参数,现在需要测量这个控件的宽高,重写如下方法。@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec,heightMeasureSpec); }先来讲讲widthMe原创 2020-06-17 13:31:14 · 318 阅读 · 0 评论 -
波形自定义控件(二):原理解析之初始化
上一篇向我们展示了WaveLoadingView的效果,本篇及后续几篇来讲解它的实现原理,先从控件的初始化开始。创建自定义控件的java文件首先我们为自定义控件创建一个java文件,并让它继承某个自定义控件,以WaveLoadingView为例,此外还需要继承控件的构造函数,默认有四个,都继承下来。public class WaveLoadingView extends View { //1 public WaveLoadingView(Context context) { sup原创 2020-06-16 23:33:18 · 226 阅读 · 0 评论 -
波形自定义控件(一):效果展示与使用方法
耗时一天,终于做出了一个波形加载控件,来看看效果吧。效果展示基本使用先在布局文件上放置一个WaveLoadingView,设置相关的参数。这里以上图红色的长方形风格为例。<com.pyjtlk.waveloadingview.WaveLoadingView android:layout_width="wrap_content" android:layout_height="wrap_content" app:imageWaveType="rec原创 2020-06-16 22:20:34 · 414 阅读 · 0 评论 -
Android弹性圆点指示器绘制详解
目录流程简析onMeasure()处理onLayout()处理onDraw()处理初识invalidate()和postInvalidate()添加动画效果基本使用效果流程简析 整个控件的加载运行流程如下图所示:onMeasure()处理 onMea...原创 2020-01-31 16:42:56 · 900 阅读 · 0 评论