Как создать дугу сплошным цветом на фоне Android в портретном и альбомном режиме

#android #android-drawable

Вопрос:

Мой текущий пользовательский интерфейс приложения для Android требует двухцветного фона с изогнутой дугой в качестве границы, как показано на следующем рисунке

введите описание изображения здесь

Я могу добиться этого эффекта в портрете (хотя мне не нравится использовать отрицательные значения полей) следующим образом…

     <ImageView
        android:id="@ id/backgroud_arc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="-150dp"
        android:layout_marginEnd="-150dp"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:src="@drawable/background_circle" />
 

где окружность фона — это нарисованная фигура

 <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/background" />
    <size
        android:width="120dp"
        android:height="60dp" />
    <corners
        android:bottomLeftRadius="60dp"
        android:bottomRightRadius="60dp" />
</shape>
 

Есть ли более простой метод, который я могу использовать для достижения желаемого эффекта?

В пейзаже этот рисунок очень плохо «обрезан».

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

1. Вы можете использовать векторную графику для ваших желаемых дизайнов.

Ответ №1:

Вместо того, чтобы использовать негибкий рисоваемый фон, мы должны рисовать цвета вместе с кривой на холсте.

Для этого мы создаем пользовательский вид ArcBackgroundView , как показано ниже. Код не требует пояснений:

 import android.content.Context
import android.content.res.Configuration
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat

class ArcBackgroundView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    private val paint = Paint()
    private val path = Path()

    init {
        paint.isAntiAlias = true
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (canvas == null) {
            return
        }
        // Draw background color
        canvas.drawColor(ContextCompat.getColor(context, R.color.blue))

        // Draw curve portion of background
        // Setup color
        paint.color = ContextCompat.getColor(context, R.color.white)

        val curveStartAndEndY = 0.6f * measuredHeight // <------ You can change this value based on your requirement
        // Set curve's control point's Y position (downwards bulge of curve) based on orientation
        var curveControlPointY = measuredHeight / 1.4f // <------ You can change this value based on your requirement
        if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // Since in landscape mode, the curve will have greater arc length,
            // we need to give the curve more downwards bulge as compared to that in portrait mode.
            curveControlPointY = measuredHeight / 1.2f // <------ You can change this value based on your requirement
        }
        // Now we draw the entire path for curve
        path.moveTo(0f, curveStartAndEndY)
        path.quadTo(
            measuredWidth / 2f,
            curveControlPointY,
            measuredWidth.toFloat(),
            curveStartAndEndY
        )
        path.lineTo(measuredWidth.toFloat(), 0f)
        path.lineTo(0f, 0f)
        path.lineTo(0f, curveStartAndEndY)
        canvas.drawPath(path, paint)
    }
}
 

Теперь ArcBackgroundView его можно использовать в формате xml, как показано ниже:

 <FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.myapp.ArcBackgroundView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
 

Результирующие выходные данные для портретной и альбомной ориентации показаны ниже:

введите описание изображения здесь

введите описание изображения здесь

Помимо создания пользовательского представления, как показано на рисунке, при необходимости вы также можете создать, скажем, пользовательский FrameLayout вызов ArcBackgroundFrameLayout . Скопируйте и вставьте код onDraw() в свой ArcBackgroundFrameLayout's onDraw() . Теперь вы можете использовать свой пользовательский контейнер напрямую, как показано ниже:

 <?xml version="1.0" encoding="utf-8"?>
<com.example.myapp.ArcBackgroundFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@color/teal_200"
        android:gravity="center"
        android:text="THIS IS A TEXT VIEW ON TOP OF THE DUAL TONE BACKGROUND"
        android:textSize="28sp"
        android:textStyle="bold" />
</com.example.myapp.ArcBackgroundFrameLayout>
 

Обратите внимание на android:background="@color/black" добавленное с ArcBackgroundFrameLayout помощью . Необходимо добавить некоторый фон (не обязательно черного цвета), иначе для контейнеров не вызывалась бы функция #onDraw (). Вам не следует беспокоиться об этом черном цвете, так как он не будет отображаться. Мы меняем цвета фона изнутри нашего переопределенного onDraw() .

Результирующие выходные данные для портретной и альбомной ориентации показаны ниже:

введите описание изображения здесь

введите описание изображения здесь

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

Код находится в Котлине. Если ваш проект на Java, пожалуйста, дайте мне знать еще раз. Я могу отредактировать и дать Java-версию того же самого.

Спасибо.