Android自定义控件零基础简述「JAVA,基础」

简介: Android自定义控件「JAVA,基础」我们有原生控件可以使用,但特定需求下,仍然无法满足我们,这时我们只能去自定义控件。自定义后如果开源,就成了我们熟悉的开源库,轮子。

Android自定义控件「JAVA,基础」

我们有原生控件可以使用,但特定需求下,仍然无法满足我们,这时我们只能去自定义控件。

自定义后如果开源,就成了我们熟悉的开源库,轮子。例如以下两个开源库,选项卡开源库FlycoTabLayout,动画开源库lottie-android

源代码已上传至View文件夹

Canvas操作

创建/module/canvasx/XView类,让该类继承于View类。使用快捷键Alt+insert,选择第一个Construct重写该类的必须要的两个构造方法。

  • 如不重写构造一程序在编译时就会报红
  • 如不重写构造二程序在编译时不会报红,但是当运行起来后,程序会崩溃,出现android.view.InflateException: Binary XML file line #9: 异常

关于这两个构造方法何时会被调用稍后会给出解释

import android.content.Context;
import android.view.View;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
public class XView extends View{
    public XView(Context context) {
        super(context);
    }
    
    public XView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
}

View类是所有控件的父类,例如我们熟悉的TextView,ImageView,而TextView又是EditView,button的父类

img_2a1303f862ed61226d1a26df7c30a784.png
继承关系

子类可使用父类的非私有方法,而父类并不能使用子类特有方法。意味着一般情况下子类拥有的方法,属性,要比父类多。

同理,View有的方法,属性同样较少,如果我们选择继承它,就得从零开始写起。但如果我们是想在某一控件上做功能扩展,我们可以选择继承于某一控件。

如需要个一键清除输入内容的输入框(在源代码处会给出参考代码),就可以选择继承于EditView,在此基础上增加功能,当然,现在我们学习,只需要继承于View就可以了。

img_4dee6d81bcb3dfe77a999d926274c309.gif
一键删除,密码显示隐藏.gif

重写父类一个onDraw方法,之后我们绘制东西,就是在该方法中绘制

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

public class XView extends View {
    public XView(Context context) {
        super(context);
    }

    public XView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 解释一下Canvas类,如果把XView类比作一个画板,那么Canvas就好比我们放在画板上的画纸,
     * 之后我们绘制的东西,就是呈现在该画纸上
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.parseColor("#03A9F4"));//使用java代码调用颜色
    }
}


在Canvas上调用drawColor方法给Canvas填充颜色,创建ViewActivity,在actiivty_view.xml下使用我们自定义的控件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".module.canvasx.ViewActivity">

    <!--下面的是我们控件所在的包名,打出控件首字母就会有自动提示的-->
    <com.example.tonjies.view.module.canvasx.XView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>

运行程序,确实和我们想的一样,画布上有了颜色

img_e3d4d6ca367875af28682c8890928d31.png
Canvas颜色

现在回过头开看看XView的两个构造方法

/**
 * 只含有一个参数Context的构造方法,在代码创建组件时会被调用
 * 例如XView xView=new XView
 * L是自己封装的Log工具类,不清楚的可以查看我的一篇文章
 * https://www.jianshu.com/p/6ca3026fc991
 * @param context
 */
public XView(Context context) {
    super(context);
    L.d("在代码创建时被调用");
}

/**
 * 在xml加载时被调用
 * @param context
 * @param attrs
 */
public XView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);  
    L.d("在xml加载时被调用");
}

一个参数的构造方法会在创建组件时被调用,我们把xml里面的控件注释掉,在Activity中手动创建,打个日志运行进行验证

public class ViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view);
        XView view = new XView(this);
    }
}

一个参数的构造方法验证成功后,我们再把xml的控件注释回来,运行程序,发现构造二也打印出了log,证明我们的猜想确实是对的

Paint

Paint类好比是我们的画笔,接下来看一下Paint类常用方法,创建XViewb类

public class XViewb extends View {

    private Paint paint;

    public XViewb(Context context) {
        super(context);
    }

    public XViewb(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setStyle(Paint.Style.FILL);//设置画笔类型
        paint.setStrokeWidth(200f);//设置画笔宽度
        paint.setColor(Color.BLACK);//设置画笔颜色
        canvas.drawPoint(0,0,paint);//设置坐标0,0
    }
}

声明了Paint类,在含有二个参数的构造方法中初始化Paint。在onDraw中通过setStrokeWidth设置画笔的宽度是200个像素,颜色是蓝色,最后调用canvas的drawPoint方法绘制了一个点

而setStyle方法的作用是设置画笔的类型,一共有三种类型可以选择,分别是FILL(填充类型),STROKE (描边类型),FILL_AND_STROKE (填充且描边)

img_0222579ec6cd92e16eee41c4a4d6efdc.png
画笔类型

可以看到FILL填充,就只是填充内部的,而FILL_AND_STROKE在填充后又进行描边,会比单填充大一圈。

canvas.drawPoint(0,0,paint);//设置坐标0,0,但是这个方法的坐标系正负和我们高中学的有所不同。

img_b2e28e8e2777c6d86472f4a49819f921.png
坐标

x轴:向右为正方向,向左为负方向

