Android Studio新手开发第二十五天

目录

视图构建过程(一)

视图的构造方法

视图构建过程(一)

Android自带的控件外观有时候不尽人意,常常需要修改某些属性,如按钮有文本颜色、文字大小、字母默认大写等属性需要修改。如果只有一两个按钮还好,但若有许多个按钮,为了统一风格就需要一个一个去修改属性或者改变风格也要一个一个去修改,这样就很麻烦。如果将统一的风格定义在一个地方再引用,这样若要改变风格就只需要修改一个地方。这种方式需要在res/values目录下的styles.xml添加样式代码,若无该文件就新建一个即可,代码示例如下:

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="button_style">
        <item name="android:text">20</item>
        <item name="android:textColor">@color/red</item>
        <item name="android:textAllCaps">false</item>
    </style>
</resources>


//在对应的按钮中添加如下属性
style="@style/button_style"

虽然利用styles.xml自定义样式,不过若忘了添加style属性就不管用了,而且样式只能修改已有的属性,不能添加新的属性以及新方法。若想要灵活的定制控件外观就需要通过自定义控件实现了。

视图的构造方法

自定义控件本身实质上是一个Java类,有其本身的构造方法。以View视图基类为例,它有四个构造方法,说明如下:

View(Context context):带一个参数的构造方法,在Java代码中通过代码动态创建 View 时调用,如new关键字创建视图对象时调用该构造方法。

View(Context context,AttributeSet attrs):带两个参数的构造方法,在xml文件中添加视图节点时会调用该构造方法。

View(Context context,AttributeSet attrs,int defStyleAttr):带三个参数的构造方法,在采取默认的样式属性时会调用该构造方法。若defStyleAttr为0则表示无默认样式。

View(Context context,AttributeSet attrs,int defStyleAttr,int defStyleRes):带四个参数的工构造方法,在采取默认样式资源时会调用该构造方法。若defStyleRes为0则表示无样式资源。

以上四个构造方法,前两个必须实现,否则不能在Java代码中创建视图对象或者不能在xml文件中添加视图节点。后两个则与styles.xml中的样式配置有关。其中的参数defStyleAttr与res/values目录下的attrs.xml中的样式配置有关,若无该文件就先新建一个,然后往里面添加一些配置,如下所示。在里面定义了属性名称为customButtonStyle,属性格式为引用类型reference,也就是说具体的样式在别的地方定义的,而这个地方就是在styles.xml中定义具体的样式配置。那么如何将两者联系起来呢?在AndroidManifest.xml文件中的application节点上有一个属性android:theme,它是app的主题属性,打开它引用的主题所在文件,在里面添加一项customButtonStyle并指定对应的样式,代码如下面所示。

attrs.xml中的代码。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="Button_Custom">
        <attr name="customButtonStyle" format="reference"/>
    </declare-styleable>
</resources>

styles.xml中的代码。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="customButtonStyle">
        <!--文本大小-->
        <item name="android:textSize">20sp</item>
        <!--文本颜色-->
        <item name="android:textColor">@color/black</item>
        <!--字母大小写-->
        <item name="android:textAllCaps">false</item>
        <!--按钮文本-->
        <item name="android:text">自定义按钮</item>
        <!--按钮背景-->
        <item name="android:background">#FFBFBFBF</item>
        <!--内边距-->
        <item name="android:padding">10dp</item>
    </style>
</resources>

APP主题中的代码

XML 复制代码
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.MyApplicationForStudy" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
        <!--新添加的内容在这-->
        <item name="customButtonStyle">@style/customButtonStyle</item>
    </style>
    <style name="Theme.MyApplicationForStudy.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
</resources>

完成上面的操作后需要新建一个继承于按钮的类并编写代码,部分代码如下所示。重点在于第二个构造方法上,将刚刚新建的样式设置为默认样式。

java 复制代码
@SuppressLint("AppCompatCustomView")
public class Button_Custom extends Button {
    public Button_Custom(Context context) {
        super(context);
    }

    public Button_Custom(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.customButtonStyle);
    }

    public Button_Custom(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs,defStyleAttr);
    }

    public Button_Custom(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
}

最后在页面的布局文件中添加这个新建成的按钮,如下所示。要使用这个按钮需要完整路径。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".CustomWidget.CustomButtonActivity">

    <com.example.myapplicationforstudy.Widget.Button_Custom
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="默认按钮"/>

</LinearLayout>

效果图如下,可以区分两个按钮的区别。

上面的方法在实现上比较麻烦,需要修改多个地方。若使用第四个构造方法就可以简化这些操作。代码示例如下,在第三个构造方法中调用第四个构造方法设置样式资源,将defStyleAttr设置为0是因为它的优先级要高于defStyleRes,而它又低于style属性。它们的优先级顺序为style属性>defStyleAttr>defStyleRes。

java 复制代码
//这个 Lint 检查规则专门针对自定义 View 的 AppCompat 兼容性问题
//当你创建自定义 View 时,如果直接继承自 Android 原生 View(如 TextView, Button 等),而不是 AppCompat 的对应组件,Lint 会发出警告。
@SuppressLint("AppCompatCustomView")
public class Button_Custom extends Button {
    public Button_Custom(Context context) {
        super(context);
    }

    public Button_Custom(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.customButtonStyle);
    }

    public Button_Custom(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs,0,R.style.customButtonStyle);
    }
//当你的代码中使用了高于 minSdkVersion 的 API 时,Lint 会发出警告,这个注解可以消除这些警告。
    @SuppressLint("NewApi")
    public Button_Custom(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
}
相关推荐
從南走到北17 分钟前
JAVA国际版二手车交易二手车市场系统源码支持Android+IOS+H5+APP
android·java·ios
江上清风山间明月22 分钟前
Android 系统中进程和线程的区别
android·python·线程·进程
2501_940094021 小时前
mig烧录卡资源 Mig-Switch游戏合集 烧录卡 1.75T
android·游戏·安卓·switch
渡我白衣2 小时前
深入理解 OverlayFS:用分层的方式重新组织 Linux 文件系统
android·java·linux·运维·服务器·开发语言·人工智能
2501_915106322 小时前
iOS性能调优的系统化实践,从架构分层到多工具协同的全流程优化指南(开发者深度版)
android·ios·小程序·架构·uni-app·iphone·webview
stevenzqzq3 小时前
android recyclerview缓存_缓存问题解决办法
android·java·缓存
下位子3 小时前
『OpenGL学习滤镜相机』- Day10: 相机预览与 OpenGL 结合
android·opengl
那就逆流而上吧3 小时前
Android AIDL 的详细讲解和实践指南
android
WYS@不忘初心4 小时前
在Eclipse IDE for Embedded C/C++ Developers软件中定义的宏,编译C源文件时编译器无法找到宏定义!
java·ide·eclipse
未来之窗软件服务4 小时前
自建开发工具IDE(五)数据库预览——东方仙盟炼气期
数据库·ide·仙盟创梦ide·东方仙盟