Introduction
Huh, this is a tough one. At least, I think so... To clear things up:
I did not find any answers to my question after searching the internet (using Google).
Everything I found was about people setting up the onClickListener
's for their View
's wrong. I guess it is the same problem in my case, but none of the other problems matched mine.
This seems to be the same problem... It has no answers.
Setup
I've got three Fragment
's set up together with a ViewPager
in my AppCompatActivity
.
viewPager = (ViewPager) findViewById(R.id.main_view_pager);
viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager()));
Handled by the SectionsPagerAdapter
.
public class SectionsPagerAdapter extends FragmentPagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return MainTextHolder.newInstance(tabIndicatorOnClick);
case 1:
return PostWriter.newInstance(tabIndicatorOnClick);
case 2:
return TopPage.newInstance(tabIndicatorOnClick);
default:
return Error.newInstance();
}
}
@Override
public int getCount() {
return 3;
}
// ... more methods
}
In each of the Fragment
's I have some content plus a custom TabIndicator
.
(the following xml
file is my View
's for the indicator)
<?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="wrap_content" >
<View
android:id="@+id/fragment_divider_one"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="one" />
<View
android:id="@+id/fragment_divider_two"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="two" />
<View
android:id="@+id/fragment_divider_three"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="three" />
</LinearLayout>
And then I set an OnClickListener
for each of those View
's (dividers) in the Fragment
's onCreateView(LayoutInflater inflater, ViewGroup Bundle savedInstanceState)
method. The OnClickListener
is already prepared in my Activity
where I also instantiate my ViewPager
so that I can change the current Item
(Fragment
/tab).
private final View.OnClickListener tabIndicatorOnClick = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view.getTag().toString().equals("one"))
viewPager.setCurrentItem(0, true); // second argument for smooth transition
else if (view.getTag().toString().equals("two"))
viewPager.setCurrentItem(1, true);
else if (view.getTag().toString().equals("three"))
viewPager.setCurrentItem(2, true);
}
};
I pass that OnClickListener
to the Fragment
's by putting it into my newInstance(View.OnClickListener tabIndicatorOnClick)
method.
This is for one of the fragments. It is identical for the others!
public static MainTextHolder newInstance(View.OnClickListener tabIndicatorOnClick) {
MainTextHolder fragment = new MainTextHolder();
Bundle args = new Bundle();
fragment.putIndicatorTabIndicatorOnClick(tabIndicatorOnClick);
fragment.setArguments(args);
fragment.setRetainInstance(true);
return fragment;
}
My putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick)
method is a Void
in an Interface
. It just applies the OnClickListener
to the Class
(Fragment
).
@Override
public void putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick) {
this.tabIndicatorOnClick = tabIndicatorOnClick;
}
Does it work
Yes it does. It works perfectly fine... until a ConfigurationChange
happens. In my case I tested it with changing the orientation.
The Problem
What happens after that ConfigurationChange
is that everything goes normally. The OnClickListener
gets applied to all View
's in all Fragment
's, but the tabIndicatorOnClick
OnClickListener
is a null object reference in the second and third Fragment
.
So in PostWriter and TopPage there isn't even really an OnClickListener
on the View
's for what ever reason. But it gets better: In MainTextHolder
Fragment
the tabIndicatorOnClick
is not a null object reference
, but it does not change the ViewPager
's Item
anymore. It runs the code, but it does not scroll the Tab
.
When turning on "Don't keep activities" ind Developer options of the device and leaving the app, all OnClickListener
's are null object references
. Even those in MainTextHolder
.
Summary
After the ConfigurationChange
the OnClickListener
gets passed into my first Fragment
, but it is no working properly and in the remaining Fragment
's it is not even passed / a null object reference
.
The issue can be replicated through destroying the Activity
and then reloading it.
In the end...
... I have no clue what is going wrong. I hope that I structured my question properly.
May be of interest
minSdkVersion: 14
targetSdkVersion: 25
I already have a SpringIndicator on my ViewPager
. This does not feature an OnClickListener
so I added my own "overlayed" indicators which have the needed OnClick
feature. I also like the look of it, but if you can give me a better solution for my TabIndicator
, I would also love to have that as an answer.
I came across the solution to put the method into the xml
:onClick
attribute multiple times, but for that I would need to create the same OnClickListener
for every Fragment
which is not really the nice way and it is also not solving my problem, but a way around it. - I would need to pass the ViewPager
into my Fragment
and then call that method from xml
which is, as I said, just another way of doing it and not the way I prefer to do it. Also I don't know if it works. I'll most likely test it.
Other OnClickListener
's in the Fragment
still work properly. So as I said the problem lays in the OnClickListener
itself not working right/being a null object reference
.
tabIndicator
also is anull object reference
in my firstFragment
(MainTextHolder). – Arezzini