y轴:向下为正方向,向上为负方向

Path

Path的作用是作为“路径”而存在的,有点类似photoshop里面钢笔工具画出来的路径,理解起来就是我们画出特定轨迹的路径,然后使用画笔工具对路径进行绘制操作

  • 绘制一个三角形
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.example.tonjies.view.R;

/**
 * Path类
 */
public class XViewc extends View {

    private Paint paint;

    public XViewc(Context context) {
        super(context);
    }

    public XViewc(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setStyle(Paint.Style.STROKE);//设置画笔类型为描边
        paint.setStrokeWidth(8);//设置画笔宽度
        paint.setColor(getResources().getColor(R.color.colorAccent));

        //初始化Path
        Path path=new Path();
        path.moveTo(300,50);//moveTo方法是移动路径绘制起点位置,起点位置是(300,30)
        path.lineTo(500,50);//lineTo方法在起点(300,30)到(500,50)之间绘制一条线段

        //调用canvas的drawPath,把path和画笔作为参数传递进入
        canvas.drawPath(path,paint);
    }
}

很简单的案例,通过moveTo(300,50)设置起点,然后通过lineTo(500,50)绘制一条从点(200,200)到(500,50)的线段,而线段的颜色的宽度是由我们的画笔的属性决定的

img_d81563f9a2bb7d8379490f7b45861608.png
path绘制直线.png

现在我们修改一下Path代码,运行程序

//初始化Path
Path path=new Path();
path.moveTo(200,200);//moveTo方法是移动路径绘制起点位置,起点位置是(200,200)
path.lineTo(400,200);//lineTo方法在起点(200,200)到(400,200)之间绘制一条线段
path.lineTo(200,400);//linTo方法在起点(400,200)到(200,400)之间绘制一条直线,该直线在我们的图像中,就是斜线
path.close();//close()方法会产生一条最短的线段闭合我们的路径,两点之间直线最短嘛,该直线在我们的图形中,就是点1(200,200)到点3(200,400)之间的直线
img_6266fe3f1de348f2f11beadd9e45a725.png
path绘制三角形.png

这样,我们就绘制了一个三角形,如果我们把画笔的模式变为FILL,就变成了一个实心的三角形

 paint.setStyle(Paint.Style.FILL);//设置画笔类型为填充

代码和效果都很简单,就不贴图了

这一小节就到这了,该小节仅仅只能作为快速了解,自定义控件包含的内容实在是很多,如果想要进一步的学习,可以查看我的Android文章推荐里面的推荐教程

文本知识和图片部分来自随风飘扬的微笑的博客,感谢大佬的付出,比起学校某些碌碌无为的人,我更愿意来称呼像启航,郭神,鸿阳前辈,刘桂林等前辈这些,这样的人为老师

如果本篇文章对你有所帮助,麻烦给个喜欢,对于我来说,这是一种很好的鼓励,thank

img_30b1f6e5518f49797537eb655a898d64.gif
谢谢,谢谢
目录
相关文章
|
2月前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的海洋中,自定义控件是那片璀璨的星辰。它不仅让应用界面设计变得丰富多彩,还提升了用户体验。本文将带你探索自定义控件的核心概念、实现过程以及优化技巧,让你的应用在众多竞争者中脱颖而出。
|
2月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
86 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
2月前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件基础与进阶
【10月更文挑战第5天】在Android应用开发中,自定义控件是提升用户体验和界面个性化的重要手段。本文将通过浅显易懂的语言和实例,引导你了解自定义控件的基本概念、创建流程以及高级应用技巧,帮助你在开发过程中更好地掌握自定义控件的使用和优化。
45 10
|
28天前
|
前端开发 Android开发 UED
安卓应用开发中的自定义控件实践
【10月更文挑战第35天】在移动应用开发中,自定义控件是提升用户体验、增强界面表现力的重要手段。本文将通过一个安卓自定义控件的创建过程,展示如何从零开始构建一个具有交互功能的自定义视图。我们将探索关键概念和步骤,包括继承View类、处理测量与布局、绘制以及事件处理。最终,我们将实现一个简单的圆形进度条,并分析其性能优化。
|
2月前
|
前端开发 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的世界里,自定义控件如同画家的画笔,能够绘制出独一无二的界面。通过掌握自定义控件的绘制技巧,开发者可以突破系统提供的界面元素限制,创造出既符合品牌形象又提供卓越用户体验的应用。本文将引导你了解自定义控件的核心概念,并通过一个简单的例子展示如何实现一个基本的自定义控件,让你的安卓应用在视觉和交互上与众不同。
|
3月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
3月前
|
缓存 前端开发 Android开发
安卓应用开发中的自定义控件
【9月更文挑战第28天】在安卓应用开发中,自定义控件是提升用户界面和交互体验的关键。本文通过介绍如何从零开始构建一个自定义控件,旨在帮助开发者理解并掌握自定义控件的创建过程。内容将涵盖设计思路、实现方法以及性能优化,确保开发者能够有效地集成或扩展现有控件功能,打造独特且高效的用户界面。
|
2月前
|
XML 存储 Java
浅谈Android的TextView控件
浅谈Android的TextView控件
41 0
|
3月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
159 1
|
3月前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
53 3