【问题标题】:Adjust layout to take a percentage of the screen调整布局以占据屏幕的百分比
【发布时间】:2023-03-29 10:26:01
【问题描述】:

如何让自定义视图只占据屏幕的 33% 并使其在每台设备上按比例显示?

这应该在下面的 xml 文件或自定义视图 kotlin 类中处理,因为它是库的一部分,我无权访问将托管我的自定义类的视图。

buff_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/mainLinearLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <include layout="@layout/buff_sender"/>
    <include layout="@layout/buff_question"/>

    <LinearLayout
        android:id="@+id/answersContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"/>

</LinearLayout>

buff_sender.xml

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:layout_marginBottom="4dp"
    android:orientation="horizontal">

    <LinearLayout

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/light_bg"
        android:orientation="horizontal"
        tools:ignore="RtlHardcoded">

        <ImageView
            android:id="@+id/sender_image"
            android:layout_width="27dp"
            android:layout_height="27dp"
            android:layout_gravity="center_vertical"
            android:padding="4dp" />

        <TextView
            android:id="@+id/sender_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:padding="4dp"
            tools:text="Praveen"
            android:textColor="@color/test_color_dark"
            android:textStyle="bold" />
    </LinearLayout>

    <androidx.appcompat.widget.AppCompatImageButton
        android:id="@+id/buff_close"
        android:layout_width="26dp"
        android:layout_height="26dp"
        android:layout_alignParentEnd="true"
        android:background="@drawable/ic_btn_close" />

</RelativeLayout>

buff_question.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/dark_bg"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/question_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|start"
        android:padding="18dp"
        android:textColor="@color/test_color_light"
        android:textStyle="bold"
        tools:text="Where do you think Jorge will put this penalty? I'd go left here! Hehehehehehehehehehe super long text" />

    <FrameLayout
        android:layout_width="32dp"
        android:layout_height="32dp">

        <ProgressBar
            android:id="@+id/question_time_progress"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:indeterminate="false"
            android:indeterminateDuration="1"
            android:max="100"
            android:progress="0" />

        <TextView
            android:id="@+id/question_time"
            android:layout_width="26dp"
            android:layout_height="26dp"
            android:layout_gravity="center"
            android:gravity="center"
            android:textColor="@color/test_color_light"
            android:textStyle="bold"
            tools:text="14" />

    </FrameLayout>

</LinearLayout>

buff_answer.xml(将根据该问题的可用答案数量动态地从 buff_view.xml 注入 answersContainer 中)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp"
    android:background="@drawable/light_bg"
    android:orientation="horizontal"
    tools:ignore="RtlHardcoded">

    <ImageView
        android:id="@+id/answer_image"
        android:layout_width="27dp"
        android:layout_height="27dp"
        android:layout_gravity="center_vertical"
        android:src="@drawable/ic_generic_answer"
        android:padding="4dp" />

    <TextView
        android:id="@+id/answer_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:padding="4dp"
        android:textColor="@color/test_color_dark"
        tools:text="The keeper's right"
        android:textStyle="bold" />
</LinearLayout>

BuffView.kt

