界面无小事(五):自定义TextView

界面无小事(五):自定义TextView

界面无小事(一): RecyclerView+CardView了解一下

界面无小事(二): 让RecyclerView展示更多不同视图

界面无小事(三):用RecyclerView + Toolbar做个文件选择器

界面无小事(四):来写个滚动选择器吧!

界面无小事(五):自定义TextView

界面无小事(六):来做个好看得侧拉菜单!

github传送门


目录

  • 效果图
  • 前言
  • 自定义属性
  • MeasureSpec类
  • 颜色解析
  • 字号转换
  • 最后

效果图

不多废话, 直接上图, 如果感兴趣再看下去.


前言

写第四篇滚动选择器的时候, 在自定义视图这里含糊了, 有些地方没说清楚, 这次补上关于自定义视图的部分.


自定义属性

自定义视图的一个要点就是添加自定义属性. 这里我们填上三个常用的, 文本, 颜色, 字号. 然后在布局文件中就可以使用了. 最后在自定义类中获取属性并赋值.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextView">
        <attr name="text" format="string" />
        <attr name="color" format="color" />
        <attr name="size" format="dimension" />
    </declare-styleable>
</resources>
复制代码
xmlns:app="http://schemas.android.com/apk/res-auto"
复制代码
<com.so.mytextview.ui.view.MyTextView
    android:id="@+id/mtv_test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    app:color="@color/colorAccent"
    app:size="60sp"
    app:text="hello world" />
复制代码
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    // 获取自定义属性
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);

    mSize = ta.getDimension(R.styleable.MyTextView_size, 16);
    mText = ta.getString(R.styleable.MyTextView_text);
    mColor = ta.getColor(R.styleable.MyTextView_color, Color.BLACK);

    ta.recycle();

    // 设置画笔
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setTextSize(mSize);

    // 设置背景颜色
    mBkColor = Color.BLUE;
}
复制代码

MeasureSpec类

MeasureSpec类官方文档 关于onMeasure方法, 最重要的就是就是MeasureSpec类的使用了. 其实主要也就是要算好match_parentwrap_content. match_parent和具体数值都是EXACTLY. wrap_content是AT_MOST. ScrollView或者是ListView就会是UNSPECIFIED.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = 0;
    int height = 0;

    int specMode = MeasureSpec.getMode(widthMeasureSpec);
    int specSize = MeasureSpec.getSize(widthMeasureSpec);

    switch (specMode) {
        case MeasureSpec.EXACTLY:
            width = getPaddingLeft() + getPaddingRight() + specSize;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            width = (int) (getPaddingLeft() + getPaddingRight()
                    + mPaint.measureText(mText));
            break;
    }

    specMode = MeasureSpec.getMode(heightMeasureSpec);
    specSize = MeasureSpec.getSize(heightMeasureSpec);

    switch (specMode) {
        case MeasureSpec.EXACTLY:
            height = getPaddingTop() + getPaddingBottom() + specSize;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            Paint.FontMetrics fmi = mPaint.getFontMetrics();
            float textHeight = Math.abs(fmi.bottom - fmi.top);
            height = (int) (getPaddingTop() + getPaddingBottom() + textHeight);
            break;
    }

    setMeasuredDimension(width, height);
}
复制代码

有两个要点, 就是算字符串的宽度和高度, 宽度用Paint实例的measureText方法即可. 高度涉及到我在第四篇写的Paint.FontMetrics类, 就是用底部减去顶部取绝对值.


颜色解析

Color是个要处理的类, 当你用getColor函数获取到函数, 它是一个int值, 如果我们需要重新在原有颜色基础上变化, 就需要解析这个int, 将它还原成RGB.

/**
 * 依据颜色值获取rgb值
 *
 * @param color 颜色值
 * @return rgb值
 */
public int[] setColor(int color) {
    int[] rgb = new int[3];
    rgb[0] = (color & 0x00ff0000) >> 16;
    rgb[1] = (color & 0x0000ff00) >> 8;
    rgb[2] = (color & 0x000000ff);
    return rgb;
}
复制代码

