Calling ViewPager inside a Fragment [duplicate] - android

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
findViewByID returns null
(33 answers)
Closed 2 years ago.
I am designing an Onboarding screen with the help of ViewPager. The ViewPager sits inside a fragment underlying my MainActivity class. The error arises when I pass the ViewPager adapter class to the ViewPager inside my fragment! It throws NullPointerException and after breakpoint debugging I find that the inflater inside my PagerAdapter class is null.
I have tried some alternatives to get the inflater working but no luck! I ll post my codes below:
ViewPager Fragment class:
public class ViewPagerFragment extends Fragment {
ViewPager viewpager;
LinearLayout dotsLayout;
SliderAdapter sliderAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_view_pager, container, false);
viewpager = (ViewPager) view.findViewById(R.id.viewPagerFragment);
dotsLayout = (LinearLayout) view.findViewById(R.id.dotsLayout);
sliderAdapter = new SliderAdapter(view.getContext());
viewpager.setAdapter(sliderAdapter); //The error is thrown here
// Inflate the layout for this fragment
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//Toast.makeText(view.getContext(),"Here",Toast.LENGTH_LONG).show();
}}
ViewPager Adapter Class:
public class SliderAdapter extends PagerAdapter {
Context context1;
LayoutInflater inflater;
public int[] slide_images = {
R.drawable.band,
R.drawable.studio,
R.drawable.videoshoot
};
public String[] slide_headings = {
"REHEARSAL PAD", "RECORDING STUDIO", "SESSION VIDEOSHOOT"
};
public String[] slide_desc ={
String.valueOf(R.string.rehearsal_desc),
String.valueOf(R.string.studio_desc),
String.valueOf(R.string.videoshoot_desc)
};
public SliderAdapter(Context context){
context1 = context;
}
#Override
public int getCount() {
return slide_headings.length;
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return view== (ConstraintLayout)object;
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
//ViewPager Sliding Images and Desc
inflater = (LayoutInflater)context1.getSystemService(context1.LAYOUT_INFLATER_SERVICE);
//inflater = LayoutInflater.from(context1);
View view = inflater.inflate(R.layout.slider_layout,container,false);
ImageView slideImageView = (ImageView) view.findViewById(R.id.SliderImageView);
TextView slideHeading = (TextView) view.findViewById(R.id.SliderTextView1);
TextView slideDesc = (TextView) view.findViewById(R.id.SliderTextView2);
slideImageView.setImageResource(slide_images[position]);
slideHeading.setText(slide_headings[position]);
slideDesc.setText(slide_desc[position]);
container.addView(view);
return view;
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((ConstraintLayout)object);
}}
And the Exception Logs are given below:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.soundflixstudios, PID: 13363
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.viewpager.widget.ViewPager.setAdapter(androidx.viewpager.widget.PagerAdapter)' on a null object reference
at com.example.soundflixstudios.onboarding.ViewPagerFragment.onCreateView(ViewPagerFragment.java:43)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7099)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:536)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
Any help is appreciated, and yes I have gone through multiple post in stackoverflow but didnt find any solutionhence reaching out with a new question!
Thanks in advance!
Edit: I have added the xml for "view_pager_fragment" layout
enter code here<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical"
tools:context=".onboarding.ViewPagerFragment">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/sliderViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1">
</androidx.viewpager2.widget.ViewPager2>
<LinearLayout
android:id="#+id/dotsLayout"
android:layout_width="wrap_content"
android:layout_height="66dp"
android:layout_gravity="center"
android:layout_weight="1"
android:orientation="horizontal">
</LinearLayout>

Root cause
In view_pager_fragment.xml file, you declare a ViewPager2 with id sliderViewPager but in ViewPagerFragment class, you use a ViewPager variable and assign a view with id viewPagerFragment to it.
Solution
Step 1. Change fragment_view_pager.xml to:
<?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:background="#color/white"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
android:id="#+id/sliderViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1">
</androidx.viewpager.widget.ViewPager>
<LinearLayout
android:id="#+id/dotsLayout"
android:layout_width="wrap_content"
android:layout_height="66dp"
android:layout_gravity="center"
android:layout_weight="1"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
Step 2. In ViewPagerFragment class, change your code from
viewpager = (ViewPager) view.findViewById(R.id.viewPagerFragment);
to
viewpager = (ViewPager) view.findViewById(R.id.sliderViewPager);

Can you add your xml file ( viewPagerFragment). In normal case, nullPointerException will show up when you missing references to your xml, or missing create xml tag( different screen- landscape/portrait)

