I have an app in Google play already and has no problem at all until I upgrade my Android Studio. The build.gradle has to be modified so that the project can be compiled Here is what I changed:
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.android.support:appcompat-v7:21.0.0'
compile 'com.google.android.gms:play-services:6+'
compile 'com.android.support:support-v4:+'
}
The only change is com.android.support:appcompat-v7:+ which is changed to com.android.support:appcompat-v7:21.0.0.
My problem is the .findViewById(R.id.tabhost) always return null so that the application crashes. Here is my layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
My java code:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTabHost;
public class MenuLeftFragment extends Fragment {
private FragmentTabHost mFragmentTabHost;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mView = getView();
if (mView != null) {
mFragmentTabHost = (FragmentTabHost) mView
.findViewById(R.id.tabhost);
Any idea? Thanks.
You should do this in onCreateView() where you should define as follows :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.your_layout, container, false);
mFragmentTabHost = (FragmentTabHost) v.findViewById(R.id.tabhost);
return v;
}
If you want to keep this code, the getView() on the onActivityCreated() is wrong, if you have a view on your onCreate() you can do something like :
mView = v;
Then in your onActivityCreated() instead of call getView() use mView
Then it should work.
Related
I would like to show a menu in my fragment. I've done this a million times, yet it is not working now for some reason. This is the first time I experiment with the new androidx library, maybe bug?
Fragment:
public class FragmentDogs extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dogs, container, false);
setHasOptionsMenu(true);
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_dogs, menu);
}
}
Activity:
public class ActivityMain extends AppCompatActivity {
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new FragmentDogs()).commit();
}
}
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/dogs_add_menu_item"
android:icon="#drawable/ic_plus"
android:title="#string/dogs" />
Gradle:
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.platinum"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
implementation 'com.google.android.gms:play-services-maps:16.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
Screenshot:
You have to set the custom toolbar to the Fragment Layout and as SupportActionBar.
Your Fragment Layout
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
android:elevation="5dp"
android:minHeight="?attr/actionBarSize"
app:contentInsetEnd="50dp"
app:contentInsetRight="50dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:title="testtext"
app:contentInsetStartWithNavigation="0dp">
</android.support.v7.widget.Toolbar>
Your Fragment class
public class YourFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.yourfragmentlayout, container, false);
setHasOptionsMenu(true);
Toolbar toolbar = (Toolbar)rootView.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("YourFragment");
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_dogs, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
If YourFragment() is red underlined
Make sure that you are using
import android.support.v4.app.Fragment;
instead of
import android.app.Fragment;
you are missing the closing tag on menu.xml, which possibly should end with </menu>.
the testInstrumentationRunner is not the correct test-runner for androidx, along with the other test dependencies. androidx.fragment:fragment:1.0.0 would be the proper dependency for the Fragment class. see the migration guide for further androidx dependencies, which you might be lacking; alike androidx.appcompat:appcompat:1.0.2 for the AppCompatActivity.
it might be a X/Y problem... first fix the dependencies - and then the menu.
If I remove the .commit() in the transaction the app compiles but shows an empty screen. If I add .commit() the app opens and closes instantly. I am new to fragments can anyone help resolve this. I have simply added an ImageView layout. Infalted it in Fragment class and hardcoded an image in it. Further I just created an instance of that Fragment in MainActivity.
My Android Studio version is: 3.1.3
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="180dp"
android:id="#+id/head_container"
/>
</android.support.constraint.ConstraintLayout>
body_part_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/body_part_frag"
>
</ImageView>
BodyPartFragment.java
package com.example.musa.my_frag_app;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
public class BodyPartFragment extends Fragment {
public BodyPartFragment(){
//Do Nothing
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.body_part_fragment, container);
ImageView body_image = rootView.findViewById(R.id.body_part_frag);
body_image.setImageResource(R.drawable.ic_launcher_background);
return rootView;
}
}
MainActivity.java
package com.example.musa.my_frag_app;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BodyPartFragment headfrag = new BodyPartFragment();
FragmentManager frag_m = getSupportFragmentManager();
frag_m.beginTransaction().add(R.id.head_container,headfrag).commit();
//frag_m.executePendingTransactions();
}
}
inflater.inflate(R.layout.body_part_fragment, container); will definitely throw an exception. The default for LayoutInflator.inflate() is attachToRoot=true. It should be false when called from onCreateView in a Fragment as this handles that for you. Change to inflater.inflate(R.layout.body_part_fragment, container, false);
add param for attachToRoot false
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.body_part_fragment, container, false);
TextView body_text = rootView.findViewById(R.id.body_part_frag);
body_text.setText("Hello World");
return rootView;
}
Try This for fragment body part:
<android.support.constraint.ConstraintLayout
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">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/body_part_frag"/>
</android.support.constraint.ConstraintLayout>
Try like this:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
BodyPartFragment headfrag = new BodyPartFragment();
fragmentTransaction.replace(R.id.head_container, headfrag);
fragmentTransaction.commit();
change
View rootView = inflater.inflate(R.layout.body_part_fragment, container);
to
View rootView = inflater.inflate(R.layout.body_part_fragment, null);
Consider an Android activity that is subclass ofandroid.support.v4.app.FragmentActivity. It contains several apges managed by FragmentStatePagerAdapter. Each page contains a ListView wrapped by android.support.v4.widget.SwipeRefreshLayout. The following screenshot shows the initial state of this activity.
Now, I swipe down to refresh the list on page 0. The refresh animation appears. Now, let's swipe to the right on page 2 and then back to page 0.
The refresh animation is still visible. This seems strange to me as page 0 was destroyed and created again. Moreover, if I swipe up (trying to scroll to the end of the list on page 0) some strange layer is rendered over the page which seems to contain the old state of the page from the time it was destroyed.
I have no idea why this happens and how to fix it. Thanks for any help.
Here is the source code of a minimal application that consists of 3 layout files, an activity class, a fragment class, a manifest file and a build script.
swipeandroid/src/main/res/layout/service_schedule_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/servicePager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"/>
</android.support.v4.view.ViewPager>
swipeandroid/src/main/res/layout/service_schedule_tab_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/serviceRefreshLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/timeSlots"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
swipeandroid/src/main/res/layout/service_schedule_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"/>
</RelativeLayout>
swipeandroid/src/main/java/com/swipetest/ServiceScheduleActivity.java
package com.swipetest;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
public class ServiceScheduleActivity extends FragmentActivity {
#Override
protected void onCreate(final Bundle inState) {
// call super class
super.onCreate(inState);
// set content
setContentView(R.layout.service_schedule_activity);
// set up service pager
((ViewPager) findViewById(R.id.servicePager)).setAdapter(new ServiceFragmentPagerAdapter());
}
private class ServiceFragmentPagerAdapter extends FragmentStatePagerAdapter {
public ServiceFragmentPagerAdapter() {
super(getSupportFragmentManager());
}
#Override
public int getCount() {
return 5;
}
#Override
public Fragment getItem(final int position) {
return ServiceScheduleTabFragment.newInstance(position);
}
#Override
public CharSequence getPageTitle(final int position) {
return String.format("page %d", position);
}
}
}
swipeandroid/src/main/java/com/swipetest/ServiceScheduleTabFragment.java
package com.swipetest;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class ServiceScheduleTabFragment extends Fragment {
private static final String TAB_POSITION_ARGUMENT = "tabPosition";
public static ServiceScheduleTabFragment newInstance(final int tabPosition) {
// prepare arguments
final Bundle arguments = new Bundle();
arguments.putInt(TAB_POSITION_ARGUMENT, tabPosition);
// create fragment
final ServiceScheduleTabFragment fragment = new ServiceScheduleTabFragment();
fragment.setArguments(arguments);
return fragment;
}
#Override
public View onCreateView(final LayoutInflater layoutInflater, final ViewGroup parent, final Bundle inState) {
// create fragment root view
final View rootView = layoutInflater.inflate(R.layout.service_schedule_tab_fragment, parent, false);
// initialize time slot list view
final ListView timeSlotListView = (ListView) rootView.findViewById(R.id.timeSlots);
timeSlotListView.setAdapter(new TimeSlotListAdapter());
// return fragment root view
return rootView;
}
private int getTabPosition() {
return getArguments().getInt(TAB_POSITION_ARGUMENT);
}
private static class TimeSlotRowViewHolder {
private final TextView timeView;
public TimeSlotRowViewHolder(final View rowView) {
timeView = (TextView) rowView.findViewById(R.id.time);
}
public TextView getTimeView() {
return timeView;
}
}
private class TimeSlotListAdapter extends BaseAdapter {
#Override
public int getCount() {
return 80;
}
#Override
public Object getItem(final int position) {
return position;
}
#Override
public long getItemId(final int position) {
return position;
}
#Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
// reuse or create row view
final View rowView;
if (convertView != null) {
rowView = convertView;
} else {
rowView = LayoutInflater.from(getContext()).inflate(R.layout.service_schedule_row, parent, false);
rowView.setTag(new TimeSlotRowViewHolder(rowView));
}
// fill data
final TimeSlotRowViewHolder rowViewHolder = (TimeSlotRowViewHolder) rowView.getTag();
rowViewHolder.getTimeView().setText(String.format("tab %d, row %d", getTabPosition(), position));
return rowView;
}
}
}
swipeandroid/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.swipetest"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23"/>
<application
android:name="android.app.Application"
android:label="Swipe Test"
android:allowBackup="false">
<activity
android:name="com.swipetest.ServiceScheduleActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
swipeandroid/build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
}
}
apply plugin: 'com.android.application'
repositories {
mavenCentral()
}
dependencies {
compile "com.android.support:support-v4:23.1.1"
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
buildTypes {
debug {
debuggable true
minifyEnabled false
}
}
}
Try to clear the list and then load the new data on swipe refresh.
As mentioned in the comment.
Finally, I have discovered a workaround that is very simple to implement and fixes the issue.
Just wrap the SwipeRefreshLayout e.g. by FrameLayout. It seems that the ViewPager does not like SwipeRefreshLayout being the root of the view hierarchy of a page fragment.
Anyway, this issue looks like a bug in Android Support Library. See
https://code.google.com/p/android/issues/detail?id=194957
I have also tried other workarounds that do not work:
Replacing FragmentStatePagerAdapter by `FragmentPagerAdapter will not help.
Calling mySwipeRefreshLayout.setRefreshing(false) in onPause will not help.
Modifying the FragmentStatePagerAdapter so that it does not remeber states of destroyed pages will not help.
The following workarounds can help somehow but I prefer the suggested wrapping of SwipeRefreshLayout anyway:
Clearing the data (so that the ListView contains no rows) in SwipeRefreshLayout.OnRefreshListener#onRefresh() helps only if the ListView has transparent background. The unwanted snapshot is probably still rendered over the first page but it is fully transparent.
You can disallow paging for the time of refresh animation. However, this takes some effort as you must subclass both ViewPager and PagerTabStrip and prevent appropriate UI events in your subclasses.
Of course, you can avoid using SwipeRefreshLayout in ViewPager completely but this does not seem to be necessary.
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;
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);
...
}
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");
}
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);
...
}
I have a Fragment class, called from by FragmentTabHost, which does not display nothing.
This is my ArticulosFragment class:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ArticulosFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("App", "asdasdasd");
return inflater.inflate(R.layout.fragment_articulos, container, false);
}
}
I have a simple TextView in the XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Articulos"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
When I run the app, the log added shows correctly, but the text Articulos doesn't.
Edit: This is my TabHost class which displays (or should displays) the ArticulosFragment class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(),
android.R.id.tabcontent);
inicializarTabs();
}
public void inicializarTabs() {
TabHost.TabSpec spec = tabHost.newTabSpec("Articulos");
spec.setContent(new TabContentFactory() {
#Override
public View createTabContent(String tag) {
// TODO Auto-generated method stub
return findViewById(R.id.realtabcontent);
}
});
spec.setIndicator("Articulos");
tabHost.addTab(spec, ArticulosFragment.class, null);
}
Two Things That Might Cause That:
Check If The Container coming is null for view
Check you Code For Fragment that show Fragment
Try Removing onCreate method from Fragment
TabContentFactory
Makes the content of a tab when it is selected. Use this if your tab
content needs to be created on demand, i.e. you are not showing an
existing view or starting an activity.
Please notice this line:
you are not showing an existing view or starting an activity.
public abstract View createTabContent (String tag)
Callback to make the tab contents
Parameters
tag Which tab was selected.
Returns
The view to display the contents of the selected tab.
So because you have a fragment and it is already have a view you do not need createTabContent and the interesting part is:
https://github.com/android/platform_frameworks_support/blob/master/v13/java/android/support/v13/app/FragmentTabHost.java#L219
as you see fragmentTabHost overwrites your TabContentFactory.
anyway your problem is:
tabHost.setup(this, getSupportFragmentManager(),android.R.id.tabcontent);
change it to:
tabHost.setup(this, getSupportFragmentManager(),R.id.realtabcontent);