Android Studio App自定义控件中视图的构造和测量方法讲解及实战(附源码 实现下拉刷新功能 超详细必看)

news2025/7/6 21:37:03

需要全部源码或者图片集请点赞关注收藏后评论区留言~~~

一、视图的构造方法

Android自带的控件往往外观欠佳,开发者常常需要修改某些属性,比如按钮控件Button就有好几个问题,其一字号太小,其二文字颜色太浅,其三字母默认大写。于是XML文件中的每个Button节点就得添加textSize,textColor,textAllCaps三个属性,以便定制按钮的字号,文字颜色和大小写开关。

为了避免每个按钮都去修改,我们一般采用定义一个style.xml文件来定义格式,然后需要的时候引用它即可 效果如下

然而这样仍有不足之处,因为只有Button节点添加了style属性才奏效,要是忘了添加style属性就不管用了,而且样式引用只能修改已有的属性,不能添加新属性,也不能添加新方法,如果想更灵活的定制控件外观,就要通过自定义控件实现了。

自定义控件本质上都是一个Java类,也拥有自身的构造方法 它有四个构造方法如下

1:带一个参数的构造方法 public View()

2:带两个参数的构造方法 public View()

3:带三个参数的构造方法 public View()

4:带四个参数的构造方法 public View()

上述四种方法,前两种必须实现,否则不能在代码中创建视图对象,要么不能在XML文件中添加视图节点 

进行自定义控件操作后效果如下 可以看见第三个按钮也就是自定义的按钮控件字号变大,文字变黑,同时按钮的默认背景不见了,文字也不居中对齐了

代码如下

Java类 

package com.example.chapter10;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class CustomButtonActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_button);
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是系统默认的Button"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是来自style的Button"
        style="@style/CommonButton"/>

    <!-- 注意自定义控件需要指定该控件的完整路径 -->
    <com.example.chapter10.widget.CustomButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是自定义的Button"
        android:background="#ffff00"/>

</LinearLayout>

二、视图的测量方法

构造方法只是自定义控件的第一步,自定义控件的第二步时测量尺寸,也就是重写onMeasure方法,要想把自定义的控件画到界面上,首先得先直到这个控件的宽高尺寸

1:文本尺寸测量

文本尺寸分为文本的宽度和高度,需要根据文本大小分别计算,其中文本宽度用Paint类的measureText方法测量,至于文本高度的计算则用到了FontMetrics类, 效果如下

放大后效果如下

 

代码如下

Java类

package com.example.chapter10;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter10.util.MeasureUtil;

@SuppressLint("DefaultLocale")
public class MeasureTextActivity extends AppCompatActivity {
    private TextView tv_desc, tv_text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_measure_text);
        tv_desc = findViewById(R.id.tv_desc);
        tv_text = findViewById(R.id.tv_text);
        initSizeSpinner(); // 初始化文字大小的下拉框
    }

    // 初始化文字大小的下拉框
    private void initSizeSpinner() {
        ArrayAdapter<String> sizeAdapter = new ArrayAdapter<String>(this,
                R.layout.item_select, descArray);
        Spinner sp_size = findViewById(R.id.sp_size);
        sp_size.setPrompt("请选择文字大小");
        sp_size.setAdapter(sizeAdapter);
        sp_size.setOnItemSelectedListener(new SizeSelectedListener());
        sp_size.setSelection(0);
    }

    private String[] descArray = {"12sp", "15sp", "17sp", "20sp", "22sp", "25sp", "27sp", "30sp"};
    private int[] sizeArray = {12, 15, 17, 20, 22, 25, 27, 30};

    class SizeSelectedListener implements OnItemSelectedListener {

        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            String text = tv_text.getText().toString();
            int textSize = sizeArray[arg2];
            tv_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
            // 计算获取指定文本的宽度(其实就是长度)
            int width = (int) MeasureUtil.getTextWidth(text, textSize);
            // 计算获取指定文本的高度
            int height = (int) MeasureUtil.getTextHeight(text, textSize);
            String desc = String.format("下面文字的宽度是%d,高度是%d", width, height);
            tv_desc.setText(desc);
        }

        public void onNothingSelected(AdapterView<?> arg0) {}
    }
}

