在布局上水平传播按钮

时间:2012-02-03 15:04:31

标签: android android-layout android-widget

这是我在Stackoverflow上的第一篇文章。在我提出问题之前,我只想说这是一个很好的信息资源,我发现社区非常有帮助。 我希望能够与其他人分享我的Android开发知识。

我已经为Android开发了6个月了,虽然我学到了很多东西,但在布局/设计方面我仍然非常努力。

我有一个包含Relative布局的layout.xml文件。在这个布局中,我有三个按钮。我希望这三个按钮具有一定的宽度,根据设备的屏幕尺寸/密度增大或缩小。

这是xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout1123123213"
    android:layout_width="fill_parent"
    android:layout_height="@dimen/actionbar_height"
    android:orientation="horizontal">

    <Button
        android:id="@+id/btnLogin"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@drawable/button"
        android:drawableLeft="@drawable/balloon_overlay_close"
        android:gravity="center"
        android:text="Earned" />

    <Button
        android:id="@+id/btnLogin2"
        android:layout_width="113dp"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/btnLogin"
        android:background="@drawable/button"
        android:drawableLeft="@drawable/balloon_overlay_close"
        android:gravity="center"
        android:text="In Progress" />


     <Button
        android:id="@+id/btnLogin3"
        android:layout_width="107dp"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/btnLogin2"
        android:background="@drawable/button"
        android:drawableLeft="@drawable/balloon_overlay_close"
        android:gravity="center"
        android:text="Done" />

</RelativeLayout>

我对宽度值进行了硬编码,考虑到每个按钮都有不同的文字大小...所以这显然会影响宽度......

我的问题是......有没有明智的方法来实现这一目标?也许以编程方式,当我知道当前设备的屏幕尺寸时?

谢谢大家! 菲利普

=============================================== ===== 更新部分

嘿伙计们, 感谢您的帮助。

我根据建议添加了LinearLayout和重量,但我仍然没有得到我想要的东西。它几乎就在那里,但并不完全。

我的新xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="@dimen/actionbar_height"
android:orientation="horizontal"  
android:gravity="center" android:weightSum="1">

    <Button
        android:id="@+id/btnLogin"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@drawable/button"
        android:drawableLeft="@drawable/balloon_overlay_close"
        android:gravity="center"
        android:text="@string/bottonbar_earned" 
        android:layout_weight=".10"/>

    <Button
        android:id="@+id/btnLogin2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight=".10"
        android:background="@drawable/button"
        android:drawableLeft="@drawable/balloon_overlay_close"
        android:gravity="center"
        android:text="@string/bottonbar_inprogress" />


     <Button
        android:id="@+id/btnLogin3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@drawable/button"
        android:drawableLeft="@drawable/balloon_overlay_close"
        android:gravity="center" android:text="@string/bottonbar_redeemed"
        android:layout_weight=".90"/>

</LinearLayout>

这是结果link 你能看到右边的结局吗?虽然我在第三个按钮上设置了0.90的重量,但我不认为重量是按照它应该分配的。 你们觉得怎么样?

4 个答案:

答案 0 :(得分:6)

您可以执行的操作是在按钮上使用android:layout_weight属性,但您需要将它们放入LinearLayout。如果您需要RelativeLayout,则可以将LinearLayout放入其中。

<LinearLayout
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:weightSum="1.0" >
    <Button
        android:text="left" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_weight=".30" /> 

    <Button
        android:text="center" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_weight=".40" />

    <Button
        android:text="right" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_weight=".30" />
</LinearLayout>

答案 1 :(得分:3)

如果您可以在xml本身中执行此操作,我建议不要以编程方式执行此操作。您可以添加以下内容:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"  
    android:gravity="center" style="android:style/ButtonBar" >
      <Button android:text="Ok" android:id="@+id/bookOkBtn"
              android:layout_width="0dp" android:layout_height="wrap_content" 
              android:layout_weight="1" android:layout_marginRight="10dp" />

      <Button android:text="Return" android:id="@+id/bookReturnBtn" 
             android:layout_width="0dp" android:layout_height="wrap_content" 
             android:layout_weight="1"/>
 </LinearLayout>

制作android:layout_width =“0”&amp; android:layout_weight = 1使用所有可用的空间宽度。

如果您还需要按高度计算,请在android:layout_height="100dip"中指定dip并检查所需的高度。

如果这也不符合您的需求,动态设置只是解决方案,那么也为此添加了答案。

更新: 看看这段代码:

    <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content" 
