last item removing error in ViewPager on TabFragment android - android

i have two custom button Add and Remove, And when i click on Add tab Work good, after when i remove tab its go ok, but when i remove last tab then i get following error.
java.lang.NullPointerException
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3699)
at android.view.ViewGroup.removeViewAt(ViewGroup.java:3663)
at app.burhanimumineenbrowser.HomeActivity$3.onClick(HomeActivity.java:184)
at android.view.View.performClick(View.java:4191)
at android.view.View$PerformClick.run(View.java:17229)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4963)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
When i remove first tab its del , second one also delete but after third tab i cant remove it, error say me null pointer.
Here is Add Button Code.
btNewtab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
COUNT_TAB+=1;
// viewPager.setAdapter(mAdapter);
actionBar.addTab(actionBar.newTab().setText("New Tabs")
.setTabListener(HomeActivity.this));
mAdapter.notifyDataSetChanged();
}
});
Remove button Code.
btCloseTab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(COUNT_TAB>0) {
if(TAB_CURRENT>=0 && PAGE_CURRENT>=0) {
System.out.println("CLOSE PAGE AND TAB : "+TAB_CURRENT+" AND "+PAGE_CURRENT);
COUNT_TAB -=1;
// int ichektab=TAB_CURRENT-1;
int ip=viewPager.getCurrentItem();
viewPager.removeViewAt(ip);
actionBar.removeTabAt(TAB_CURRENT);
//actionBar.removeTab(iTab);
mAdapter.notifyDataSetChanged();
// viewPager.destroyDrawingCache();
/* if(ichektab>0){
// viewPager.setCurrentItem(ichektab);
viewPager.setCurrentItem(ichektab);
//actionBar.removeTabAt(TAB_CURRENT);
}*/
}
}
}
});
My Adapter
public class TabsPageAdapter extends FragmentStatePagerAdapter {
private long baseId = 0;
public TabsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
return new MyWebBrowser();
}
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public int getCount() {
return COUNT_TAB;
}
}
} please kindly suggest me about this error. Thanks

Use this code in remove button:
before removing tab u making COUNT_TAB to reduce so it troughs NullPointerException
also in addtab button increment the count tab in last
btCloseTab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(COUNT_TAB>0) {
if(TAB_CURRENT>=0 && PAGE_CURRENT>=0) {
System.out.println("CLOSE PAGE AND TAB : "+TAB_CURRENT+" AND "+PAGE_CURRENT);
// int ichektab=TAB_CURRENT-1;
int ip=viewPager.getCurrentItem();
viewPager.removeViewAt(ip);
actionBar.removeTabAt(TAB_CURRENT);
//actionBar.removeTab(iTab);
mAdapter.notifyDataSetChanged();
COUNT_TAB -=1;
// viewPager.destroyDrawingCache();
/* if(ichektab>0){
// viewPager.setCurrentItem(ichektab);
viewPager.setCurrentItem(ichektab);
//actionBar.removeTabAt(TAB_CURRENT);
}*/
}
}
}
});
View Pager page change listener
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener(){
#Override
public void onPageScrolled(int i, float v, int i2) {
NUM_TABS=i+1;
btTabCount.setText(""+NUM_TABS);
}
#Override
public void onPageSelected(int i) {
getActionBar().setSelectedNavigationItem(i);
PAGE_CURRENT=i;
System.out.println("CURRENT PAGE DISCRIPTION : "+PAGE_CURRENT);
mAdapter.notifyDataSetChanged();
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
Tab listener methods
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mAdapter.notifyDataSetChanged();
viewPager.setCurrentItem(tab.getPosition());
TAB_CURRENT=tab.getPosition();
iTab=tab;
System.out.println("CURRENT TAB DISCRIPTION : "+TAB_CURRENT);
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
//viewPager.setCurrentItem(tab.getPosition());
}

Finally i solve error.
Th reason is viewpager pager screen limit. By default there viewpager have Two page limit, but i write first time i used this code
viewPager.setOffscreenPageLimit(COUNT_TAB);
And i solved it
viewPager.setOffscreenPageLimit(500);
and if use COUNT_TAB then add button code is
btNewtab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// COUNT_TAB+=1;
// viewPager.setAdapter(mAdapter);
actionBar.addTab(actionBar.newTab().setText("New Tabs")
.setTabListener(HomeActivity.this));
COUNT_TAB+=1;
mAdapter.notifyDataSetChanged();
viewPager.setOffscreenPageLimit(COUNT_TAB);
}
});
Put pager limit after notifydatasetchanged.
Hope you guys understand.