xml文件 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp" >

        <TextView
            android:id="@+id/tv_size"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:gravity="center"
            android:text="字体大小:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <Spinner
            android:id="@+id/sp_size"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_toRightOf="@+id/tv_size"
            android:gravity="left|center"
            android:spinnerMode="dialog" />
    </RelativeLayout>
    
    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:textColor="@color/black"
        android:textSize="17sp" />
    
    <TextView
        android:id="@+id/tv_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:gravity="center"
        android:text="每逢佳节倍思亲"
        android:textColor="@color/black" />

</LinearLayout>

 2:图形尺寸测量

相对于文本尺寸,图形尺寸的计算反而简单一些,因为Android提供了现成的宽和高的获取方法,如果图形时Bitmap格式,就通过getWidth方法获取宽度 其他类似

3:布局尺寸测量

View类提供了一种测量整体布局的思路,下面通过实战讲解 实现了一个下拉刷新功能

 代码如下

Java类

package com.example.chapter10;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter10.util.MeasureUtil;

@SuppressLint("DefaultLocale")
public class MeasureLayoutActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_measure_layout);
        LinearLayout ll_header = findViewById(R.id.ll_header);
        TextView tv_desc = findViewById(R.id.tv_desc);
        // 计算获取线性布局的实际高度
        float height = MeasureUtil.getRealHeight(ll_header);
        String desc = String.format("上面下拉刷新头部的高度是%f", height);
        tv_desc.setText(desc);
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <include layout="@layout/drag_drop_header" />
    
    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:gravity="left"
        android:textColor="@color/black"
        android:textSize="17sp" />
    
</LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4735.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

表白爱心代码

文章目录一、演示&#xff08;python版&#xff09;代码二、演示&#xff08;html版&#xff09;代码一、演示&#xff08;python版&#xff09; 代码 # 在等一句我愿意 import random from math import sin, cos, pi, log from tkinter import *CANVAS_WIDTH 640 # 画布的宽…

hive最近的学习汇总-20221110

下个项目可能要用hive比较多 之前对分区、分桶搞不明白 趁着最近又学习了一下 ps&#xff1a;之前说的prophet在年底前一定会放上来的 hive是基于Hadoop构建的一套数据仓库分析系统&#xff0c;它提供了丰富的SQL查询方式来分析存储在Hadoop分布式文件系统中的数据&#xff1…

MySQL管理常用工具介绍

1.mysql 该mysql不是指mysql服务&#xff0c;而是指mysql的客户端工具。 -e选项可以在Mysql客户端执行SQL语句&#xff0c;而不用连接到MySQL数据库再执行&#xff0c;对于一些批处理脚本&#xff0c; 这种方式尤其方便。 示例&#xff1a; 2、 mysqladmin mysqladmin 是一个…

大三Web课程设计——悬崖上的波妞(4页) HTML+CSS(可以很好的应付老师的作业)

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 ⚽精彩专栏推荐&#x1…

Java基础系列(八)——线程池详解

目录 线程池详解 什么是线程池&#xff1f;为什么要用线程池&#xff1f; 如何创建线程池 ThreadPoolExecutor类分析 ThreadPoolExecutor 饱和策略 简单的线程池Demo ThreadPoolExecutor线程池新增线程流程 线程池详解 什么是线程池&#xff1f;为什么要用线程池&#…

Word2Vec原理以及实战详解

文章目录前言0、序言(词嵌入介绍)一、Word2vec详解。二、CBOW 和 Skip-Gram详解。2-1、CBOW模型:&#xff08;已知周围词预测中心词&#xff09;2-2、Skip-Gram模型&#xff08;已知中心词预测周围词&#xff09;2-3、词嵌入的缺点三、Word2vec实战&#xff08;使用Gensim包&am…

[SQL]视图和权限

有时让用户看到整个基本表是不合适的&#xff0c;出于安全考虑&#xff0c;可能需要向用户隐藏特定的数据。如在instructor关系中隐藏工资值&#xff1a; select ID,name,dept_name from instructor;创建更符合特定用户直觉的个人化的关系集合&#xff0c;如学生成绩表由学生关…

一文学会JavaScript计时事件

文章目录JavaScript 计时事件setInterval() 方法clearInterval() 方法setTimeout() 方法clearTimeout() 方法JavaScript 计时事件 通过使用 JavaScript&#xff0c;我们有能力做到在一个设定的时间间隔之后来执行代码&#xff0c;而不是在函数被调用后立即执行。我们称之为计时…

Linux--基础命令

