Search code examples
androidfragmentfindviewbyid

Android: how do I access views (using findViewById) of an Activity from a Fragment onCreateView()?


I have a pretty simple project with an Activity that contains a Fragment. Only thing you may be unfamiliar with is that I am using a VideoEnabledWebView which isn't that complicated and is something I've used before. It's just a custom webview.

Here is my code:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<!-- Don't forget the internet permission if you will be using the WebView to load remote content -->
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:hardwareAccelerated="true" > <!-- Only works in API level 11+, and allows the HTML5 videos to play in-line -->

    <activity
        android:name="name.cpr.ExampleActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

ExampleActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

import cpr.name.videoenabledwebview.R;

public class ExampleActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        Log.i("rai", "activity onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

    }

}

activity_example.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ExampleActivity">

<!-- View that will be hidden when video goes fullscreen -->
<RelativeLayout
    android:id="@+id/nonVideoLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <fragment android:name="name.cpr.WebViewFragment"
        android:id="@+id/webViewFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

<!-- View where the video will be shown when video goes fullscreen -->
<RelativeLayout
    android:id="@+id/videoLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</RelativeLayout>

WebViewFragment.java

package name.cpr;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import cpr.name.videoenabledwebview.R;


public class WebViewFragment extends Fragment {

private VideoEnabledWebView webView;
private VideoEnabledWebChromeClient webChromeClient;
View rootView;

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

    rootView = inflater.inflate(R.layout.root, container, false);

    webView = (VideoEnabledWebView) rootView.findViewById(R.id.webView);

    Log.i("rai", "nonVideoLayout = " + R.id.nonVideoLayout);

    Log.i("rai", "videoLayout = " + R.id.videoLayout);

    View nonVideoLayout = rootView.findViewById(R.id.nonVideoLayout);

    if(nonVideoLayout == null){

        Log.i("rai", "why is nonVideoLayout null?");
    }

    ViewGroup videoLayout = (ViewGroup)     rootView.findViewById(R.id.videoLayout);

    if(videoLayout == null){

        Log.i("rai", "why is videoLayout null?");
    }

    webChromeClient = new VideoEnabledWebChromeClient(nonVideoLayout, videoLayout);

    webView.setWebChromeClient(webChromeClient);

    webView.loadUrl("http://m.youtube.com");

    return rootView;

}
}

root.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:text="the fragment"/>

<name.cpr.VideoEnabledWebView
    android:id="@+id/webView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

</LinearLayout>

I just can't get access to those two relative layouts in my Activity, I keep getting null.

Things I have tried that DON'T work:

rootView.findViewById //rootView is the return from the inflate

getActivity().findViewById

getView().findViewById

container.findViewById

I've also tried this in my fragments onCreate:

context = getActivity().getApplicationContext();

webViewFragmentId = context.getResources().getIdentifier(
        "root", "layout", context.getPackageName());

webViewId = context.getResources().getIdentifier("webView", "id",
        context.getPackageName());

nonVideoLayoutId = context.getResources().getIdentifier("nonVideoLayout", "id", context.getPackageName());
videoLayoutId = context.getResources().getIdentifier("videoLayout","id", context.getPackageName());

rootView = inflater.inflate(webViewFragmentId, null);

webView = (VideoEnabledWebView) rootView.findViewById(webViewId);

View nonVideoLayout = getActivity().findViewById(nonVideoLayoutId);
ViewGroup videoLayout = (ViewGroup) getActivity().findViewById(videoLayoutId);

webChromeClient = new VideoEnabledWebChromeClient(nonVideoLayout, videoLayout);

webView.setWebChromeClient(webChromeClient);

webView.loadUrl("http://m.youtube.com");


return rootView;

Solution

  • Update 2020-10-27

    Now that onActivityCreated has been deprecated the documentation states you should instead register a LifecycleObserver to know when the Activity.onCreate() method has completed.

    See this answer for an example.


    Original Answer

    You should override onActivityCreated and access the views you need from the activity in that method because when onCreateView is run in the fragment the activity has not yet had its layout set so you cannot access its views.

    @Override
    public void onActivityCreated (Bundle savedInstanceState) {
        View nonVideoLayout = getActivity().findViewById(R.id.nonVideoLayout);
        ViewGroup videoLayout = (ViewGroup) getActivity().findViewById(R.id.videoLayout);
        ...
    }