返回顶部
首页 > 资讯 > 移动开发 >Android如何通过组合的方式自定义View
  • 754
分享到

Android如何通过组合的方式自定义View

2024-04-02 19:04:59 754人浏览 八月长安
摘要

前言: 自定义View可以分为两种方式: 第一种通过继承ViewGroup,内部通过addView的方式将其他的View组合到一起。第二种则是通过继承View,重启View的onMe

前言:

自定义View可以分为两种方式:

  • 第一种通过继承ViewGroup,内部通过addView的方式将其他的View组合到一起。
  • 第二种则是通过继承View,重启View的onMeasure,onLayout,onDraw方法来绘制不规则图形,如折线图等。

本文介绍的是第一种方式通过组合的方式去实现自定义View。

实现自定义View首先要自定义属性。对于自定义属性,第一步是在项目res/values文件夹中新建attrs.xml文件,在文件中设置自定义属性的名称和类型,

代码如下:

<resources>
    <declare-styleable name="InputItemLayout">
        <attr name="hint" fORMat="string"></attr>
        <attr name="title" format="string"/>
        <attr name="inputType" format="enum">
            <enum name="text" value="0"/>
            <enum name="passWord" value="1"/>
            <enum name="number" value="2"/>
        </attr>
        <attr name="inputTextAppearance" format="reference"/>
        <attr name="titleTextAppearance" format="reference"/>
        <attr name="topLineAppearance" format="reference"/>
        <attr name="bottomLineAppearance" format="reference"/>
    </declare-styleable>
    <declare-styleable name="inputTextAppearance">
        <attr name="hintColor" format="color" />
        <attr name="inputColor" format="color" />
        <attr name="textSize" format="dimension" />
        <attr name="maxInputLength" format="integer" />
    </declare-styleable>
    <declare-styleable name="titleTextAppearance">
        <attr name="titleColor" format="color" />
        <attr name="titleSize" format="dimension" />
        <attr name="minWidth" format="dimension" />
    </declare-styleable>


    <declare-styleable name="lineAppearance">
        <attr name="color" format="color" />
        <attr name="height" format="dimension" />
        <attr name="leftMargin" format="dimension" />
        <attr name="rightMargin" format="dimension" />
        <attr name="enable" format="boolean" />
    </declare-styleable>
</resources>

自定义属性都需要包裹在declare-styleable标签中,name属性标志这个属性集合的名字,其中的attr标志属性。对于自定义属性的类型,主要的有以下几种

string字符串类型 reference引用类型,一般是指向另外的一个资源属性 color颜色代码 dimension尺寸 float浮点型 boolean布尔型 integer整型 enum枚举型

当你定义完上面的文件,接下来我们需要在自定义View中解析它们,从而获得用户传递进来的属性。 属性的解析可以使用以下代码完成

val array = context.obtainStyledAttributes(attributeSet, R.styleable.InputItemLayout)
val title = array.getString(R.styleable.InputItemLayout_title)
val titleResId = array.getResourceId(R.styleable.InputItemLayout_titleTextAppearance, 0)

上面的代码中,第一句是通过obtainStyledAttributes解析上面XML文件中属性名为InputItemLayout的属性内容,并返回TypedArray,后续该命名空间中的所有属性都可以通过TypedArray.getXX()来获得XX是属性类型。

但是引用类型除外,因为引用类型中还包含了其他属性,所以需要如下代码去提取属性。

val array1 = context.obtainStyledAttributes(attributeSet, R.styleable.InputItemLayout)
val titleResId = array1.getResourceId(R.styleable.InputItemLayout_titleTextAppearance, 0)
val array = context.obtainStyledAttributes(titleResId, R.styleable.titleTextAppearance)
val titleColor = array.getColor(
    R.styleable.titleTextAppearance_titleColor,
    resources.getColor(R.color.color_565)
)

如上代码,我们先获取在InputItemLayout属性中titleTextAppearance的属性,这时候发现titleTextAppearance是一个引用类型的属性,在使用 context.obtainStyledAttributes(titleResId, R.styleable.titleTextAppearance)获取titleTextAppearance中的属性值,第一个参数titleResId是titleTextAppearance的资源ID。 最终我们获取了所有的属性,这时候就可以开始自定义你的View了。

当我们最终完成了所有的代码,怎么在布局文件中使用呢。对于普通的属性,如String Int等就和平常一样,但是对于引用类型,我们需要在style.xml文件中定义资源文件

