📌  相关文章
📜  如何使用 Kotlin 在 Android 中创建自己的自定义视图?

📅  最后修改于: 2022-05-13 01:54:53.573000             🧑  作者: Mango

如何使用 Kotlin 在 Android 中创建自己的自定义视图?

在本文中,我们将逐步讨论如何在 Android 中创建我们自己的自定义视图。我们都知道一开始 android 平台为我们提供了一些基本的视图,例如——TextView、ImageView、EditText、Button、ImageButton、RadioButton 等。但是,有时我们需要一种全新类型的视图,而我们的预建布局和小部件却无法满足我们的需求。所以,让我们深入了解一下。

什么是 Android 中的自定义视图?

首先,Android 中自定义视图的概念无非就是拥有我们自己的自定义视图模型,而不是预先构建的视图模型。我们如何实现这一目标?通过简单地将不同类型的预构建视图组合在一起,然后将组合的视图用作单个视图。

为什么我们甚至需要在我们的应用程序中使用它们?

我们都知道一开始 android 平台为我们提供了一些基本的视图,例如——TextView、ImageView、EditText、Button、ImageButton、RadioButton 等。但是,有时我们需要一个更具交互性和复杂性的视图类型,其中我们的预建布局和小部件无法满足我们的需求。自定义视图出现在图片中。现在 Android 中的自定义视图完全由开发人员自定义以实现目标。尽管并非到处都需要自定义视图。但是,在复杂性更高的更高开发级别,我们需要它们。

我们将如何创建我们自己的自定义视图?

每当我们要为我们的应用程序创建自定义视图时,我们都需要考虑一些项目。向自己介绍 Android 中视图的生命周期。



现在,要重视 3 种基本方法。

  1. 测量()
  2. 布局()
  3. 绘制()

这 3 个方法将在相应的Java/Kotlin 类中被覆盖。

1. onMeasure() 方法

正如方法名称所暗示的那样,它用于测量目的。基本上,我们可以控制自定义视图的宽度和高度。

  • 如果未被覆盖:视图的大小将为“match_parent”或“wrap_content”。
  • 如果被覆盖:在覆盖此方法时,我们可以更好地控制自定义视图的大小。不要调用方法'super.onMeasure()' 。相反,我们将调用方法“setMeasuredDimension(width, height)”。

覆盖 onMeasure():

当这个方法被调用时,我们得到'widthMeasureSpec''heightMeasureSpec'作为参数。大小模式是由父级为其子级视图设置的约束。下面列出了可用的 3 种模式。

  • UNSPECIFIED:没有给出任何限制,所以它可以是它想要的任何大小。
  • EXACTLY:确定子视图的确切大小。
  • AT_MOST:子项可以根据需要达到指定大小。

例子:

Kotlin
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  
          // requested width and mode
        val reqWidth = MeasureSpec.getSize(widthMeasureSpec)
        val reqWidthMode = MeasureSpec.getMode(widthMeasureSpec)
  
        // requested height and mode
        val reqHeight = MeasureSpec.getSize(heightMeasureSpec)
        val reqHeightMode = MeasureSpec.getMode(heightMeasureSpec)
  
        // your choice
        val desiredWidth: Int =  // TODO("Define your desired width")
        val desiredHeight: Int = // TODO("Define your desired height")
  
        val width = when (requestedWidthMode) {
            MeasureSpec.EXACTLY -> reqWidth
            MeasureSpec.UNSPECIFIED -> desiredWidth
            else -> Math.min(reqWidth, desiredWidth) // AT_MOST condition
        }
  
        val height = when (requestedHeightMode) {
            MeasureSpec.EXACTLY -> reqHeight
            MeasureSpec.UNSPECIFIED -> desiredHeight
            else -> Math.min(reqHeight, desiredHeight) // AT_MOST condition
        }
  
        // set the width and the height of the view
        setMeasuredDimension(width, height)
}


Kotlin
protected fun onDraw(canvas:Canvas) {
  // Grab canvas dimensions.
  val canvasWidth = canvas.getWidth()
  val canvasHeight = canvas.getHeight()
  // Calculate horizontal center.
  val centerX = canvasWidth * 0.5f
  // Draw the background.
  backgroundRect.set(0f, 0f, canvasWidth, canvasHeight)
  canvas.drawRoundRect(backgroundRect, cornerRadius, cornerRadius, backgroundPaint)
  // Draw baseline.
  val baselineY = Math.round(canvasHeight * 0.6f).toFloat()
  canvas.drawLine(0, baselineY, canvasWidth, baselineY, linePaint)
  // Draw text.
  
  // Measure the width of text to display.
  val textWidth = numberPaint.measureText(displayedCount)
  // Figure out an x-coordinate that will center the text in the canvas.
  val textX = Math.round(centerX - textWidth * 0.5f).toFloat()
  // Draw.
  canvas.drawText(displayedCount, textX, baselineY, numberPaint)
}


2. onLayout() 方法

父视图使用此方法通知我们的自定义视图其位置。人们应该使用它来计算他们的绘图宽度和高度。要记住onMeasure() 中发生的任何事情都会影响从父级获得的位置。建议在继续绘制视图之前始终在此处计算图纸尺寸。

3. onDraw() 方法

所有的绘图都发生在这部分内。这一点都不难,因为你得到了一个 Canvas 对象的实例,你可以随意绘制任何你想要的东西。

覆盖 onDraw() :

首先为简单起见,使用'getWidth()''getHeight()'方法获取画布对象的宽度和高度。

例子:

科特林

protected fun onDraw(canvas:Canvas) {
  // Grab canvas dimensions.
  val canvasWidth = canvas.getWidth()
  val canvasHeight = canvas.getHeight()
  // Calculate horizontal center.
  val centerX = canvasWidth * 0.5f
  // Draw the background.
  backgroundRect.set(0f, 0f, canvasWidth, canvasHeight)
  canvas.drawRoundRect(backgroundRect, cornerRadius, cornerRadius, backgroundPaint)
  // Draw baseline.
  val baselineY = Math.round(canvasHeight * 0.6f).toFloat()
  canvas.drawLine(0, baselineY, canvasWidth, baselineY, linePaint)
  // Draw text.
  
  // Measure the width of text to display.
  val textWidth = numberPaint.measureText(displayedCount)
  // Figure out an x-coordinate that will center the text in the canvas.
  val textX = Math.round(centerX - textWidth * 0.5f).toFloat()
  // Draw.
  canvas.drawText(displayedCount, textX, baselineY, numberPaint)
}
想要一个更快节奏和更具竞争力的环境来学习 Android 的基础知识吗?
单击此处前往由我们的专家精心策划的指南,旨在让您立即做好行业准备!