9

I am using a Gallery to display an horizontal timeline of events. Some of the events get Gravity.TOP and some Gravity.BOTTOM to align them above or below a nice line displaying the years. So far, so good.

I want to change the left margin property of the elements in the top, so there are no huge gaps and the elements look interleaved. For example: setting a negative left margin to every element aligned on top.

Each element of the Gallery consists on a LinearLayout, which can be set up a MarginLayoutParams instance to change the margins programatically. However, I'm getting a ClassCastException when using MarginLayoutParams inside the adapter because the Gallery code does this:

    // Respect layout params that are already in the view. Otherwise
    // make some up...
    Gallery.LayoutParams lp = (Gallery.LayoutParams) child.getLayoutParams();

Any ideas or hints on how to overcome this problem?

mgv
  • 8,384
  • 3
  • 43
  • 47
  • "I'm getting a ClassCastException when using MarginLayoutParams inside the adapter" - can you show us how your MarginLayoutParams interacts with your adapter? – Keith May 04 '11 at 19:05

2 Answers2

4

Each element of the Gallery consists on a LinearLayout

Just wrap it using another LinearLayout and set the margin in the LinerLayout.LayoutParams for the inner LinearLayout. I have checked it, and it seems to do what you want.

So the layout you inflate for Gallery item should look like this:

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

    <LinearLayout
        android:id="@+id/layInner"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView android:id="@+id/imageView1" android:src="@drawable/icon"
            android:layout_height="wrap_content" android:layout_width="wrap_content"
            android:scaleType="fitXY" />

        <TextView android:text="TextView" android:id="@+id/textView"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:visibility="visible" />
    </LinearLayout>
</LinearLayout>

Then you can access inner LinearLayout in adapter getView method and set margin there depending on your conditions (sample code without convertView reuse optimization):

public View getView(int position, View convertView, ViewGroup parent) {
  Context context = getContext();
  final float density = context.getResources().getDisplayMetrics().density;

  LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  View layOuter = inflater.inflate(R.layout.row_layout, null);
  View layInner = layOuter.findViewById(R.id.layInner);
  if (...) {  // your condition
    LinearLayout.LayoutParams innerLP = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    innerLP.leftMargin = (int) (50 * density);
    layInner.setLayoutParams(innerLP);
  }
  return layOuter;
}

Please note that you must use LinearLayout.LayoutParams (it extends MarginLayoutParams) for the inner layout, otherwise it will not work.

Volo
  • 28,673
  • 12
  • 97
  • 125
  • What I need is a mix of the two options. I have to reference the LinearLayout in the XML file and set the margin programatically, because different elements will have different margins. That's when you get the exception. – mgv May 05 '11 at 12:57
  • Please check the updated answer. As a general rule: you can set margin for elements which are places inside a layout that support margins (e.g.: RelativeLayout, LinearLayout, FrameLayout). So in your case you can set margins for elements placed in the `LinearLayout` (but not for the LinearLayout itself when its parent is Gallery which doesn't support setting margins for its child - that's why we should add inner LinearLayout) . If you need additional help please post the layout you use for Gallery row and `getView` code as well. – Volo May 05 '11 at 14:47
  • Adding one more level of child elements worked. It seems that you cannot alter the layout params of the direct child of a Gallery. Thanks! – mgv May 05 '11 at 14:47
  • I cannot award the bounty for 4 hours (I guess because it is less than 24 hours old), but I will award it to you as soon as it is enabled. :) – mgv May 05 '11 at 14:49
  • Glad to hear it helped you. NP about the bounty - I can wait for 4 hours. ;) – Volo May 05 '11 at 17:00
-2

Gallery.LayoutParams is an entirely different class than android.view.ViewGroup.LayoutParams.

Your child view (built from the adapter) is a LinearLayout that returns a android.view.ViewGroup.LayoutParams, whereas the Gallery returns a Gallery.LayoutParams.

Try using android.view.ViewGroup.LayoutParams instead of Gallery.LayoutParams. If you must use both, then manually set the properties from one to the other where applicable (although I can't really think of a reason why you'd need to use both).

Keith
  • 2,958
  • 4
  • 26
  • 29
  • I am not using Gallery.LayoutParams, that's the whole problem. My LinearLayout is automatically wrapped in a Gallery.LayoutParams just because it's an element in a Gallery widget. That's exactly the problem. – mgv May 04 '11 at 19:14