4

I was testing out B4A (Basic4Android) and there's something called a "designer script", this basically allows you to position elements on a screen. For example:
TextBox1.setTopAndBottom(0%y, 50%y)
TextBox1.setLeftAndRight(0%x, 50%x)

When this script runs it will automatically position the TextBox1 on the screen, imagine the the screen is 100 pixels by 100 pixels (100x100), the TextBox1 will be placed at (0, 0) (top left), (50, 50) (bottom right).

How can I achieve something like this in Eclipse?
I can't figure it out. I want to position an element (TextBox1 for example) to fit 25% of the width and 50% of the height for example. How do I achieve this?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
user3422952
  • 319
  • 2
  • 8
  • 17
  • Bad practice? So what's the best way to go around this? RelativeLayout? – user3422952 Jul 31 '14 at 16:25
  • @ashishduh ... what are you talking about? he asked for a technique (which you illustrated in your answer), which is **terrible**. And it's called "nested layout weights" – Phantômaxx Jul 31 '14 at 16:32
  • I accidentally deleted my comment, but I'll reiterate, it has nothing to do with nested weights. My link doesn't talk about nested weights either, nor does my example. – ashishduh Jul 31 '14 at 16:34
  • @FrankN.Stein - thanks for the advice. So how should I go about this? I don't want to define the width/height of an element specifically, I want to do it automatically. Is this at all possible with a relativelayout? It seems like it should be possible and have good performance. – user3422952 Jul 31 '14 at 16:36
  • I added my RelativeLayout tricky trick. See if you like it. – Phantômaxx Jul 31 '14 at 16:56

3 Answers3

1

OK. This is the trick

In simple words: make a 1px (px, not dp - you don't want it scaled, but small enough to be trascurable!) TextView which will be your invisible (you leave it transparent and set no text in it) "center of the universe".
Then stretch your other TextView, but limit it to stay to the left (which is at 50% - 1/2 px) of the center and above (again, 50% - 1/2 px) it:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:id="@+id/centerPoint"
        android:layout_width="1px"
        android:layout_height="1px"
        android:layout_centerInParent="true"
    />
    <TextView
        android:id="@+id/myText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_toLeftOf="@id/centerPoint"
        android:layout_above="@id/centerPoint"
    />
</RelativeLayout>
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • As clever as this is, isn't there the possibility that if the user clicks on the text box the keyboard will display? Also, this works for splitting the screen into 4 sections. Is it possible to, for example, move the "centred" down a bit until it's 60% down? In B4A you could do something similar to this, e.g. `.setTopAndBottom(0%y, Center + 10%y) - I wish something this simple was possible. – user3422952 Jul 31 '14 at 17:07
  • 1
    You could do that, but then you'd use some **invisible** TextViews laying in some LinearLayouts. Then this will revive the ghost of the "nested layout weights", if you are going to set both the width and the height... Which is still what Basic4Android will produce, in the end. OR you could do all the math in Java and build your UI in code. But it would be such an overkill; I guess I'd prefer to suicide. – Phantômaxx Jul 31 '14 at 17:29
  • 1
    But is there honestly no way to just say "width:50%x" OR SOMETHING?! This seems ridiculous, I don't want to use dp/dip because it'll be different on every screen. This can't be possible, there has to be a way to just say "make this 25% of the (x) screen". – user3422952 Jul 31 '14 at 18:30
  • 1
    Well, percentage is **not** a measure unit, in Android, unfortunately. But yes, there is a way. If you want ONLY one dimension scaled: weights (only in LinearLayout and its derivates). For having both the dimensions scaled, you have to include the LinearLayout in a parent LinearLayout... – Phantômaxx Jul 31 '14 at 18:33
  • I've got a RelativeLayout with a child LinearLayout - I think this is the best way to simply achieve this. Heck, two elements won't mean bad performance. If so, the app shouldn't be too intensive. I'll see how it goes. Thanks for your help man! +1 – user3422952 Jul 31 '14 at 18:56
  • 1
    No, just two nested layouts won't be that bad. The problem is when you have a ListView with a hundred layouts... – Phantômaxx Jul 31 '14 at 18:58
  • Hmm, makes sense. I've encountered another problem again. I've got two LinearLayouts (to split the screen in two). The first one contains to elements (should only take up 50% of the screen) and the second one contains another two elements. The first LinearLayout seems to take up the entire screen when I have it set to `android:layout_height="wrap_content"`. Why does this happen? How do I make the height smaller without hardcoding it? – user3422952 Jul 31 '14 at 19:13
  • 1
    Portrait or Landscape? Assuming Portrait, with an orientation set to vertical, in the parent LinearLayout. Both the elements then must have weight=1, height="0dp" – Phantômaxx Jul 31 '14 at 19:16
  • Portrait. This seems so ridiculous - I'm fairly new to Android and this layout crap, but surely they should add a simpler construction tool. – user3422952 Jul 31 '14 at 19:17
  • 1
    The `weighted` dimension must be set to **0dp**, so Android knows which dimension is the affected **one** (not both) – Phantômaxx Jul 31 '14 at 19:18
  • Thanks! You're a god - I don't know why I didn't think of this... Thanks. I had to change the RelativeLayout parent to a LinearLayout but this isn't a problem. Also, if I wanted a textview over the LinearLayout I assume I'll need to use a RelativeLayout nested under the LinearLayout? My current view is: ` ` if I wanted text over the LinearLayouts should it be: ` ` - thanks for the help. – user3422952 Jul 31 '14 at 19:28
  • No, I'm not. I'm almost human... If you want a TextView OVER (but you show it UNDER?) the LLs, you don't need a RL. Just use the TV and save a layout (better for performances). The TV parent will be the outer LL container. That's all. – Phantômaxx Aug 01 '14 at 07:10
1

Consider using the Android percent support library, which adds a PercentRelativeLayout and PercentFrameLayout that allow children to define their sizing in percentages.

e.g.

 <android.support.percent.PercentFrameLayout
         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">
     <ImageView
         app:layout_widthPercent="50%"
         app:layout_heightPercent="50%"
         app:layout_marginTopPercent="25%"
         app:layout_marginLeftPercent="25%"/>
 </android.support.percent.PercentFrameLayout/>
Mark McDonald
  • 7,571
  • 6
  • 46
  • 53
-2

You need to use LinearLayout and weights.

http://developer.android.com/guide/topics/ui/layout/linear.html

Example of 6 TextViews, each row will take up 50% of the screen height, and within each row each TextView will take up 33% of the screen width.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/text1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/text2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/text3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/text4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/text5"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/text6"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
</LinearLayout>
ashishduh
  • 6,629
  • 3
  • 30
  • 35