Related

Having problems to pass data from recyclerview adapter to fragment

So I am developing a project with view pager that has 2 tabs with 2 different fragments. There's a card view in both of the fragments. When I click on one of the item in the card view, it should go to another fragment to load the web view with URLs that are passed from the recycler view adapter. I tried to pass the URLs from the adapter to the fragment to load the web view but the app keep on crashing in the emulator. I might be using the wrong method for this or there's something I didn't include in the program. I really need help!
main_activty.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<androidx.viewpager.widget.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CYBERSECURITY" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AI" />
</com.google.android.material.tabs.TabLayout>
</androidx.viewpager.widget.ViewPager>
</LinearLayout>
fragment_web.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/webView_Frame"
tools:context=".FragmentWeb">
<!-- TODO: Update blank fragment layout -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</WebView>
<ProgressBar
android:id="#+id/progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.view_pager);
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
}
MyRecyclerViewAdapter.java
final String URLs = news.getURLs();
Log.d("here",URLs);
myViewHolder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putString(KEY, URLs);
FragmentWeb fragmentWeb = new FragmentWeb();
fragmentWeb.setArguments(bundle);
fragmentWeb.getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.webView_Frame, fragmentWeb)
.commit();
}
});
Above are the codes I tried to pass the URLs to the FragmentWeb class. I tried with log.d to check and the URLs variable already contain all the URLs. I've also tried with fragmentWeb.getChildFragmentManager or even fragmentWeb.getFragmentManager but neither of them work and keep giving me different errors.
FragmentWeb.java
public class FragmentWeb extends Fragment{
private static final String KEY = "URLS";
private String URLs;
private ProgressBar progressBar;
private WebView webView;
public FragmentWeb() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
URLs = getArguments().getString(KEY);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_web, container, false);
progressBar = view.findViewById(R.id.progress_bar);
webView = view.findViewById(R.id.web_view);
return view;
}
public void loadWebPage()
{
webView.loadUrl(URLs);
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageStarted(WebView view, String URLs, Bitmap favicon) {
progressBar.setVisibility(View.VISIBLE);
webView.setVisibility(View.GONE);
}
#Override
public void onPageFinished(WebView view, String URLs) {
progressBar.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
}
});
}
#Override
public void onStart() {
super.onStart();
loadWebPage();
}
}
Above are the codes to load the web page with the URLs passed from the adapter.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.assignment4_task1, PID: 6803
java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.fragment.app.FragmentManager androidx.fragment.app.FragmentActivity.getSupportFragmentManager()' on a null object reference at com.example.assignment4_task1.MyRecyclerViewAdapter$1.onClick(MyRecyclerViewAdapter.java:66)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Here:
FragmentWeb fragmentWeb = new FragmentWeb();
fragmentWeb.setArguments(bundle);
fragmentWeb.getActivity().getSupportFragmentManager()
You're calling 'getActivity()' on fragmentWeb, but you've just created fragmentWeb above. That fragment is not loaded in any activity yet, so getActivity() returns null.
Get the current activity from the surrounding context, such as the RecyclerView's context or, if you declare the Adapter as an inner class of your Fragment, by using Fragment's getActivity().

Fragment inside ViewPager inside ViewGroup

