0

I'm trying to create something similar to what Facebook has done below:

facebook groups

I have created an empty RelativeLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/fav_cake_rl">
</RelativeLayout>

Then I wrote the following code to dynamically create my views. As I would like 4 circles in one row going across the page (facebook only had 3), I obtained the DisplayMetrics which i placed into an object called "dm" in the code below and then divided the widthpixels by 4.

The layouts are created dynamically in a recyclerview.

    RelativeLayout rl = (RelativeLayout) v.findViewById(R.id.fav_cake_rl);

    CircularImageView circularImageView = new CircularImageView(context);
    RelativeLayout.LayoutParams circlellp = new RelativeLayout.LayoutParams(dm.widthPixels/4, dm.widthPixels/4);
    circularImageView.setLayoutParams(circlellp);
    circularImageView.setId(1);
    Drawable drawable = (Drawable) ContextCompat.getDrawable(context, R.drawable.cake);
    circularImageView.setImageDrawable(drawable);
    rl.addView(circularImageView);

    final TextView groupname = new TextView(context);
    RelativeLayout.LayoutParams textLp = new RelativeLayout.LayoutParams(dm.widthPixels/4, RelativeLayout.LayoutParams.WRAP_CONTENT);
    textLp.addRule(RelativeLayout.BELOW, 1);
    groupname.setLayoutParams(textLp);
    groupname.setGravity(Gravity.CENTER_HORIZONTAL);
    groupname.setText("StrawBerry Fields");
    rl.addView(groupname);

The end result looks like this:

strawberry cakes

I don't really want the circles to be so big or so close together so then I added padding and margin to the imageview:

    CircularImageView circularImageView = new CircularImageView(context);
    RelativeLayout.LayoutParams circlellp = new RelativeLayout.LayoutParams(dm.widthPixels/4, dm.widthPixels/4);
    **circlellp.setMargins(margin, margin, 0, 0);**
    circularImageView.setLayoutParams(circlellp);
    **circularImageView.setPadding(32, 32, 32, 0);**
    circularImageView.setId(1);
    Drawable drawable = (Drawable) ContextCompat.getDrawable(context, R.drawable.cake);
    circularImageView.setImageDrawable(drawable);
    rl.addView(circularImageView);

Now, it looks like this:

strawberrry after adding margin

I do not want the text to be so far away from the imageview and it appears that while the padding has reduce the imageview, it has also added an extra space between the imageview and the text.

How can I get the textview and the imageview to be close to one another?

UPDATE:

I tried it with XML instead by doing the following:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/fav_group_rl">

    <com.example.simon.customshapes.CircularImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/circlecake"
        android:layout_centerHorizontal="true"
        android:padding="24dp"
        android:layout_margin="8dp"
        android:src="@drawable/cake"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@id/groupname"
        android:text="StrawBerry Fields"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/circlecake"/>

</RelativeLayout>

To get 4 of them to display properly, I tried this:

        RelativeLayout rl = (RelativeLayout) v.findViewById(R.id.fav_group_rl);
        RelativeLayout.LayoutParams llp = new RelativeLayout.LayoutParams(dm.widthPixels/4, RelativeLayout.LayoutParams.WRAP_CONTENT);
        rl.setLayoutParams(llp);

When I ran this app, nothing was displayed.

