Изящно растягивая кнопки горизонтально по макету - PullRequest
1 голос
/ 03 февраля 2012

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

Я занимаюсь разработкой для Android уже 6 месяцев и, хотя я многому научился, я все еще испытываю большие трудности, когда дело касаетсяlayout / design.

У меня есть один файл 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>

Это результат ссылка Вы видите конец правой стороны?Я не думаю, что вес распределяется так, как должен, хотя я установил вес 0,90 для третьей кнопки.Что вы, ребята, думаете?

Ответы [ 4 ]

6 голосов
/ 03 февраля 2012

Что вы можете сделать, это использовать атрибут 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>
3 голосов
/ 03 февраля 2012

Если бы вы могли сделать это в самом 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" & ​​android: layout_weight = 1 использует всю доступную ширину пространства.

Если вы также хотите увеличить высоту, укажите погружение в android:layout_height="100dip" и проверьте желаемую высоту.

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

ОБНОВЛЕНО: Посмотрите на этот код:

    <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 и не имеет отступов или полей.

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" android:orientation="vertical">
2 голосов
/ 03 февраля 2012

Это больше похоже на случай LinearLayout, чем RelativeLayout. Если вы укажете LinearLayout в качестве родительского элемента с общим весом макета 3 и каждый из ваших Buttons задает вес макета 1, они должны получиться точно так, как вы хотите на любом экране.

1 голос
/ 03 февраля 2012

У меня была такая же ситуация, когда мне приходилось устанавливать размеры кнопок в зависимости от размеров экрана и плотности. Я рассчитываю размер кнопок на основе фактического пространства для приложения, которое я получаю.

Я бы предложил вам использовать LinearLAyout вместо RelativeLayout, но, поскольку у вас есть некоторый опыт, вы должны знать о различиях и простоте использования с линейными, а не с относительными макетами.

В моем XML у меня есть root LinearLayout & 2 inner LinearLayout (row1 & row2). Каждый ряд имеет 3 кнопки. В моем onCreate я получаю более 3 из них, используя findViewById.

Используя LayoutParams, размер и плотность экрана, я вычисляю размер кнопок и размеры текста. Алгоритм:

  1. Получить высоту экрана и ширину
  2. Вычтите отступы и поля, которые вы используете
  3. Высота удержания строки заголовка
  4. Теперь у вас есть все свободное место. Разделите его по горизонтали и вертикали, как вам нужно
  5. Это даст вам размер 1 кнопки
  6. Установить одинаковый размер для всех кнопок
  7. На основе ширины кнопок, высоты и плотности определить размер текста

Вы можете начать с этого, если вам понадобится помощь, я буду там. Не стейсняйся спросить.

ОБНОВЛЕНО: КОД ДОБАВЛЕН: -

Эти методы добавлены в класс с именем "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 содержит установщики / получатели для следующих членов:

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

СЕЙЧАС наступает фактическая реализация в 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 ряда по 3 кнопки в каждом ряду. Я сохранил журналы, которые я добавил, так как это поможет вам отладить и выяснить ваше решение.

Это будет работать на 100%.

* Я все равно рекомендую попробовать: просто создайте новый xml и в LinearLayout в качестве родителя добавьте свой LinearLayout кнопок и посмотрите. Это работает ? Во время выполнения попробуйте в обоих режимах. В вашем LinearLayout попробуйте удалить WeightSum. По моему мнению, это требование должно быть выполнено в самом xml. *

УДАЧИ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...