Android 基础布局优化

113 阅读5分钟

Android UI 布局优化

背景

最近工作需要维护一个比较旧的项目、功能也比较简单,用到的技术栈也比较旧了。项目不是很紧急,现学现卖 Kotlin 重写走起。

其中有一个功能需要选择画笔的颜色以及大小,展示的时候需要显示当前画笔的状态。看到布局文件脑子有点大,做了好多级的嵌套(可能这个项目创建之前都没有约束布局)。一个选项竟然是通过一层相对布局包含View。相对布局负责边框颜色变化,View负责内容展示。

捕获.PNG

布局嵌套过多,首先想到的就是可以用约束布局优化。想到的方案是一个选项可以通过一个ImageView 展示,通过代码设置它们的background或者src

<RelativeLayout
        android:layout_width="298.6dp"
        android:layout_height="190.6dp"
        android:background="@drawable/shadow_3">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="27.3dp"
            android:orientation="horizontal">

            <RelativeLayout
                android:id="@+id/color_r_1"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="@drawable/shape_pen_color_sel">

                <View
                    android:id="@+id/color_v_1"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/shape_pen_color" />

            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/color_r_2"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="14.6dp"
                android:background="@drawable/shape_pen_color_sel">

                <View
                    android:id="@+id/color_v_2"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/shape_pen_color"
                    android:backgroundTint="@color/white" />

            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/color_r_3"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="14.6dp"
                android:background="@drawable/shape_pen_color_sel">

                <View
                    android:id="@+id/color_v_3"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/shape_pen_color"
                    android:backgroundTint="@color/blue" />

            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/color_r_4"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_marginLeft="14.6dp"
                android:background="@drawable/shape_pen_color_sel">

                <View
                    android:id="@+id/color_v_4"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_centerInParent="true"
                    android:backgroundTint="@color/black"
                    android:background="@drawable/shape_pen_color" />

            </RelativeLayout>

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="99.3dp"
            android:orientation="horizontal">

            <RelativeLayout
                android:id="@+id/size_r_1"
                android:layout_width="56dp"
                android:layout_height="56dp"
                android:background="@drawable/shape_pen_color">

                <View
                    android:layout_width="11dp"
                    android:layout_height="11dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/shape_pen_size" />

            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/size_r_2"
                android:layout_width="56dp"
                android:layout_height="56dp"
                android:layout_marginLeft="31.3dp"
                android:background="@drawable/shape_pen_color">

                <View
                    android:layout_width="19dp"
                    android:layout_height="19dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/shape_pen_size" />

            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/size_r_3"
                android:layout_width="56dp"
                android:layout_height="56dp"
                android:layout_marginLeft="31.3dp"
                android:background="@drawable/shape_pen_color">

                <View
                    android:layout_width="28dp"
                    android:layout_height="28dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/shape_pen_size" />

            </RelativeLayout>

        </LinearLayout>

    </RelativeLayout>

优化后的布局。(约束布局真的好用)

<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/group"
        android:layout_width="150dp"
        android:layout_height="95dp"
        android:background="@drawable/shadow_3">

        <ImageView
            android:id="@+id/color_r_1"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginTop="14dp"
            app:layout_constraintHorizontal_chainStyle="spread"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/color_r_2"
            app:layout_constraintTop_toTopOf="parent"
            />

        <ImageView
            android:id="@+id/color_r_2"
            android:layout_width="24dp"
            android:layout_height="24dp"
            app:layout_constraintLeft_toRightOf="@+id/color_r_1"
            app:layout_constraintRight_toLeftOf="@+id/color_r_3"
            app:layout_constraintTop_toTopOf="@+id/color_r_1" />

        <ImageView
            android:id="@+id/color_r_3"
            android:layout_width="24dp"
            android:layout_height="24dp"
            app:layout_constraintLeft_toRightOf="@+id/color_r_2"
            app:layout_constraintRight_toLeftOf="@+id/color_r_4"
            app:layout_constraintTop_toTopOf="@+id/color_r_1" />

        <ImageView
            android:id="@+id/color_r_4"
            android:layout_width="24dp"
            android:layout_height="24dp"
            app:layout_constraintLeft_toRightOf="@+id/color_r_3"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="@+id/color_r_1" />


        <ImageView
            android:id="@+id/size_r_1"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:scaleType="center"
            android:layout_marginTop="50dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/size_r_2"
            app:layout_constraintTop_toTopOf="parent"
            />

        <ImageView
            android:id="@+id/size_r_2"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:scaleType="center"
            app:layout_constraintLeft_toRightOf="@+id/size_r_1"
            app:layout_constraintRight_toLeftOf="@+id/size_r_3"
            app:layout_constraintTop_toTopOf="@+id/size_r_1" />

        <ImageView
            android:id="@+id/size_r_3"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:scaleType="center"
            app:layout_constraintLeft_toRightOf="@+id/size_r_2"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="@+id/size_r_1" />

    </androidx.constraintlayout.widget.ConstraintLayout>

