Пользовательский вид не отображается в Android

#java #android #canvas #kotlin

#java #Android #холст #kotlin

Вопрос:

Я реализую пользовательскую кнопку для своего приложения Android, где должен быть только незаполненный круг. Я относительно новичок в этой части разработки Android, поэтому у меня возникли проблемы с этим.

Есть пользовательские атрибуты:

 <resources>
<declare-styleable name="CircleButton">
    <attr name="stroke_width" format="dimension"/>
</declare-styleable>
 

Код класса:

 class CircleButton (context: Context,
                attrs: AttributeSet) : View(context, attrs) {

val paint: Paint = Paint()

init {
    var a = context.theme.obtainStyledAttributes(attrs, R.styleable.CircleButton, 0, 0)
    paint.color = Color.RED
    try {
        paint.strokeWidth = a.getDimension(R.styleable.CircleButton_stroke_width, 3f)
    } finally {
        a.recycle()
    }
}

var centerX = x   width / 2
var centerY = y   height / 2
var radius = width / 2


override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)
   canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint)
}

override fun onMeasure(w : Int, h : Int) {
    setMeasuredDimension(w, w)
}
 

Это Kotlin, но я думаю, с ним все ясно. Но в любом случае я могу предоставить Java-код, если это необходимо.

Есть макет XML:

 <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    android:paddingBottom="@dimen/activity_vertical_margin">

<com.prox1mity.myapplication.CircleButton
    android:layout_width="250dp"
    android:layout_height="300dp"
    android:layout_centerInParent="true"
    custom:stroke_width="3dp"
/>
 

Когда я запускаю приложение, я вижу только белый экран, что означает, что метод onDraw не работает должным образом. Но если я меняю рисунок круга на простое заполнение холста цветом с помощью canvas.drawColor() «все в порядке», вид будет полностью заполнен. Это наводит меня на мысль, что что-то не так с моим Paint классом или моим неправильным пониманием системы координат. Как правильно нарисовать круг с центром в центре зрения?

Комментарии:

1. Хм, я не знаком с Kotlin, но если я правильно следую коду, вы хотите удалить x из centerX вычисления и y из centerY . То есть, var centerX = width / 2 , var centerY = height / 2 .

2. Ну, это не работает.

3. О, точно. Вы не хотите выполнять эти вычисления там. Там у View него будет 0 измерений. Переместите эти вычисления в его onSizeChanged() метод. Или даже в onDraw() , если вы просто хотите провести быстрый тест.

Ответ №1:

 var centerX = x   width / 2
var centerY = y   height / 2
var radius = width / 2
 

Этот код будет вычислен при инициализации экземпляра. И в этот момент width = 0 и height = 0. Потому что представление еще не измерено.

Вы можете добавить Log.d(...) точку останова или точку останова, onDraw и вы увидите, что radius = 0.

Для быстрого тестирования вы можете изменить onDraw на:

 override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)

   val centerX = width / 2
   val centerY = height / 2
   val radius = width / 2
   canvas.drawCircle(centerX.toFloat(), centerY.toFloat(), radius.toFloat(), paint)
}
 

Возможно, вы можете оптимизировать этот код. Делать выделения onDraw — не очень хорошая идея. Вы можете найти объяснение здесь.