Simon
  • 19,658
  • 27
  • 149
  • 217
  • Your padding didn't actually reduced your ImageView, it reduced _image_ inside your imageView. Have you tried using margins instead? – Kistamushken Oct 10 '15 at 18:37
  • I wanted it to reduce the image inside the imageview so that it looks similar to what facebook has done. I have not tried setting negative margin on my imageview to see if it will reduce the bottom part of it then maybe the top of the textview will align to the bottom of the actual image – Simon Oct 10 '15 at 18:41
  • What about reducing the padding/margin values? Otherwise you can use a negative top margin for your TextViews (to reduce the space between the image and text) – Rami Oct 10 '15 at 18:41
  • actually reducing the negative bottom margin value does bring the text up closer to the imageview, but I don't know if this is the best solution as while it might work on my device, it might not work on all devices. – Simon Oct 10 '15 at 18:45
  • What i meant is that you can try using this instead of setting padding to your imageviews :((RelativaLayout.LayoutParams)imageView.getLayoutParams().topMargin = ((RelativaLayout.LayoutParams)imageView.getLayoutParams().leftMargin = (RelativaLayout.LayoutParams)imageView.getLayoutParams().rightMargin = 32; – Kistamushken Oct 10 '15 at 18:50
  • margin would create more space that would push the bounds of the imageview so that the fourth item would be pushed off the screen. The padding on the other hand reduces the size of the imageview which is what I had wanted. The side effect of using padding is that it does not reduce the size of the imageview, as you have correctly pointed out so therefore the textview is far below the imageview. – Simon Oct 10 '15 at 19:01
  • 1
    Actually, I tried the margin thing and it worked, thanks @Kistamushken – Simon Oct 10 '15 at 19:13
  • 1
    You are welcome @Simon – Kistamushken Oct 10 '15 at 19:25

3 Answers3

0

Why not use xml to create one item and repeat it in recyclerview using adapter ? Xml will give you better control while designing your view and you are using recyclerview anyways.

Rahul Tiwari
  • 6,851
  • 3
  • 49
  • 78
  • I considered doing that but the problem with xml is that you cannot set the imageview at a fourth of the screen's width. You can either set it as match_parent or wrap_content. – Simon Oct 10 '15 at 18:39
  • Make them wrap content, and have four of them in a row in your recyclerview. – Rahul Tiwari Oct 10 '15 at 18:42
  • 1
    @Simon By XML, everything is possible! – frogatto Oct 10 '15 at 18:44
  • @Simon If you're okay with XML, tell me to post an answer. – frogatto Oct 10 '15 at 18:46
  • I'm going to test it out on xml first by making my relativeLayout equal to 1/4 of the screen width with all the elements on xml and then see if i can fit 4 into the width of my screen. – Simon Oct 10 '15 at 18:48
  • I added more information on the xml test that I performed but I was not successful. If you can assist me in making it successful, you can post an answer. Thanks @abforce – Simon Oct 10 '15 at 18:58
0

Using XML, you can easily divide screen width into n equal segment using layout_weight trick. As far as I know, you can only use this attribute in LinearLayouts.

However nothing will go wrong by LinearLayout, you can, of course, compose multiple layouts inside each other.

Let's head back to your case. In your case you would need a horizontal LinearLayout and then divide it into 4 equal cells. This could be done by a XML code like this.

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

    <FrameLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <!-- Cell 1 -->

    </FrameLayout>
    <FrameLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <!-- Cell 2 -->

    </FrameLayout>
    <FrameLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <!-- Cell 3 -->

    </FrameLayout>
    <FrameLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <!-- Cell 4 -->

    </FrameLayout>

</LinearLayout>

Note: layout_width of those cells should be zero. And layout_weight is the weight by which the whole width is divided. This could be different for each cell to producing heterogeneous cells.

More Info

Community
  • 1
  • 1
frogatto
  • 28,539
  • 11
  • 83
  • 129
  • OK - thanks for the suggestion but if I have to implement this, it would mean changing the entire structure of my app to a linearlayout as it is currently based off a recyclerview, which would be a lot of rework. I can see that this would work though, just not in my use case. – Simon Oct 10 '15 at 19:12
  • @Simon I don't think so, you may want to only change the codes pertaining to that header view, not whole your XML structure. However it depends on how your XML structure is. – frogatto Oct 10 '15 at 19:16
0

I found the solution to this by actually playing around with margins in the end.

For the imageView, to reduce the size of the imageview, I had set the margin to some 8dp for top, left and right but not bottom.

Then for the textview, I have set the margin to -8dp for the top to compensate for the margin taken by the imageView at the imageView's top.

Then to draw the actual linearLayout properly, I had to set the linearLayout at the height of the imageView (dm.widthPixels/4), add on the margin at the top of the imageView and then the height of the textview (h).

    RelativeLayout rl = (RelativeLayout) v.findViewById(R.id.fav_group_rl);

    CircularImageView circularImageView = new CircularImageView(context);
    RelativeLayout.LayoutParams circlellp = new RelativeLayout.LayoutParams(dm.widthPixels/4, dm.widthPixels/4);
    circlellp.setMargins(margin, margin, margin, 0);
    circularImageView.setLayoutParams(circlellp);
    circularImageView.setId(1);
    Drawable drawable = (Drawable) ContextCompat.getDrawable(context, R.drawable.cake);
    circularImageView.setImageDrawable(drawable);
    rl.addView(circularImageView);

    final TextView groupname = new TextView(context);
    RelativeLayout.LayoutParams textLp = new RelativeLayout.LayoutParams(dm.widthPixels/4, RelativeLayout.LayoutParams.WRAP_CONTENT);
    textLp.addRule(RelativeLayout.BELOW, 1);
    groupname.setLayoutParams(textLp);
    textLp.setMargins(0,-margin,0,0);
    groupname.setGravity(Gravity.CENTER_HORIZONTAL);
    groupname.setText("StrawBerry Fields");
    rl.addView(groupname);
    groupname.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT < 16) {
                h = groupname.getHeight();
                groupname.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                h = groupname.getHeight();
                Log.e("groupnameH: ", ""+h);
                groupname.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        }
    });

    RelativeLayout.LayoutParams llp = new RelativeLayout.LayoutParams(dm.widthPixels/4, dm.widthPixels/3+ h + margin);
    rl.setLayoutParams(llp);
Simon
  • 19,658
  • 27
  • 149
  • 217