class BuffView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
    : LinearLayout(context, attrs) {

    private val apiErrorHandler = ApiErrorHandler()
    private val getBuffUseCase = GetBuffUseCase(apiErrorHandler)

    private val intervalsHandler = Handler()

    private val buffView: LinearLayout = inflate(context, R.layout.buff_view, this) as LinearLayout

    private var errorListener: ErrorListener? = null

    private var countDownTimer: CountDownTimer? = null

    private var buffIdCount = 1

    private var getBuffs = false

    fun init() {
        getBuffs = true
        getBuff()
    }

    private fun getBuff() {
        if (!getBuffs) return
        getBuffUseCase.invoke(Params(buffIdCount.toLong()), object : UseCaseResponse<Buff> {
            override fun onSuccess(result: Buff) {
                displayBuff(result)
            }

            override fun onError(errorModel: ErrorModel?) {
                errorListener?.onError( errorModel?.message?: "An error has occurred")
                hideBuff()
            }
        })

        if (buffIdCount < TOTAL_BUFFS ) {
            intervalsHandler.postDelayed({
                buffIdCount++
                getBuff()
                stopCountDownTimer()
            }, REQUEST_BUFF_INTERVAL_TIME)
        }
    }

    private fun displayBuff(buff: Buff) {
        setQuestion(buff.question.title)
        setAuthor(buff.author)
        setAnswer(buff.answers)
        setProgressBar(buff.timeToShow)
        setCloseButton()
        invalidate()
        showBuff()
    }

    private fun setQuestion(questionText: String) {
        question_text.text = questionText
    }

    private fun setAuthor(author: Buff.Author) {
        val firstName = author.firstName
        val lastName = author.lastName
        sender_name.text = "$firstName $lastName"

        Glide.with(buffView)
            .load(author.image)
            .into(sender_image)
    }

    private fun setAnswer(answers: List<Buff.Answer>) {
        val answersContainer = findViewById<LinearLayout>(R.id.answersContainer)
        answersContainer.removeAllViews()
        for(answer in answers) {
            val answerView: View = LayoutInflater.from(answersContainer.context).inflate(
                R.layout.buff_answer,
                answersContainer,
                false
            )

            answer.answerImage?.x0?.url?.let {
                Glide.with(buffView)
                    .load(it)
                    .into(answerView.answer_image)
            }

            answerView.setOnClickListener {
                answerView.background = ContextCompat.getDrawable(context, R.drawable.answer_selected_bg)
                answerView.answer_text.setTextColor(ContextCompat.getColor(context, android.R.color.white))
                //freeze timer
                stopCountDownTimer()
                //hideView() after 2 seconds
                it.postDelayed(Runnable {
                    hideBuff()
                }, HIDE_BUFF_AFTER_SELECTED_ANSWER_DURATION)
            }

            answerView.answer_text?.text = answer.title
            answersContainer.addView(answerView)
        }
    }
...
}

【问题讨论】:

    标签: android xml android-layout kotlin


    【解决方案1】:

    您必须将 buff_view.xml 作为布局的子项包含在内,您可以在其中设置 layout_weight 属性,如下所示。

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:gravity="bottom">
    
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="horizontal">
    
            <include layout="@layout/buff_view">
            
        </LinearLayout>
    
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2" />
    
    </LinearLayout>
    

    还像这样更改 buff 视图顶部 LinearLayout 的宽度和高度约束

    <LinearLayout
        android:id="@+id/mainLinearLayout"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <include layout="@layout/buff_sender"/>
        <include layout="@layout/buff_question"/>
    
        <LinearLayout
            android:id="@+id/answersContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"/>
    
    </LinearLayout>
    

    编辑:进度条不可见问题

    我认为这是 TextView 的问题question_text

    这样改

    <TextView
        android:id="@+id/question_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_gravity="center_vertical|start"
        android:padding="18dp"
        android:textColor="@color/test_color_light"
        android:textStyle="bold" />
    

    同时更改 buff_question.xml 中的主布局并将其 layout_width 设置为 ma​​tch_parent 像这样

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/dark_bg"
        android:orientation="horizontal">
    

    【讨论】:

    • 感谢您的回答。这行得通,我发现的唯一问题是 buff_question.xml 文件中包含的进度条像这样不可见。关于如何修复它的任何想法?
    【解决方案2】:

    这很容易使用ConstraintLayout 和宽度/高度百分比来完成。 请务必将 实际 宽度尺寸设置为 0dp(使用百分比值)并确保视图受到适当限制。

    下面会产生这个输出

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    <View
        android:background="@color/salmon1"
        android:id="@+id/view1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent=".33"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
    <View
        android:background="@color/orange1"
        android:id="@+id/view2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/view1" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    【讨论】:

    • 感谢您的回答。不幸的是,我不能使用 ConstraintLayout。我的 buff_view 需要是一个 LinearLayout。
    • 为什么一定要LinearLayout?
    猜你喜欢
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多