一、Linux指令 mkdir&#xff08;Make Directory&#xff09;&#xff1a;在当前路径下新建一个目录 -p --parents 可以是一个路径名称。此时若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多个目录; ls&#xff08;List…

Day796.什么是线程数据的强、弱一致性 -Java 性能调优实战

什么是线程数据的强、弱一致性 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于什么是线程数据的强、弱一致性。 一致性&#xff0c;其实在系统的很多地方都存在数据一致性的相关问题。 除了在并发编程中保证共享变量数据的一致性之外&#xff0c;还有数据库的 ACI…

Autosar基本概念详细介绍

Autosar的由来 在汽车创新应用不断涌现的推动下&#xff0c;当代汽车电子电气&#xff08;E/E—Electronic/Electrical&#xff09;架构已经非常复杂&#xff0c;需要有创新的技术突破才能有效地进行管理&#xff0c;满足日益增长的乘客需求和法律要求。这个需求对汽车制造商及…

记一次简单的HTTP绕WAF

0X01 基础知识 关于WAF的问题&#xff1f; 它是我们日常攻防演练必会遇见的&#xff0c;在IOS七层模型中&#xff0c;WAF分为网络层、应用层的&#xff0c;当然还有云 WAF&#xff08;CDNWAF&#xff09;这新型类场景的。不同环境下我们绕过WAF的思路也是有所区别的&#xff…

mybatis单框架通用mapper使用(二)

mybatis单框架通用mapper使用(二) 1 查询 1.1 简单查询 1.1.1 查多条 a 用法 接口引用.select(实体类对象引用); //里面实体类对象,里面不为null值的部分就会作为条件被查询,多个条件使用and进行拼接起来 //传入为null就是查询全部的值b 测试代码 Testpublic void t2(){Sq…

直播带货系统源码,居家“神器”不出门就能购物

如今&#xff0c;直播带货的火爆程度已经超出了人们的想象。线下销售行业的卖家也开启了直播带货模式&#xff0c;直播带货的的火爆归根到底还是消费者的购物方式发生的变化。从传统的线下购物到电商购物&#xff0c;再到今天的直接直播带货。从各大数据可以总结&#xff0c;消…

应用密码学期末速通复习

文章目录模运算分数求模负数求模gcd最大公约数逆元分组密码DES加密AES加密操作模式ECB电子密码本CBC分组链接CFB密码反馈OFB输出反馈序列密码A5-1算法RC4算法Hash函数Md5算法SHA-1算法消息认证数字信封公钥密码背包公钥算法RSA公钥算法Rabin公钥算法ElGamal公钥算法ECC公钥算法…

C/C++刷题DAY2

1.第一题 27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 分析&#xff1a;对于此题&#xff0c;我们使用双指针的方式去写它&#xff0c;需要注意空间复杂度是O&#xff08;1&#xff09;&#xff0c;时间复杂度也是尽量的越低越好&#xff0c;要去需要原地修改数组&a…

Matplotlib设置刻度和刻度标签

Matplotlib在我们之前的所有例子中都自动接管了轴上间隔点的任务。Matplotlib的默认刻度定位器和格式化器在很多常见情况下通常都足够了。可以明确提及刻度线的位置和标签以满足特定要求。 xticks()和yticks()函数将列表对象作为参数。列表中的元素表示将显示刻度的相应操作的位…

nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇

文章目录前言一、对上一篇博文的分析二、配置文件分析1. nginx 官方网址&#xff08;很详细&#xff09;2、配置文件&#xff08;全&#xff09;3、配置文件&#xff08;去掉注释&#xff09;4、讲解a、nginx 配置文件有三部分组成b、全局块c、events块d、http块5、http块中loc…

无脚本自动化测试

在当今的企业环境中&#xff0c;软件测试不再被视为不必要的投资&#xff1b;相反&#xff0c;它已经上升到一种需要而不是奢侈品的水平。随着市场的不断变化和竞争的加剧&#xff0c;企业必须做一些让他们与竞争对手区分开来的事情。 为了使自己与众不同&#xff0c;公司必须…

Dockerfile

Dockerfile指令集 对于Dockerfiel而言&#xff0c;是在学习docker工具里面&#xff0c;最重点的内容&#xff0c;它可以帮助我们生成自己想要的基础镜像。部署一个容器最重要的就是镜像&#xff0c;指令都已经内置好了。 FROM 这个镜像的妈妈是谁&#xff1f;&a…