4

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;
Lv99Zubat
  • 853
  • 2
  • 10
  • 27
  • Have you tried either casting `getActivity` like `((ExampleActivity) getActivity()).findViewById` or using that code in the `onAttach` method in the Fragment? – OneCricketeer Jan 27 '16 at 16:48

3 Answers3

3

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);
    ...
}
George Mulligan
  • 11,813
  • 6
  • 37
  • 50
  • ah okay, you know what? The things I tried actually worked when I was messing with nested fragments. So I was able to access the views from an activity if the fragment was a child fragment. I guess an activity has it's layout by the time a child fragment is created? But a parent would not work. I thought I was losing my mind lol. – Lv99Zubat Jan 27 '16 at 17:05
  • 1
    @Rai What do you mean by a child fragment? If you add the fragment using the `FragmentManager` that is usually done in `onCreate` of the host activity or later so in that case the view would be accessible in `onCreateView` of the fragment. – George Mulligan Jan 27 '16 at 17:10
  • that must have been it then. I created the child fragment using a child fragment manager. So if I use a fragment manager in the onCreate of the Activity and create the fragment that way, it should work. Wow, android is so tricky :P If that works, I'll close the question and mark your answer as accepted. – Lv99Zubat Jan 27 '16 at 17:17
  • Now that the onActivityCreated() method is deprecated , how can this be done on the latest SDK? Unable to use the fragment onViewCreated method as the activity views are not available at that point. Thanks – Sachithd Oct 27 '20 at 10:48
2

You need to override onActivityCreated() as activity view is not created until this method is called .

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    View nonVideoLayout = ((MainActivity)getActivity()).findViewById(R.id.nonVideoLayout);

    if(nonVideoLayout == null){

        Log.e("rai", "why is nonVideoLayout null?");
    }
    else{
        Log.e("rai", "view not null hurray");
    }
    View videoLayout =    getActivity().findViewById(R.id.videoLayout);

    if(videoLayout == null){

        Log.e("rai", "why is videoLayout null?");
    }else{
        Log.e("rai", "view not null hurray");
    }
JAAD
  • 12,349
  • 7
  • 36
  • 57
1

You need to override onViewCreated. The views aren't created at the onCreate but are once the view is actually created. This post gives a little more information Difference between onCreateView and onViewCreated in Fragment

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ...
}
Community
  • 1
  • 1
aminner
  • 359
  • 3
  • 10