字号转换

要处理好字号问题, 最重要的就是转换, 代码中都是用px的, 但是布局文件一般用sp.

/**
 * sp转px
 */
public static int sp2px(float spVal) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
            spVal, getContext().getResources().getDisplayMetrics());
}

/**
 * px转sp
 */
public static float px2sp(float pxVal) {
    return (pxVal / getContext().getResources().getDisplayMetrics().scaledDensity);
}
复制代码

最后

这样可以自定义一些简单的视图类了, 如果要更复杂的, 还需要去处理更多的参数, 特别是构造方法那个四参数的. 有意见或者建议评论区见, 喜欢记得点赞或者关注我哦~


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101539.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 碰撞检测经典解决方案

    碰撞检测经典解决方案碰撞检测在3D游戏中至关重要,好的碰撞检测要求人物在场景中可以平滑移动,遇到一定高度内的台阶可以自动上去,而过高的台阶则把人挡住,遇到斜率较小的斜坡可以上去,斜率过大则把人挡住,在各种前进方向被挡住的

    2022年7月3日
    38
  • CSDN Chrome插件来了。助开发者提升开发效率,远离996

    插件定位帮助开发者提升开发效率,远离996特点以搜索框为入口,集成开发者常用工具,提升开发效率主要功能如下:支持本地书签、tab页、历史记录搜索集成CSDN搜索结果,本地内容和远程结果无缝集成所有操作都支持快捷键,提升搜索效率他是一个时间转换工具他是一个计算器他是。。。,更多功能正在添加中安装下载安装包浏览器输入地址“chrome://extensions/”进入扩展程序页面,开启开发者模式以下操作任选其一:zip文件安装:点击“加载已解压的扩展程序”按钮,选择已解压

    2022年4月8日
    64
  • 伴随矩阵求逆矩阵(已知A的伴随矩阵求A的逆矩阵)

    在之前的文章《线性代数之矩阵》中已经介绍了一些关于矩阵的基本概念,本篇文章主要就求解逆矩阵进行进一步总结。余子式(Minor)我们先看例子来直观的理解什么是余子式(Minor,后边将都用英文Minor,中文的翻译较乱)。minorexample这个例子(我们假设矩阵为A)中我们看到A[1,1]的minor就是将A[1,1]所在的行和列删除后剩下的矩阵的行列式,假设我们把A[…

    2022年4月13日
    151
  • laravel5.4 前后台未登陆,跳转到各自的页面

    laravel5.4 前后台未登陆,跳转到各自的页面

    2021年10月25日
    38
  • java实战——图书管理系统

    因为这个写的比较完整,所以简单说明一下过程中使用的EJB和RMI两个东西。EJB实现原理:就是把原来放到客户端实现的代码放到服务器端,并依靠RMI进行通信。RMI实现原理:就是通过Java对象可序列化机制实现分布计算。好了,没了,就这么简单…想稍微深入了解一下的看一下这个好了,我就不再赘述。https://blog.csdn.net/lovechuanyu/article/…

    2022年4月12日
    41
  • 【摄像头】图像传感器尺寸、像素大小和成像质量的关系

    【摄像头】图像传感器尺寸、像素大小和成像质量的关系1、图像传感器的尺寸(靶面大小)越大,成像质量越好如果相同分辨率的相机,传感器面积越大,则其单位像素的面积也越大,成像质量也会越好。同样的500万像素的摄像头,2/3”的传感器成像质量就要优于1/2”的。2、图像传感器的尺寸单位换算图像传感器的尺寸大小是指靶面对角线的长度,单位为英寸,1英寸等于16mm。这样1/2”传感器对角线长度则为8mm,按照一般的传感器的长宽比为4:3的话,那么就对应勾股定理,1/2”的传感器长宽分辨率为6.4mm、4.8mm。如某相机的分辨率为25881940的500万像素

    2022年6月10日
    71

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号