<com.slowtd.tcommon.InputItemLayout
   Android:layout_marginTop="10dp"
   android:layout_width="match_parent"
   android:layout_height="55dp"
   app:hint="请输入密码"
   app:title="密码"
   app:inputType="text"
   app:titleTextAppearance="@style/titleTextAppearance"
   app:inputTextAppearance="@style/inputTextAppearance_limitLength"
   app:topLineAppearance="@style/lineAppearance"
   app:bottomLineAppearance="@style/lineAppearance"
   />
<style name="inputTextAppearance">
   <item name="hintColor">@color/color_C1B</item>
   <item name="inputColor">@color/color_565</item>
   <item name="textSize">15sp</item>
</style>

<style name="inputTextAppearance_limitLength" parent="inputTextAppearance">
   <item name="maxInputLength">4</item>
</style>
<style name="titleTextAppearance">
   <item name="titleColor">@color/color_565</item>
   <item name="titleSize">15sp</item>
   <item name="minWidth">100dp</item>
</style>
<style name="lineAppearance">
   <item name="color">@color/black</item>
   <item name="height">2dp</item>
   <item name="leftMargin">0dp</item>
   <item name="rightMargin">0dp</item>
   <item name="enable">true</item>
</style>

下面的代码是一个简单的自定义输入框代码,供大家参考,配合上面的XML属性资源就可以使用了。

class InputItemLayout : LinearLayout {
   private lateinit var titleView: TextView
   private lateinit var editText: EditText
   private var bottomLine: Line
   private var topLine: Line
   private var topPaint = Paint(Paint.ANTI_ALIAS_FLAG)
   private var bottomPaint = Paint(Paint.ANTI_ALIAS_FLAG)