Related

How to know whether the page is selected from Swipe or Click of Tab of Viewpager

I have a ViewPager which Toolbar tabs.
I have to know how many times user clicked tabs and how many times user swiped and selected a page.
I am using ViewPager.OnPageChangeListener() for this purpose.
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override public void onPageSelected(int position) {
// Here i am sending the GA event
}
#Override public void onPageScrollStateChanged(int state) {
}
});
OnPageSelected is called for both click and swipe of page.
How will I differentiate the page selected is from click of tabs or its from swipe of Viewpager ?
Here is my solution. I am basing on single variable.
public class MainActivity extends AppCompatActivity {
// remember last action
private Action lastAction = Action.RESET;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
mViewPager = findViewById(R.id.viewPager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
// No-op
}
#Override
public void onPageSelected(int i) {
if (lastAction == Action.RESET) {
lastAction = Action.SWIPE;
Log.d(TAG, "onPageSelected: SWIPED");
} else {
lastAction = Action.RESET;
}
}
#Override
public void onPageScrollStateChanged(int i) {
// No-op
}
});
mTabLayout = findViewById(R.id.tabLayout);
mTabLayout.setupWithViewPager(mViewPager);
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
if (lastAction == Action.RESET) {
lastAction = Action.SELECT;
Log.d(TAG, "onPageSelected: SELECTED");
} else {
lastAction = Action.RESET;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
// No-op
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
// No-op
}
});
}
}
Limitation:
Content for viewPager must be loaded before adding listeners because this solutions is basing on ordered calls (onTabSelected, onPageSelected).
Preview:
In this example I will be checking if the user selected the page at index 1 by swiping or by tapping the tab:
Note: You can use tabLayout.getChildAt(0) to get the main sliding layout, and
((ViewGroup) tabLayout.getChildAt(0)).getChildAt(desiredPosition) //to get the tab at desired position
Using this, we add onClickListener to the desired tab and once clicked, its onClick() method will be called first followed by the onTabSelected() method of the TabSelectedListener of the TabLayout.
private Boolean tabClicked = false; //variable which determines after entering the onTabSelected() method, if onClick was called or not
((ViewGroup) tabLayout.getChildAt(0)).getChildAt(1).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tabClicked = true;
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
if(tab.getPosition()==1){
if(tabClicked){
//your tab was clicked, do work here
}
else{
//your tab was swiped, do some work here
}
tabClicked = false;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {}
#Override
public void onTabReselected(TabLayout.Tab tab) {}
});
The tabview you use, is a textview. So there will be onclicklistener for this textview. You could track the tab click on onClick() method of listener!
Try this
fun onTabClickedListener(callback: String.() -> Unit){
tabContainer?.let { tabContainer->
for (i in 0 until tabContainer.tabCount) {
val text = tabContainer.getTabAt(i)?.text.toString() ?: ""
(tabContainer.getChildAt(0) as ViewGroup).getChildAt(i).tag = text
(tabContainer.getChildAt(0) as ViewGroup).getChildAt(i).setOnClickListener {
callback(text)
}
}
}
}```

Hide/Show FloatingActionButton on tab Click

I have a SlidingTabLayout with this pageListener, when I scroll to another tab, the FAB hides and then shows again, this is correct, the problem is that it doesn't work when I click tab, it just hides and doesn't reappear until I scrollPage again. Any ideas? (I'm using support design library of course)
private ViewPager.OnPageChangeListener pageListener = new
ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
Log.i("SCROLL", "onPageSelected");
fab.show()
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
Log.i("SCROLL", "onPageScrolled");
if(fab.isShown()) {
fab.hide();
}
}
#Override
public void onPageScrollStateChanged(int arg0) {
Log.i("SCROLL", "onStateChanged: "+arg0);
fab.show();
}
};

Android: Replacing fragments inside tabs

So I am trying to have a screen with three fragments in different tabs, and on one of them have them switch to be another fragment, but I am unable to figure out how I could do this. I have looked at other similar questions, however, I cannot seem to get them working. So if someone could help me exactly figure it out that would be great.
My tabsadapter is this
public class Tabsadapter extends FragmentStatePagerAdapter {
private int TOTAL_TABS = 3;
public Tabsadapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new fragment1();
case 1:
return new fragment2();
case 2:
return new fragment3();
return null;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return TOTAL_TABS;
}
}
and my main is this:
public class main extends ActionBarActivity implements android.support.v7.app.ActionBar.TabListener {
private ViewPager tabsviewPager;
private ActionBar mActionBar;
private Tabsadapter mTabsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabsviewPager = (ViewPager) findViewById(R.id.tabspager);
mTabsAdapter = new Tabsadapter(getSupportFragmentManager());
tabsviewPager.setAdapter(mTabsAdapter);
getSupportActionBar().setHomeButtonEnabled(false);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab1 = getSupportActionBar().newTab().setText("Month").setTabListener(this);
Tab tab2 = getSupportActionBar().newTab().setText("Week").setTabListener(this);
Tab tab3 = getSupportActionBar().newTab().setText("Day").setTabListener(this);
getSupportActionBar().addTab(tab2);
getSupportActionBar().addTab(tab2);
getSupportActionBar().addTab(tab3);
tabsviewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
getSupportActionBar().setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
}
#Override
public void onTabSelected(Tab selectedtab, FragmentTransaction arg1) {
tabsviewPager.setCurrentItem(selectedtab.getPosition()); //update tab position on tap
}
#Override
public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {
}
}
Any help anyone can provide would be greatly appreciated. Thanks!
On Android Studio, you can create automatically the code for this :
Right click on a folder of your project, choose New -> Tabbed Activity.
Choose the navigation style. (ActionBarTabs if I understood you well)
Change other fields if needed
Click finish
You now have a brand new Tabbed Activity to use :)
You can read the generated code if you want to understand how it works.
Please ask me if you need any help.

Updating the contents on tab changed in view pager

I am scracthing my head for past 1 day but unable to find the solution.
In mine application there are two tabs under the toolbar
First tab is USER-TAB
the second one is ADMIN-TAB
In both the tabs there are the listView. When a ListItem on the USER-TAB is clicked a dialog appears and user take some action.
Now after this when the ADMIN-TAB is Selected the Admin should get refreshed with new sets of data. But It's not. On selecting the ADMIN-TAB the onResume() method and everyting is getting called but it is not able to update the list.
I wont be able to write the Whole code, I am giving some snippet.
Basically I have taken the code from this link
https://github.com/codepath/android_guides/wiki/Sliding-Tabs-with-PagerSlidingTabStrip
In My Main Activity I have written the OpPageChangeListener.
public class MaterialTab extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.material_main_sample);
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new SampleFragmentPagerAdapter(getSupportFragmentManager()));
// Give the PagerSlidingTabStrip the ViewPager
PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
// Attach the view pager to the tab strip
tabsStrip.setViewPager(viewPager);
tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position == 0){
MileUserFragment userFragment = new MileUserFragment();
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(userFragment);
ft.attach(userFragment);
ft.commit();
} if(position == 1){
MileAdminFragment adminFragment = new MileAdminFragment();
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(adminFragment);
ft.attach(adminFragment);
ft.commit();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
OnPageSelected You can see I am detaching and reattaching the fragment.Everything is working fine. Both Fragments OnResume() are getting called but the List is not getting changed. I don't undrstand why
For additional assistance i am adding snippet one Fragment. Hope this will give some Idea where i might be going wrong
public class MileUserFragment extends Fragment {
#Override
public void onResume() {
super.onResume();
new GetAdminDbTask().execute();
if(!internetUtil.isConnectedToInternet(getActivity())){
mSwipeRefreshLayout.setRefreshing(false);
mSwipeRefreshLayout.setEnabled(false);
}
}
public class GetAdminDbTask extends AsyncTask<Admin, Void, String> {
#Override
protected String doInBackground(Admin... parmas) {
_adminList = shipmentDbHandler.getAllAdmin();
return "";
}
#Override
protected void onPostExecute(String str) {
mAdminAdapter = new AdminAdapter(getActivity(), _adminList);
adminListView.setAdapter(mAdminAdapter);
mAdminAdapter.notifyDataSetChanged();
// Set the refresh Listener to false after the list has been loaded with new set of data
if (mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}
if(_adminList.size() > 0 ){
mAdminAdapter = new AdminAdapter(getActivity(), _adminList);
adminListView.setAdapter(mAdminAdapter);
mAdminAdapter.notifyDataSetChanged();
}
}
}
}
public class SampleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "Tab1", "Tab2" };
private FragmentManager fragmentManager;
public SampleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
this.fragmentManager = fm;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
FragmentTransaction ft = null;
if(position == 0){
MileUserFragment userFragment = new MileUserFragment();
return userFragment;
}
if(position == 1){
MileAdminFragment adminFragment = new MileAdminFragment();
return archiveFragment;
}
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
Haah.. Finally i got an answer to after an heck of losing almost 1 and half days. It might be not completely good answer but atleast it is one of the closest I got.
First of all MainActivity.java looks like:
tabs.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
int scrollPosition = 0;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(position == 0){
scrollPosition = 0;
}
if(position == 1){
scrollPosition = 1;
}
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
if(state == pager.SCROLL_STATE_IDLE){
if(scrollPosition == 0 && application.isActiveAction()){
viewPagerAdapter.notifyDataSetChanged();
application.setActiveAction(false);
}
if(scrollPosition == 1 && application.isArchiveAction()){
viewPagerAdapter.notifyDataSetChanged();
application.setArchiveAction(false);
}
}
}
});
Now what I have done here is I have set OnPageChangeListener and in this I am keeping track of the position whenever the tabs are changing. For my needs what i have done is i have created two boolean variables and setting it when any content on those tab are changing in Application scope. Now when the contents on one tab has been changed or some Action are done I am calling
viewPagerAdapter.notifyDataSetChanged() // Now this is the real gem
after invoking this it will make a call to the ViewPagerAdapter function
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE; // This will get invoke as soon as you call notifyDataSetChanged on viewPagerAdapter.
}
Also the Point is your ViewPagerAdapter should extend FragmentStatePageAdapter. Now the Point is
PagerAdapter.POSITION_NONE
will not cache the fragment and reload a new fragment for that tab position.
Basic idea is we should not make or retutn PagerAdapter.POSITION_NONE everytime on sliding of tab since it destroys the cached element and reload the fragment which affects UI performance.
So finally the basic thing is always check that whether on calling viewPagerAdapter.notifyDataSetChanged() the function getItemPosition() should also gets invoked. Hope it will help somebody. For better perfomance you can make changes according to your requirement.
I got the needed breakthrough and understanding from this post : #Louth Answer
Remove Fragment Page from ViewPager in Android
Just put
viewPager.setCurrentItem(tab.getPosition());
in your onTabSelected method like:
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});

Tabhost and fragment Activity

I am unable to understand properly what these functions are used for in my FragmentActivity class.
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
// on changing the page
// make respected tab selected
position = pos;
actionBar.setSelectedNavigationItem(pos);
new Getquestions().execute();
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
I am using a view pager for page sliding, and what I want to do is, if a condition is false, for example I have three edit texts in fragment one, and if a user wants to slide to fragment two without filling up the texts then the must not slide.
I tried to find any such example but I am unable to find it. Can anyone help? Understanding these functions will help me implement my thing I guess
I have got an answer from another forum
public class CustomViewPager extends ViewPager {
private boolean isPagingEnabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.isPagingEnabled = true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.isPagingEnabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.isPagingEnabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean b) {
this.isPagingEnabled = b;
}
}
Now when you want to disable swiping just setPagingEnable = false;
and in the layout file replace any <com.android.support.V4.ViewPager> tags with <com.yourpackage.CustomViewPager> tags.
Documented advantage of fragments, is that they can be added or removed to the activity on a run-time.
What you want is have a single fragment initially, and once the requirements are fulfilled - add a next fragment to your activity.

Categories

Resources