android:orientation="horizontal"  android:gravity="center" 
android:layout_marginTop="15dp" style="android:style/ButtonBar">
    <Button android:id="@+id/browseAddBtn" android:text="Add" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp" />
    <Button android:id="@+id/browseViewBtn" android:text="Edit" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp"  />
    <Button android:id="@+id/browseDelBtn" android:text="Delete" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginRight="10dp"  />
    <Button android:id="@+id/browseReturnBtn" android:text="Return" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" />        
</LinearLayout>

结果Click Here

图像显示了上述代码的结果,也分别显示了文件中提到的更改layout_weight的结果。我的父布局也是LinearLayout&amp;没有设置填充或边距。

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" android:orientation="vertical">

答案 2 :(得分:2)

这听起来更像LinearLayout而不是RelativeLayout。如果您指定LinearLayout为父级,总布局权重为3,并且每个Buttons指定的布局权重为1,那么它们应该在任何屏幕上完全按照您的需要结束。

答案 3 :(得分:1)

我有同样的情况,我必须根据屏幕尺寸和密度设置按钮的大小。我根据我得到的应用程序的实际空间计算按钮的大小。

我建议您使用LinearLAyout而不是RelativeLayout,但是由于您有一些经验,您必须了解使用Linear而不是Relative布局的差异和易用性。

在我的XML中,我有根LinearLayout&amp; 2内部LinearLayout(row1&amp; row2)。每行有3个but .. 在我的onCreate中,我使用findViewById获得了3个以上。

