zoukankan      html  css  js  c++  java
  • Android代码故事第一回,平均间隔的按钮

    我们的APP新做了一个放操作按钮的界面,老板要求简洁美观有内涵,按钮要均匀分布,于是参考之前的实现,设计MM给了一张图,像这样:

    |==============================================|

    |==========[Button]==========[Button]==========|

    |==========[Button]==========[Button]==========|

    |==============================================|

    当然设计MM给的是高清图片,这里只是示意一下。经过分析,需求应该是这样的:两个按钮需要排列在一行里,要求他们之间的间距、以及按钮和屏幕边缘的间距要相等,并且要撑满整个屏幕宽度。

    看来并不是什么难事,利用LinearLayout的特性,使用layout_weight使得占位View大小相同,如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true">
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"/>
    
            <ImageView
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:src="@drawable/record_start"
                android:gravity="center_horizontal"/>
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"/>
    
            <ImageView
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:src="@drawable/game"
                android:gravity="center_horizontal"
                />
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"/>
        </LinearLayout>
    </RelativeLayout>
    Android Layout XML

    效果图如下:

    虽然引入了占位View,不那么优雅,但看起来很完美。

    然而实际情况要复杂一点,每个按钮下面还有文字,添加上文字后效果如下:

    依然看起来很完美,然后问题来了,按下Play按钮之后,它就会变成另一个按钮"Play again":

    可以看到,两个按钮的位置与原来比有一点细微的偏差,因为第一个按钮由于字符串的变化而变宽了。之前没有考虑到按钮宽度不同的情况,他们之间的间距即使相等,也不会产生均匀分布的效果。但需要注意的是,按钮图片的宽度必须是相等的,否则无论如何都达不到均匀分布的视觉效果。

    于是需求重新定义:每个按钮的X轴中心要正好在整个屏幕的N分之一处,N=按钮数量+1。

    我们来研究一下用LinearLayout的weight能不能实现这个需求:

    显然之前使占位View宽度相等的方法是不可行的,想要利用weight,那么就要找到宽度的一种比例上的关系,按钮之间的间距并不是固定的,固定的是他们中心的间距。但LinearLayout中所有View都是线性排列的,并没有像RelativeLayout中两个子View之间的关系来实现两个View的相对居中。

    当然,有很多种复杂办法可以实现这个需求,比如用RelativeLayout在View绘制完成后,根据按钮的宽度和屏幕的宽度,用代码计算出margins值再设置给按钮;还可以自定义View计算出这个位置,这种方式应该是最正统的方式,但显得有些过于“小题大做”,并且定义一个有意义的自定义View并不是一件简单的事情。

    还是回到LinearLayout,想实现需求必须要解决居中的问题,居中其实是所有View都有的功能,View的gravity属性能实现内容的居中,那么怎么利用这个属性呢?想要让按钮老实地待在屏幕的三分之一处,只能让这个点正好是某个View的二分之一处,那么其实这是一个数学问题。

    假设按钮的图片宽度为w,屏幕宽度为W,间距长度L=(W-2w)/3,边缘的View宽度为L/2,而按钮实际宽度为L+w,于是两者的比例是(L/2):(L+w)。代入w=32dp,W=360dp,得到比例约等于5:13。于是代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:id="@+id/layout1"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_centerVertical="true">
    
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:background="#ffaa00"
                android:layout_weight="5"/>
    
            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:drawableTop="@drawable/ic_action_start"
                android:gravity="center_horizontal"
                android:layout_weight="13"
                android:background="#00ff80"
                android:text="Play again"/>
    
            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:drawableTop="@drawable/ic_action_stop"
                android:gravity="center_horizontal"
                android:layout_weight="13"
                android:background="#4490a0"
                android:text="Stop"/>
    
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:background="#ffaa00"
                android:layout_weight="5"/>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/layout2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/layout1"
            android:layout_centerVertical="true">
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"/>
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableTop="@drawable/ic_action_start"
                android:gravity="center_horizontal"
                android:text="Play"/>
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"/>
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableTop="@drawable/ic_action_stop"
                android:gravity="center_horizontal"
                android:text="Stop"/>
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1"/>
        </LinearLayout>
    </RelativeLayout>
    Android Layout XML
    效果对比:

    问题初步解决,可以忽悠老板了。问题本身并没有完美解决,因为安卓的碎片化,屏幕宽度并不一定是360dp,如果你以为是这样,会有各种奇葩的设备给你会心一击,这也是不能用写死margin的方法的原因。用了这个方法的代码真的能上线么,我们来考虑一下各种屏幕宽度的情况,将使W=[300, 400]代入公式,得到下面的表:

    其中按比例L/2就是weight=5的实际宽度,按比例L+w就是weight=13的实际宽度,偏差是按钮和屏幕的间距与两个按钮之间间距的差,反应了三等分的精确程度,可以看到偏差在屏幕宽度为300dp时仅仅是3dp左右。

    所以结论是,真的可以忽悠老板。

    当然,至此并没有完美解决问题,但用了最少的代码和时间达到了次优的效果,这个间距又不是生死功能,所以到此为止就算开发成功了。

    后来还发现一个好处,就是当一个按钮不可见,visibility设置为GONE的时候,正好另一个按钮可以居中显示。

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/ajeyone/p/5709446.html
Copyright © 2011-2022 走看看