5

Is it possible to add dynamically add Fragments with LayoutParams? I have 2 fragments that I want to put in a RelativeLayout: one should lock to the left. The other should be locked to the right.

user123321
  • 12,593
  • 11
  • 52
  • 63

4 Answers4

6

I used the following approach for a ListFragment in a LinearLayout:

class CustomListFragment
    extends ListFragment
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        ViewGroup v = (ViewGroup) super.onCreateView(inflater, container,
                savedInstanceState);
        v.setLayoutParams(new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.MATCH_PARENT, 1));
        return v;
    }
}

Now that I read your comments on the other answer, I see it is similar to what you considered.

But note: the framework may instantiate your fragments. Therefore, the class must be public and must have a constructor without any further arguments.

Any setter-methods to customize your fragments won't work therefore, as they won't be called for any framework-created instances.

sstn
  • 3,050
  • 19
  • 32
  • this works! somewhere inside android those LayoutParams are applied to the view that contains frame view. – babay Feb 10 '13 at 00:08
2

You could wrap them each in a layout (such as a LinearLayout), then set its size and position. This answer is regarding a similar problem, and shows how to use a FrameLayout with custom layout parameters to contain a Fragment.

Note that, when using the fragment object in XML, you can use android:layout_* attributes to control its position. Like so:

<LinearLayout
    android:orientation="horizontal"
    ... >

    <fragment
        android:layout_height="wrap_content"
        android:layout_width="0px"
        android:layout_weight="1"
        ... />

    <fragment
        android:layout_height="wrap_content"
        android:layout_width="0px"
        android:layout_weight="1"
        ... />

</LinearLayout>

However, I don't think it's possible to apply layout parameters programmatically to Fragments. They're not ViewGroups, after all.

Community
  • 1
  • 1
Cat
  • 66,919
  • 24
  • 133
  • 141
  • 1
    This is what I was afraid of. I'm hoping this isn't true. What a poor API choice. Google rants about not having nested unneeded layouts and now I'm forced to use nested layouts for positioning fragments. sigh.... – user123321 Sep 10 '12 at 19:17
  • Well, consider a `Fragment` in the same vein as an `Activity`. They perform slightly different tasks, but neither one is a layout object. They're both designed for running a portion of a process individually. To me, this is actually a good design decision; it keeps the functional code separate from the layout code. – Cat Sep 10 '12 at 19:19
  • I think I'm going to try having setLayoutParams on my fragment, and then in onCreateView add the custom layout params to the view before I return it. Still terrible I need an "id" to a container and can't use a reference....you're killing me El Goog. – user123321 Sep 10 '12 at 19:21
  • How is not being able to control the composition of a layout a good thing? – user123321 Sep 10 '12 at 19:22
  • You can completely control the composition of a layout. But instead of directly controlling the functional portion of the layout, you're containing it in a layout. Additionally, I just remembered (stupid of me) that `Fragment` XML objects [can have layout weights](http://developer.android.com/guide/components/fragments.html#Creating) applied to them. I'm going to amend my post to reflect this, as it may be a good enough solution. – Cat Sep 10 '12 at 19:24
  • 1
    Thanks for the edit, but that isn't dynamic anymore. However it's kind of like my idea above which I think will work though. Thanks for all the help and ideas. Totally appreciate it. :-) – user123321 Sep 10 '12 at 19:41
1

For specific cases, you can move the layer ordering into onStart() override

Fragment looks like this

public class FragmentOne extends Fragment {

private Client client;

public interface Client {
    RelativeLayout.LayoutParams fetchFragmentOneParams(FragmentOne fragment);
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    Activity activity = getActivity();

    try {
        client = (Client) getActivity();
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement FragmentOne.Client");
    }
}

@Override
public void onStart() {
    super.onStart();

    getView().setLayoutParams(client.fetchFragmentOneParams(this));
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    RelativeLayout view = new RelativeLayout(getActivity());
    //
    // code
    //
    return view;
}
0

You can set LayoutParameters of your Fragment in onCreateView method. Befor returning the final view as return value of this method you can set layout parameters. As a sample below fragment return a TextView as its View which stucked to its parent left by setting LayoutParams on it:

    public static class DummySectionFragment extends Fragment {
    public static final String ARG_SECTION_NUMBER = "placeholder_text";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        TextView textView = new TextView(getActivity());
        textView.setGravity(Gravity.CENTER);
        textView.setText(Integer.toString(getArguments().getInt(
                ARG_SECTION_NUMBER)));
        LayoutParams lp  = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        textView.setLayoutParams(lp);

        return textView;
    }
}
VSB
  • 9,825
  • 16
  • 72
  • 145