使用LayoutParams和屏幕的大小和凹凸,我计算按钮和文字大小的大小。 算法:

  1. 获取屏幕高度&amp;宽度
  2. 扣除填充物&amp;您使用的保证金
  3. 标题栏的扣除高度
  4. 现在,您已获得全部可用空间。将它水平分开&amp;根据需要垂直
  5. 这将为您提供1个按钮的大小
  6. 为所有按钮设置相同的尺寸
  7. 基于按钮宽度&amp;高度和密度计算出文字大小
  8. 你可以启动这个,如果你需要帮助,我会在那里。随意问。

    更新:已添加代码: -

    这些方法添加到名为“Utility”的类中,并使其成为静态以轻松访问整个项目中的方法:

          public static ScreenInfo scrnInfo = new ScreenInfo();
    
    public static void calculateChildSize(LinearLayout root, LinearLayout.LayoutParams row1Params, LinearLayout.LayoutParams row2Params, DisplayMetrics metrics) {
        int height, width;
        int childWidth, childHeight;
    
        //gets screen dimensions 
        height = metrics.heightPixels;  //480
        width = metrics.widthPixels;    //320
        scrnInfo.setScreenHeight(height);
        scrnInfo.setScreenWidth(width);
    
        //Log.i("MY", "Actual Screen Height = " + height + " Width = " + width);
        // Get height/width after deducting Padding of all 4 sides
        height = height - (root.getPaddingBottom() + root.getPaddingTop()); // 480-70
        width = width - (root.getPaddingLeft() + root.getPaddingRight());   // 320-70
        //Log.i(TAG, "Actual Area after Padding W = " + width + " H = " + height);
    
        int bottomMargin = row1Params.bottomMargin; //15
        bottomMargin = (row1Params.bottomMargin %2) == 0 ? row1Params.bottomMargin : row1Params.bottomMargin+1;
    
        // Actual Height/Width of child
        childWidth = (int)(width);
        childHeight = (int)(height /2) - (bottomMargin/2);  
    
        childHeight -= scrnInfo.getTitleBarHeight();    
        scrnInfo.setRowHeight(childHeight);
    
        row1Params.height = childHeight;
        row1Params.width = childWidth;
        row1Params.bottomMargin = (bottomMargin/2);
    
        row2Params.height = childHeight;
        row2Params.width = childWidth;
        row2Params.topMargin = (bottomMargin/2);
    
        scrnInfo.setChild1LayoutParams(row1Params);
        scrnInfo.setChild2LayoutParams(row2Params);
    
        calcTileWidthHeight(childWidth);
        calcTileTextSize();
        //android.util.Log.i(TAG, "Child W = " + childWidth + " H = " + childHeight + " Tile W = " + scrnInfo.getTileWidth() + " Tile Text Size = " + getTileTextSize());
    
        return;
    }
    
    public static void calcTileWidthHeight(int childWidth) {
        int margin = 8;
        scrnInfo.setTileWidth(((childWidth/3)-margin));
    }
    
    public static void findTitleBarHeight(Window win) {
        Rect rect = new Rect();
        win.getDecorView().getWindowVisibleDisplayFrame(rect);
        int statusHeight = rect.top;
        int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
        int titleHeight = contentViewTop - statusHeight;
    
        scrnInfo.setTitleBarHeight(titleHeight);    // SET TitleBarHeight
        //Log.i(Utility.TAG, "titleHeight = " + titleHeight + " statusHeight = " + statusHeight + " contentViewTop = " + contentViewTop);
    
        return;
    }
    
    public static void calcTileTextSize() {
        // current is 11 on W = 75 => its small
        int w = scrnInfo.getTileWidth();
        float ts = 11f;
    
        if (w >= 51 && w <= 70) // Port LDPI W - 54 H -98
            ts = 15f;
        // Screen 320 * 480 Medium dense
        else if (w >= 71 && w <= 80)    // Port MDPI 
            ts = 13f;
        else if (w >= 81 && w <= 110)   // Land LDPI W - 81 H - 58
            ts = 15f;
        else if (w >= 111 && w <= 220)  // Landscape - Perfect
            ts = 18f;
        else if (w >= 221 && w <= 250)
            ts = 20f;
        setTileTextSize(ts);        
    }
    

    ScreenInfo类包含以下成员的setter / getters:

    public class ScreenInfo {
    private int titleBarHeight, screenHeight, screenWidth;
    private int rowHeight;
    private LinearLayout.LayoutParams child1LayoutParams, child2LayoutParams;
    private int _6tiles_Width;  // Width of a Tile where 3 tiles on 2rows r shown
    

    NOW在Activity中实际实现:

        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.datapage);
    
       root = (LinearLayout) findViewById(R.id.dataroot);
       row1 = (LinearLayout) findViewById(R.layout.datarow1); 
       row2 = (LinearLayout) findViewById(R.layout.datarow2);
    
        btn1 = (Button) findViewById(R.id.relationBtn);
        btn2 = (Button) findViewById(R.id.productBtn);
        btn3 = (Button) findViewById(R.id.bankBtn);
        btn4 = (Button) findViewById(R.id.locationBtn);
        btn5 = (Button) findViewById(R.id.curencyBtn);
        btn6 = (Button) findViewById(R.id.dataReturnBtn);       
    
        root.post(new Runnable() {
            public void run() {
                Utility.findTitleBarHeight(getWindow());
    
                // CALCULATE THE SIZE OF INNER LAYOUTS
                //calculateChildSize();
                LinearLayout.LayoutParams row1Params = (android.widget.LinearLayout.LayoutParams) row1.getLayoutParams();
                LinearLayout.LayoutParams row2Params = (android.widget.LinearLayout.LayoutParams) row2.getLayoutParams();
    
                DisplayMetrics metrics = new DisplayMetrics();
                getWindowManager().getDefaultDisplay().getMetrics(metrics);
                Utility.calculateChildSize(root, row1Params, row2Params, metrics);
    
                row1.setLayoutParams(Utility.scrnInfo.getChild1LayoutParams());
                row2.setLayoutParams(Utility.scrnInfo.getChild2LayoutParams());
    
                RefreshComponents();
            }
        });             
    }
    
    protected void RefreshComponents() {
        // Set background of the root 
        root.setBackgroundColor(Utility.getBackgroundColor());
        // set Gradient Colors & text color of all buttons
        RefreshGradientButtons();
    }
    
    protected void RefreshGradientButtons() {
        GradientDrawable btnGradient = Utility.getButtonDrawable(); 
        int i = -1;
        for(i=0; i < row1.getChildCount(); i++) {
            Button btn = (Button)row1.getChildAt(i);
            btn.setBackgroundDrawable(btnGradient);
            btn.setTextColor(Utility.getTextColor());
            btn.setTextSize(Utility.getTileTextSize());
        }
    
        for(i=0; i < row2.getChildCount(); i++) {
            Button btn = (Button)row2.getChildAt(i);
            btn.setBackgroundDrawable(btnGradient);
            btn.setTextColor(Utility.getTextColor());
            btn.setTextSize(Utility.getTileTextSize());
        }       
    }
    

    每当屏幕从纵向更改为横向或反之亦然或者如果在运行时更改了所有密度,则每次调用onCeate。因此,此代码添加在onCreate()中,因此计算和设置可以适当地在现场进行。

    在我的应用程序中,这就像1.5到3.2版本中的魅力和所有密度一样。

    您必须相应地更改您的要求。由于您的设计只是连续3个按钮,而我上面代码的设计就像屏幕上的Tiles。每行2行n 3个按钮。我保留了我添加的日志,因为它可以帮助您调试并找出解决方案。

    这将100%工作。

    *我仍然建议尝试:只需创建一个新的xml并在LinearLayout中作为父级,添加你的LinearLayout按钮并查看。那样有用吗 ?执行时在两种模式下都可以尝试。在LinearLayout中尝试删除weightSum。据我所知,这个要求应该在xml本身中实现。 *

    BEST LUCK。