Problem
As shown in the figure below, I have two tabs called "température" which are created in the same way (see mainFragment). In this two tabs, I have a viewpager to get previous graphics ( 05 august, 04 august,...).
The first tab works well but in the second, nothing appears. When debugging, I can see that the fragment is created in both cases. It's only on the second tab where the problem is. Even more, I can see the viewpager working when sliding to the left or right end.
I'm seeking since hours now and I don't understand where the problem is. Why the fragments don't appear ?
I'm using android.support.v13.app.FragmentStatePagerAdapter for the adapter.
Here is a short movie to show the problem :
https://www.dropbox.com/s/vf8qlrd75mdwijp/device-2017-08-06-214510.mp4?dl=0
Code
MainFragment
public class MainFragment extends Fragment implements BTListener {
// the different ID for the views.
private final static int ID_TEMPERATURE = 1;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.main,container,false);
final ViewGroup mainContainer = (ViewGroup) rootView.findViewById(R.id.main_container);
createTemperatureTab(mainContainer);
createTemperatureTab(mainContainer);
return rootView;
}
private void createTemperatureTab(ViewGroup mainContainer){
//inflate the view
ViewGroup view = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.main_list,mainContainer,false);
((TextView)view.findViewById(R.id.title_main_list)).setText("Température");
((TextView)view.findViewById(R.id.information_main_list)).setText("°C");
final ExpandableLayout expandableLayout = (ExpandableLayout) view.findViewById(R.id.expandable_layout);
CustomPager viewPager = (CustomPager) view.findViewById(R.id.viewpager);
LinearGraphAdapter linearGraphAdapter = new LinearGraphAdapter(getChildFragmentManager());
viewPager.setAdapter(linearGraphAdapter);
viewPager.setCurrentItem(linearGraphAdapter.getCount());
expandableLayout.setExpanded(false);
expandableLayout.setDuration(500);
expandableLayout.setInterpolator(new DecelerateInterpolator());
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(expandableLayout.isExpanded()) {
expandableLayout.collapse();
}
else {
expandableLayout.expand();
}
}
});
mainContainer.addView(view);
}
}
main_list
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/title_main_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:textSize="20sp" />
<TextView
android:id="#+id/information_main_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="80dp"
android:textSize="20sp" />
</LinearLayout>
<net.cachapa.expandablelayout.ExpandableLayout
android:id="#+id/expandable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.renaud.aquariumslinding.adapter.CustomPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.example.renaud.aquariumslinding.adapter.CustomPager>
</net.cachapa.expandablelayout.ExpandableLayout>
</LinearLayout>
LineGraphFragment
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.linear_graph_layout,container,false);
lineChart = (LineChart) rootView.findViewById(R.id.linear_graph);
initiateChart(lineChart); // not important for this case
drawChart(lineChart,dayOfYear); // not important for this case
return rootView;
}
linear_graph_layout
<?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="wrap_content">
<TextView
android:id="#+id/linear_graph_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:elevation="4dp"
android:textColor="#fff" />
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/linear_graph"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
LinearGraphAdapter
public class LinearGraphAdapter extends FragmentStatePagerAdapter {
public static int MAXIMUM_COUNT_PAGER = 7;
private int mCurrentPosition = -1;
public LinearGraphAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putInt(Constant.CUSTOM_PAGER_NUMBER,MAXIMUM_COUNT_PAGER-position);
Fragment fragment = new LinearGraphFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return MAXIMUM_COUNT_PAGER;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
Fragment fragment = (Fragment) object;
CustomPager pager = (CustomPager) container;
if (fragment != null && fragment.getView() != null) {
mCurrentPosition = position;
pager.measureCurrentView(fragment.getView());
}
}
}
}
Ok, after a night of research and reading the API I figured it out. I don't understand everything but it seems the v13 and v4 library have a conflict.
To override it, firstly :
Make sure that you called getChildFragmentManager() instead of getFragmentManager()
Create a different ID for all the different viewpageryou have. Those IDs must have at least 4 digits. Of course, it is better to have those in R.String
Set your ID in every viewpager by calling setID()
If it doesn't work, please clean and rebuild your project.
And finally, the reward :
I hope that it will help.

ViewPager and NullObjectReference error [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I've got an issue with setting an adapter to the ViewPager. Each time i get a NullObjectReference error. What's wrong with my code?
1) Layout:
<?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">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="4dp"
android:paddingTop="4dp" />
</android.support.v4.view.ViewPager>
</LinearLayout>
2) Java class:
public class FoodFragment extends Fragment {
Toolbar toolbar;
ViewPager viewPager;
TabsPagerAdapter pagerAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setRetainInstance(true);
((AppCompatActivity)getActivity())
.getSupportActionBar().setDisplayShowTitleEnabled(true);
((AppCompatActivity)getActivity())
.getSupportActionBar().setTitle(R.string.food);
toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
toolbar.setBackgroundColor(Color.parseColor("#f6a632"));
pagerAdapter = new TabsPagerAdapter(getActivity()
.getSupportFragmentManager());
viewPager = (ViewPager) getActivity().findViewById(R.id.view_pager);
viewPager.setAdapter(pagerAdapter);
return inflater.inflate(R.layout.fragment_food, container, false);
}
}
I always get this error when calling viewPager.setAdapter(pagerAdapter); line.
The reason is that your onCreateView. In fragment, you need to first inflate the view for fragment first, and then findViewById from this view.
You may see an example below:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_food, container, false);
// get your view by: rootView.findViewById()
// for example:
viewPager = (ViewPager) rootView.findViewById(R.id.view_pager);
// do others...
return rootView;
}

