Search code examples
androidandroid-layoutandroid-gallery

Setting layout parameters for an element inside a Gallery


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?


Solution

  • 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.