GradientDrawable在Android中便是shape标签的代码实现,利用GradientDrawable也可以创建出各种形状。我们直接在代码里面设置我们需要的 shape。设置画笔颜色ImageView直接设置background就可以了。设置画笔的大小我们可以创建一个有具体宽高的形状为圆形的 shapeImageView 设置此为src。创建一个背景颜色为白色、边框有颜色形状为矩形shapeImageView 设置此为background

class MainActivity2 : AppCompatActivity() {

    private lateinit var binding: PenTypeLayoutCopyBinding

    private val color = arrayOf(
        Color.parseColor("#ffffff"),
        Color.parseColor("#fdd02f"),
        Color.parseColor("#000000"),
        Color.parseColor("#157efb")
    )

    private val strokeNormalColor: Int = Color.parseColor("#cccccc")  //边框默认颜色
    private val strokeSelectedColor: Int = Color.parseColor("#3b73b5")  //边框选中颜色

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = PenTypeLayoutCopyBinding.inflate(layoutInflater)
        setContentView(binding.root)
            
        //默认选择第一个
        setPenColor(0)  
        setPenWidth(4)
        binding.colorR1.setOnClickListener {
            setPenColor(0)
        }
        binding.colorR2.setOnClickListener {
            setPenColor(1)
        }
        binding.colorR3.setOnClickListener {
            setPenColor(2)
        }
        binding.colorR4.setOnClickListener {
            setPenColor(3)
        }
        binding.sizeR1.setOnClickListener {
            setPenWidth(4)
        }
        binding.sizeR2.setOnClickListener {
            setPenWidth(5)
        }
        binding.sizeR3.setOnClickListener {
            setPenWidth(6)
        }
    }

    //画笔颜色是从第1个选项开始
    private fun setPenColor(position: Int) {
        for (i in 0 until 4) {
            val drawable = GradientDrawable()
            drawable.shape=GradientDrawable.RECTANGLE
            drawable.setColor(color[i])
            val color = if (i == position) strokeSelectedColor else strokeNormalColor
            drawable.setStroke(3, color)
            drawable.cornerRadius = 6.0f
            binding.group.getChildAt(i).background = drawable
        }
    }

    //画笔大小是从第五个选项开始
    private fun setPenWidth(position: Int) {
        for (i in 4 until binding.group.childCount) {
            val drawable = GradientDrawable()
            drawable.shape = GradientDrawable.OVAL
            drawable.cornerRadius = 6.0f
            drawable.setSize(4 * i, 4 * i)
            drawable.setColor(Color.parseColor("#4a4a4a"))
            val imageView = binding.group.getChildAt(i) as ImageView
            imageView.setImageDrawable(drawable)
            val drawable1 = GradientDrawable()
            drawable1.shape=GradientDrawable.RECTANGLE
            drawable1.setColor(Color.WHITE)
            drawable1.cornerRadius = 6.0f
            val color = if (i == position) strokeSelectedColor else strokeNormalColor
            drawable1.setStroke(3, color)
            imageView.background = drawable1
        }
    }

}

踩坑地方:ImageView 需要设置 android:scaleType="center" ,这表示在视图中居中图像,但不执行缩放。不设置这个的话ImageView 设置 src 肯能会铺满 ImageView ,得不到我们想要的效果。比如:

捕获1.PNG

欢迎大家提出不同的想法、建议。