Must ViewPagers have a unique id within their Activity? (If they're backed by a FragmentStatePagerAdapter)

I have an activity with two ViewPagers both working with a FragmentStatePagerAdapter. But when the ViewPagers have no id, or both have the same id, they will not work correctly.
Activity layout (activity.xml):
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.app.MainActivity">
<FrameLayout
android:id="#+id/frame1"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<include layout="#layout/merge_pager" />
</FrameLayout>
<FrameLayout
android:id="#+id/frame2"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<include layout="#layout/merge_pager" />
</FrameLayout>
</LinearLayout>
Merge layout (merge_pager.xml):
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</merge>
Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
FrameLayout frame1 = (FrameLayout) findViewById(R.id.frame1);
FrameLayout frame2 = (FrameLayout) findViewById(R.id.frame2);
ViewPager vp1 = (ViewPager) frame1.getChildAt(0);
ViewPager vp2 = (ViewPager) frame2.getChildAt(0);
if (vp1 == null | vp2 == null) {
throw new NullPointerException();
}
vp1.setAdapter(new ColorAdapter(getSupportFragmentManager()));
vp2.setAdapter(new ColorAdapter(getSupportFragmentManager()));
}
private class ColorAdapter extends FragmentStatePagerAdapter {
public ColorAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int i) {
return new ColorFragment();
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
}
public static class ColorFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView tv = new TextView(container.getContext());
Drawable d = new ColorDrawable(randomColor());
tv.setBackgroundDrawable(d);
return tv;
}
public static int randomColor() {
return Color.rgb(random255(), random255(), random255());
}
public static int random255() {
return
(int) (Math.random() * (double) 255);
}
Using this code, the second ViewPager won't work. I suspected it might be due to clashing ids (R.id.view_pager), so I removed the id from the merge file. However, this results in a fatal exception:
FATAL EXCEPTION: main
android.content.res.Resources$NotFoundException: Unable to find resource ID #0xffffffff
What is up with this?
It says in the docs:
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
So at least it's documented that the adapter won't work without an id for its pager. I suppose you can then take 'valid' to mean 'unique in the activity view hierarchy'.

Null Object that is a child of a Fragment

I have a Fragment that is part of a ViewPager. In this Fragment I have a ViewGroup child. Now, why in my MainActivity's onCreate() after having instantiated my ViewPager and adapter, my Container is getting null?
Here is my onCreate():
private MyAdapter mAdapter;
private ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mContainerView = (ViewGroup) findViewById(R.id.container);
//Here mContainerView is already null
...
}
Here is the Fragment that is part of a ViewPager that contains mContainerView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- This is my ViewGroup -->
<LinearLayout android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:showDividers="middle"
android:divider="?android:dividerHorizontal"
android:animateLayoutChanges="true"
android:paddingLeft="16dp"
android:paddingRight="16dp" />
</ScrollView>
<TextView android:id="#android:id/empty"
style="?android:textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="32dp"
android:text="#string/message_empty_layout_changes"
android:textColor="?android:textColorSecondary" />
</FrameLayout>
If I'm reading your question correctly, you're trying to access the Fragment's View (and children) using the Activity's findViewById() method. That shouldn't work since the Fragment inflates its own layout and Fragments are not traditional Views.
If you know the Fragment is instantiated and you can retrieve it, you can get an instance of the ViewGroup using
yourFragment#getView().findViewById()
If not, you can make an interface that your Activity implements with a method that accepts a ViewGroup as the argument. Then in the Fragment's onCreateView(), have the Fragment pass the ViewGroup off to the interface. You can cast directly to your Activity, but an interface is cleaner.
Eg
public class Fragment {
public interface ViewGroupCreateListener{
public void onViewGroupCreated (ViewGroup v);
}
private ViewGroupCreateListener listener;
public void onAttach (Activity a){
super.onAttach (a);
listener = (ViewGroupCreateListener) a;
}
public View onCreateView (/*all its arguments here*/){
View v = inflater.inflate (R.layout.your_layout);
ViewGroup group = v.findViewById (R.id.container);
listener.onViewGroupCreated(group);
return v;
}
}
Your Activity would look something like:
public class MainActivity extends Activity implements ViewGroupCreateListener, OtherInterface1, OtherInterface2{
private ViewGroup mViewGroup;
public void onViewGroupCreated (ViewGroup v){
mViewGroup = v;
}
}
This is nice since if the pager re-instantiates the Fragment, the Activity still gets a valid instance of the ViewGroup.
Or, if depending on what you're actually trying to achieve with this ViewGroup, you may be able to do this processing inside the Fragment itself.

Categories

Resources