   constructor(context: Context) : this(context, null)
   constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)
   constructor(context: Context, attributeSet: AttributeSet?, defStyle: Int) : super(
       context,
       attributeSet,
       defStyle
   ) {
       dividerDrawable = ColorDrawable()
       showDividers = SHOW_DIVIDER_BEGINNING

       //去加载 去读取 自定义sytle属性
       orientation = HORIZONTAL
       val array = context.obtainStyledAttributes(attributeSet, R.styleable.InputItemLayout)

       //解析title 属性
       val title = array.getString(R.styleable.InputItemLayout_title)
       val titleResId = array.getResourceId(R.styleable.InputItemLayout_titleTextAppearance, 0)
       parseTitleStyle(title, titleResId)

       //解析右侧的输入框属性
       val hint = array.getString(R.styleable.InputItemLayout_hint)
       val inputResId = array.getResourceId(R.styleable.InputItemLayout_inputTextAppearance, 0)
       val inputType = array.getInteger(R.styleable.InputItemLayout_inputType, 0)
       parseInputStyle(hint, inputResId, inputType)
       //上下分割线属性
       val topResId = array.getResourceId(R.styleable.InputItemLayout_topLineAppearance, 0)
       val bottomResId = array.getResourceId(R.styleable.InputItemLayout_bottomLineAppearance, 0)
       topLine = parseLineStyle(topResId)
       bottomLine = parseLineStyle(bottomResId)

       if (topLine.enable) {
           topPaint.color = topLine.color
           topPaint.style = Paint.Style.FILL_AND_STROKE
           topPaint.strokeWidth = topLine.height
       }
       if (bottomLine.enable) {
           bottomPaint.color = bottomLine.color
           bottomPaint.style = Paint.Style.FILL_AND_STROKE
           bottomPaint.strokeWidth = bottomLine.height
       }
       array.recycle()
   }
   @SuppressLint("CustomViewStyleable")
   private fun parseLineStyle(resId: Int): Line {
       val line = Line()
       val array = context.obtainStyledAttributes(resId, R.styleable.lineAppearance)
       line.color =
           array.getColor(
               R.styleable.lineAppearance_color,
               ContextCompat.getColor(context, R.color.color_d1d2)
           )
       line.height = array.getDimensionPixelOffset(R.styleable.lineAppearance_height, 0).toFloat()
       line.leftMargin =
           array.getDimensionPixelOffset(R.styleable.lineAppearance_leftMargin, 0).toFloat()
       line.rightMargin =
           array.getDimensionPixelOffset(R.styleable.lineAppearance_rightMargin, 0).toFloat()
       line.enable = array.getBoolean(R.styleable.lineAppearance_enable, false)

       array.recycle()
       return line
   }
   inner class Line {
       var color = 0
       var height = 0f
       var leftMargin = 0f
       var rightMargin = 0f;
       var enable: Boolean = false
   }
   @SuppressLint("CustomViewStyleable")
   private fun parseInputStyle(hint: String?, resId: Int, inputType: Int) {

       val array = context.obtainStyledAttributes(resId, R.styleable.inputTextAppearance)

       val hintColor = array.getColor(
           R.styleable.inputTextAppearance_hintColor,
           ContextCompat.getColor(context, R.color.color_d1d2)
       )
       val inputColor = array.getColor(
           R.styleable.inputTextAppearance_inputColor,
           ContextCompat.getColor(context, R.color.color_565)
       )
       //px
       val textSize = array.getDimensionPixelSize(
           R.styleable.inputTextAppearance_textSize,
           applyUnit(TypedValue.COMPLEX_UNIT_SP, 15f)
       )
       val maxInputLength = array.getInteger(R.styleable.inputTextAppearance_maxInputLength, 0)

       editText = EditText(context)
       if (maxInputLength > 0) {
           editText.filters = arrayOf(InputFilter.LengthFilter(maxInputLength))//最多可输入的字符数
       }
       editText.setPadding(0, 0, 0, 0)
       val params = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)
       params.weight = 1f
       editText.layoutParams = params
       editText.hint = hint
       editText.setTextColor(inputColor)
       editText.setHintTextColor(hintColor)
       editText.gravity = LEFT or (CENTER)
       editText.setBackgroundColor(Color.TRANSPARENT)
       editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize.toFloat())
       
       if (inputType == 0) {
           editText.inputType = InputType.TYPE_CLASS_TEXT
       } else if (inputType == 1) {
           editText.inputType =
               InputType.TYPE_TEXT_VARIATION_PASSWORD or (InputType.TYPE_CLASS_TEXT)
       } else if (inputType == 2) {
           editText.inputType = InputType.TYPE_CLASS_NUMBER
       }
       addView(editText)
       array.recycle()
   }
   @SuppressLint("CustomViewStyleable")
   private fun parseTitleStyle(title: String?, resId: Int) {
       val array = context.obtainStyledAttributes(resId, R.styleable.titleTextAppearance)
       val titleColor = array.getColor(
           R.styleable.titleTextAppearance_titleColor,
           resources.getColor(R.color.color_565)
       )
       //px
       val titleSize = array.getDimensionPixelSize(
           R.styleable.titleTextAppearance_titleSize,
           applyUnit(TypedValue.COMPLEX_UNIT_SP, 15f)
       )
       val minWidth = array.getDimensionPixelOffset(R.styleable.titleTextAppearance_minWidth, 0)

       titleView = TextView(context)
       titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize.toFloat())  //sp---当做sp在转换一次
       titleView.setTextColor(titleColor)
       titleView.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)
       titleView.minWidth = minWidth
       titleView.gravity = LEFT or (CENTER)
       titleView.text = title
       addView(titleView)
       array.recycle()
   }
   override fun onDraw(canvas: Canvas?) {
       super.onDraw(canvas)


       //巨坑
       if (topLine.enable) {
           canvas!!.drawLine(
               topLine.leftMargin,
               0f,
               measuredWidth - topLine.rightMargin,
               0f,
               topPaint
           )
       }

       if (bottomLine.enable) {
           canvas!!.drawLine(
               bottomLine.leftMargin,
               height - bottomLine.height,
               measuredWidth - bottomLine.rightMargin,
               height - bottomLine.height,
               bottomPaint
           )
       }
   }
   private fun applyUnit(applyUnit: Int, value: Float): Int {
       return TypedValue.applyDimension(applyUnit, value, resources.displayMetrics).toInt()
   }
   fun getTitleView(): TextView {
       return titleView
   }
   fun getEditText(): EditText {
       return editText
   }
}

到此这篇关于Android如何通过组合的方式自定义View的文章就介绍到这了,更多相关Android自定义View内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Android如何通过组合的方式自定义View

