Search code examples
androidandroid-layoutandroid-fragmentsappcompatactivity

Align View in Fragment to View in parent AppCompatActivity


Im trying to to use getLayoutParams() to align a View in a fragment to a view in its parent AppCompatActivity

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) viewImAligning.getLayoutParams();
        params.addRule(RelativeLayout.BELOW, R.id.video_view_from_appCompat);
        viewImAligning.setLayoutParams(params);

Im initializing R.id.video_view_from_appCompat on the the fragment correctly since I can get its width/height etc from Fragment's setUserVisibleHint method. However I can not get viewImAligning to align to video_view_from_appCompat no matter where in the fragment's lifecycle I place viewImAligning.setLayoutParams(params);

For now I'm using a hacky workaround using getLocationsOnScreen

        int [] generatedLocations = new int[2];
        locations = generatedLocations;

        videoViewFromAppCompat.getLocationOnScreen(locations);
        int x = locations[0];
        int y = locations[1];
        viewImAligning.setY(y);

While the hacky workaround does the trick, I would like to learn why Im not getting the getLayoutParams to work.

Edit: Code and XML (bit of spaghetti code included AsyncTask incase that had something to do with it

public abstract class VideoIntro extends AppCompatActivity{

private LinearLayout videoViewFromAppCompat;

@Override
final protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.video_intro_layout_test);
    new LoadContestTask().execute();

}

private  class  LoadContestTask extends AsyncTask<Object, Object, Object> {
    ProgressDialog pDialog;

    @Override
    protected void onPreExecute() {
    ...

    }

    @Override
    protected Object doInBackground(Object... params) {
        initialize();
        return true;
    }

    protected void onPostExecute(Object result) {
        loadContent();
        pDialog.dismiss();
    }
}

    private void initialize() {
    ...
    videoViewFromAppCompat = (LinearLayout) findViewById(video_view_from_appCompat);
}
...
}

XML for video_intro_layout_test

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
>
<SurfaceView
   android:layout_width="0px"
   android:layout_height="0px" />
<LinearLayout
    android:id="@+id/video_view_from_appCompat"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/top"
    android:paddingLeft="45dp"
    android:paddingRight="45dp"
    android:paddingTop="36dp"
    android:visibility="invisible">
<VideoView
    android:id="@+id/video"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
     />
</LinearLayout>

<com.my_test.app.CustomViewPager
    android:id="@+id/view_pager"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
</com.my_test.app.CustomViewPager>

Fragment's Code

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    videoViewFromAppCompat = (LinearLayout) getActivity().findViewById(R.id.video_view_from_appCompat);

}

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_layout, container, false);
    viewImAligning = (RelativeLayout) v.findViewById(R.id.view_im_aligning);

}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser ) 
    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) viewImAligning.getLayoutParams();
    params.addRule(RelativeLayout.BELOW, R.id.video_view_from_appCompat);
    viewImAligning.setLayoutParams(params);

Solution

  • I think I figured it out. You are trying to align a view which is the base view of the Fragment (R.id.view_im_aligning) to a view (R.id.video_view_from_appCompat) inside a RelativeLayout which belongs to your Activity. The problem is that they do not share the same parent and that is what is causing for your code to fail.

    I suggest the following - if you need a dedicated Fragment to appear below your video_view_from_appCompat, add FrameLayout to contain the fragment add the Fragment into that view. After that you can align the FrameLayout to be below video_view_from_appCompat.

    So your xml will look somewhat like:

    <RelativeLayout ...>
        ...
        <LinearLayout
            android:id="@+id/video_view_from_appCompat"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/top"
            android:paddingLeft="45dp"
            android:paddingRight="45dp"
            android:paddingTop="36dp"
            android:visibility="invisible">
        <FrameLayout
            android:id="@+id/fragment_container"   
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/video_view_from_appCompat"/>
        ...
    </RelativeLayout>