本文链接: https://www.lsjlt.com/news/167495.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Android如何通过组合的方式自定义View
    前言: 自定义View可以分为两种方式: 第一种通过继承ViewGroup,内部通过addView的方式将其他的View组合到一起。第二种则是通过继承View,重启View的onMe...
    99+
    2024-04-02
  • Android中View自定义组合控件的基本编写方法
    有很多情况下,我们只要运用好Android给我提供好的控件,经过布局巧妙的结合在一起,就是一个新的控件,我称之为“自定义组合控件”。 那么,这种自定义组合控件在什么情况下用呢?...
    99+
    2022-06-06
    view 方法 Android
  • Android通过自定义View实现随机验证码
    很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章。 一...
    99+
    2022-06-06
    view 验证码 自定义view Android
  • Android中怎么通过自定义View实现画圆
    Android中怎么通过自定义View实现画圆,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。引入布局<xml version="1.0...
    99+
    2023-05-30
    android
  • Android自定义View绘制的方法及过程(二)
    上一篇《Android 自定义View(一) Paint、Rect、Canvas介绍》讲了最基础的如何自定义一个View,以及View用到的一些工具类。下面讲下View绘制的方...
    99+
    2022-06-06
    view 方法 Android
  • Android中怎么通过自定义view实现TopBar效果
    这篇文章给大家介绍Android中怎么通过自定义view实现TopBar效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。布局文件<xml version="1.0" en...
    99+
    2023-05-30
    android view topbar
  • Android自定义组件:1、什么是自定义组件、自定义组件的方式、定义自定义属性
    声明:本教程不收取任何费用,欢迎转载,尊重作者劳动成果,不得用于商业用途,侵权必究!!! 目录 一、前言 二、什么是自定义组件 三、自定义组件的方式 1、组合现有组件 2、在某...
    99+
    2022-06-06
    属性 自定义属性 Android
  • Android自定义View的三种实现方式总结
    在毕设项目中多处用到自定义控件,一直打算总结一下自定义控件的实现方式,今天就来总结一下吧。在此之前学习了郭霖大神博客上面关于自定义View的几篇博文,感觉受益良多,本文中就参考...
    99+
    2022-06-06
    view Android
  • Android通过自定义view实现刮刮乐效果详解
    目录前言实现原理关键步骤创建bitmap绘制文字画路径完整代码前言 已经有两个月没有更新博客了,其实这篇文章我早在两个月前就写好了,一直保存在草稿箱里没有发布出来。原因是有一些原理性...
    99+
    2024-04-02
  • Android如何自定义View歌词控件
    本篇内容介绍了“Android如何自定义View歌词控件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录前言一、 歌词解析歌词实体类Lrc...
    99+
    2023-06-20
  • Android如何实现自定义View中attrs.xml
    这篇文章主要为大家展示了“Android如何实现自定义View中attrs.xml”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Android如何实现自定义View中attrs.xml”这篇文章...
    99+
    2023-05-30
    android view attrs.xml
  • Android中怎么通过自定义view实现动态柱状图
    这篇文章将为大家详细讲解有关Android中怎么通过自定义view实现动态柱状图,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。自定义viewpublic class Hi...
    99+
    2023-05-30
    android view
  • Android中怎么通过自定义View 实现QQ侧滑菜单
    这期内容当中小编将会给大家带来有关Android中怎么通过自定义View 实现QQ侧滑菜单,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。布局代码<fierce_luk.com.sideslipvie...
    99+
    2023-05-30
    android view
  • Android 通过自定义view实现水波纹效果案例详解
    在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她; 在这样的关键时候,身...
    99+
    2024-04-02
  • Android中怎么通过自定义View实现圆形切图效果
    本篇文章给大家分享的是有关Android中怎么通过自定义View实现圆形切图效果,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。实现思路使用一个Paint,将得到的Bitmap设...
    99+
    2023-05-30
  • Android自定义view绘制表格的方法
    本文实例为大家分享了Android自定义view绘制表格的具体代码,供大家参考,具体内容如下 先上效果图 平时很少有这样的表格需求,不过第一想法就是自定义view绘制表格,事实上我...
    99+
    2024-04-02
  • android中自定义view的方法有哪些
    在Android中,可以通过以下几种方式来自定义View:1. 继承View类:创建一个继承自View类的子类,并实现相应的绘制方法...
    99+
    2023-10-18
    android
  • vue3自定义hooks/可组合函数方式
    目录自定义hooks/可组合函数1.mixins方式的痛点2.传统mixins方式示例3.自定义hooks方式示例vue3(hooks)自定义hooks/可组合函数 vue3 com...
    99+
    2024-04-02
  • 怎么在Android中通过自定义View实现一个扫描效果
    这篇文章给大家介绍怎么在Android中通过自定义View实现一个扫描效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。自定义属性:<declare-styleable name="ScanV...
    99+
    2023-06-14
  • 怎么在Android中通过自定义view实现滑动解锁效果
    怎么在Android中通过自定义view实现滑动解锁效果?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。自定义view如下@SuppressLint("Clicka...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作