Delete fragment in secure way from FragmentPagerAdapter - android

I am trying to implement a Gallery with a FragmentPagerAdapter on a ViewPager. Each fragment has a "delete" button which deletes the file.
Then I am trying to remove this fragment and scroll to next fragment when a callback of a AsyncTask is called.
In summary, when the delete button is touched first, delete the file in a remote FTP server and then remove the local file.
This is the Activity container of the ViewPager
public class MediaViewerActivity extends FragmentActivity implements OnFTPResult{
(...)
protected void onCreate(Bundle savedInstanceState) {
ArrayList<String> multimedia;
viewPager = (ViewPager) findViewById(R.id.pager);
multimedia = getFiles();
MediaViewerAdapter adapter;
adapter = new MediaViewerAdapter(getSupportFragmentManager(), MediaViewerActivity.this, multimedia);
viewPager.setOffscreenPageLimit(2);
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(position);
(...)
}
#Override
public void onActionPerformed(String result) {
switch (result) {
case "Done delete":
//remove the fragment and local file
break;
}
}
}
This is the code of the adapter for the ViewPager
public class MediaViewerAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener{
(...)
public MediaViewerAdapter(FragmentManager fm, Context _ctx,ArrayList<String> imagePaths) {
super(fm);
manager = fm;
_imagePaths = imagePaths;
ctx = _ctx;
}
}
(...)
#Override
public Fragment getItem(int position) {
Fragment fragment;
String[] fileExtensionCaching = _imagePaths.get(position).split("\\.");
String currentExtension = fileExtensionCaching[fileExtensionCaching.length - 1];
Bundle args = new Bundle();
args.putString("path", _imagePaths.get(position));
if((currentExtension.equals("pdf")))
fragment = FragmentPDFViewer.newInstance(args);
else
if((currentExtension.equals("jpg") || currentExtension.equals("png") || currentExtension.equals("gif"))) {
fragment = FragmentImageViewer.newInstance(args);
}
else{
fragment = FragmentVideoPlayer.newInstance(args);
}
return fragment;
}
#Override
public int getCount() {
return _imagePaths.size();
}
(...)
}
And this is a slice of the AsyncTask class
#Override
protected void onPostExecute(String response) {
((OnFTPResult)ctx).onActionPerformed(response);
}
Which would be the best safety way to remove the current Fragment and then scroll to next (If there is)?
Thanks

Related

Android - MVP - Fragments, Presenter and ViewPager

I have an Activity1 that contains several fragments through a ViewPager.
Each fragment has a Presenter. For some reason when I rotate the screen, the fragment is recreated and lose the relationship with the presenter
I'm doing the following
open activity 1 (contains viewPager with fragment)
open activity 2
rotate the screen
Press back button
Apparently the fragment is recreated and I get the following error
Caused by: java.lang.NullPointerException: Attempt to invoke
interface method 'void ....Presenter1.subscribe()' on a null object
reference at ....Fragment1.onResume(Fragment1.java:72)
My Activity1 contains 2 views (layout and layout-normal-land)
The code of activity1 is as follows
#Override
protected void onCreate(Bundle savedInstanceState) {
...
final ViewPager viewPager = (ViewPager) findViewById(R.id.htab_viewpager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.htab_tabs);
...
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
the code of the ViewPagerAdapter class is the following:
private class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<String> mFragmentTitleList = Arrays.asList("Fragment1", "Fragment2");
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
if (position == 0){
Fragment1 fragment = Fragment1.newInstance();
new Presenter1(fragment);
return fragment;
}else if (position == 1){
Fragment2 fragment = Fragment2.newInstance();
new Presenter2(fragment);
return fragment;
}
return null;
}
#Override
public int getCount() {
return mFragmentTitleList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
The code of each Fragment is the following
public class Fragment1 extends Fragment {
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
}
#Override
public void onResume() {
super.onResume();
mPresenter.subscribe();
}
#Override
public void onPause() {
super.onPause();
mPresenter.unsubscribe();
}
#Override
public void setPresenter(#NonNull Presenter1 presenter) {
mPresenter = checkNotNull(presenter);
}
....
}
The code of each presener
public class Presenter1 {
private final Fragment1 view;
public PerfilAlumnoCalificacionesPresenter(Fragment1 view ....) {
....
this.view = view
this.view.setPresenter(this);
}
....
}
How can i fix this? I do not understand why the fragment is recreated if it contains setRetainInstance (true)
What is the best way to initialize the Presenter so that the Fragments do not lose the relation?
thanks, sorry for my english

Get fragment activity outside of Fragment.OnCreateView()

I have a Fragment with a TableLayout. The data in the table is from a SQLite db. The SQLite db is populated from a RESTful webservice in an AsyncTask in the MainActivity. The Fragment must wait for the task to complete before populating the table. The Fragment listens for the task onPostExecute() method to be called. When it is, the method onLoadAndStoreComplete in the Fragment is called. This all works.
What doesn't work is that I need the fragment activity in order to create new TableRows and TextViews in onLoadAndStoreComplete and I can't get it.
I've tried:
- making a class member fragmentActivity and assigning in onCreateView(), but by the time it gets to onLoadAndStoreComplete(), it is null.
- calling this.getActivity() again in onLoadAndStoreComplete(), but it returns null.
How do I get the fragment activity?
MyFragment.java:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
fragmentActivity = this.getActivity(); // return value is valid
...
}
#Override
public void onLoadAndStoreComplete() {
fragmentActivity = this.getActivity(); // returns null
...
}
from MainActivity.java (extends ActionBarActivity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = this;
setContentView(R.layout.activity_main);
Resources resources = getResources();
String[] tabTitleArray = { resources.getString(R.string.first_fragment),
resources.getString(R.string.second_fragment),
resources.getString(R.string.help_fragment) };
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
mAdapter = new TabsPagerAdapter(this.getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tab_name : tabTitleArray) {
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
// On swiping the ViewPager, select the respective tab
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position) ;// on changing the page, make respected tab selected
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
String url = "http://myrestfulwebservice";
Fragment secondFragment = mAdapter.getItem(SECOND_TAB);
new LoadAndStoreDataTask((OnLoadAndStoreCompleteListener)secondFragment).execute(url);
}
} // end OnCreate
TabsPagerAdapter.java
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
case 2:
return new HelpFragment();
}
return null;
}
#Override
public int getCount() {
return 3; // get item count - equal to number of tabs
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++) {
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#FF0000")); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#0000FF")); // selected
}
}
I haven't tested this, but it seems to me that it would work.
Add a Context parameter to the constructor for both TabsPagerAdapter and MyFragment.
Something like this:
TabsPagerAdapter.java:
public class TabsPagerAdapter extends FragmentPagerAdapter {
private Context mCtx;
public TabsPagerAdapter(FragmentManager fragmentManager, Context context) {
super(fragmentManager);
mCtx = context;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment(mCtx);
case 1:
return new SecondFragment(mCtx);
case 2:
return new HelpFragment(mCtx);
}
return null;
}
#Override
public int getCount() {
return 3; // get item count - equal to number of tabs
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++) {
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#FF0000")); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#0000FF")); // selected
}
}
MainActivity.java:
mAdapter = new TabsPagerAdapter(this.getSupportFragmentManager(), this);
MyFragment.java (do this in FirstFragment, SecondFragment, and HelpFragment):
public static class MyFragment extends Fragment {
private Context fragmentActivity ;
public MyFragment(Context context){
fragmentActivity = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//.........
return rootView;
}
#Override
public void onLoadAndStoreComplete() {
//do something with fragmentActivity
}
}
It seems the AsyncTask starts too early. suggest loading the db in onActivityCreated(), it's be called after onCreateView
#Override
public void onActivityCreated (Bundle savedInstanceState) {
//load your db here
}

Passing data between two Fragments: NullPointerException

I'm having an Activity that hosts two Fragments. One which contains an EditText and one that shows the input in a GridView. Fragment1 implements an interface to notify when the user wants to save the input. In the Activity I want to pass the data to the ArrayAdapter of Fragment2 but here I get the NullPointerException.
Activity:
public class SwipeTest extends FragmentActivity implements TestFragment1
.OnFragmentInteractionListener {
private final String[] tabs = {"Test 1", "Test 2"};
private ViewPager pager;
private ActionBar actionBar;
private TabsPagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.pager = new ViewPager(this);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup
.LayoutParams.MATCH_PARENT,
ViewGroup
.LayoutParams.MATCH_PARENT);
this.pager.setLayoutParams(params);
setContentView(this.pager);
this.actionBar = getActionBar();
this.adapter = new TabsPagerAdapter(
getSupportFragmentManager());
this.pager.setAdapter(this.adapter);
this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
setUpViewPager();
setUpActionBar();
}
/**
* Sets up the ViewPager and adds an OnPageChangeListener
*/
private void setUpViewPager() {
this.pager.setAdapter(this.adapter);
// pager needs an id; crashes if it has none
this.pager.setId(123456789);
// Set up the listener
ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager
.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i2) {
}
#Override
public void onPageSelected(int i) {
SwipeTest.this.actionBar.setSelectedNavigationItem(i);
}
#Override
public void onPageScrollStateChanged(int i) {
}
};
this.pager.setOnPageChangeListener(onPageChangeListener);
}
/**
* Sets up the ActionBar with it's tabs and adds an ActionBar.TabListener to
* them
*/
private void setUpActionBar() {
this.actionBar = getActionBar();
this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set up listener
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction
fragmentTransaction) {
SwipeTest.this.pager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction
fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction
fragmentTransaction) {
}
};
for (String tab_name : this.tabs) {
this.actionBar.addTab(
this.actionBar.newTab()
.setText(tab_name)
.setTabListener(tabListener));
}
}
/**
* Interface method of Fragment1
*/
#Override
public void onFragmentInteraction(String s) {
// This gets the fragment correct
TestFragment2 fragment = (TestFragment2) ((TabsPagerAdapter) pager
.getAdapter()).getItem(1);
// This assigns null to adapter
ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment
.getAdapter();
adapter.add(s);
adapter.notifyDataSetChanged();
}
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new TestFragment1();
case 1:
return new TestFragment2();
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
}
Fragment1:
public class TestFragment1 extends Fragment {
private OnFragmentInteractionListener mListener;
private EditText edit;
public TestFragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
LinearLayout layout = new LinearLayout(getActivity());
layout.setLayoutParams(params);
this.edit = new EditText(getActivity());
Button btn = new Button(getActivity());
btn.setText("Save");
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onButtonPressed();
}
});
layout.addView(this.edit);
layout.addView(btn);
return layout;
}
public void onButtonPressed() {
if (this.mListener != null) {
String input = this.edit.getText().toString();
this.mListener.onFragmentInteraction(input);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
this.mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement " +
"OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
this.mListener = null;
}
public interface OnFragmentInteractionListener {
public void onFragmentInteraction(String s);
}
}
Fragment2:
public class TestFragment2 extends Fragment {
private final List<String> data = new ArrayList<String>();
private ArrayAdapter<String> adapter;
public TestFragment2() {
// Required empty public constructor
}
public ArrayAdapter getAdapter() {
return this.adapter;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
GridView view = new GridView(getActivity());
GridView.LayoutParams params = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(params);
this.data.add("Hello");
this.data.add("World");
this.adapter = new ArrayAdapter(getActivity(),
android.R.layout
.simple_list_item_1,
this.data);
view.setAdapter(this.adapter);
return view;
}
}
I don't know why ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment.getAdapter(); is null. So, how do I get access to the fields of Fragment2?
It seems problem about lifecycle. As you may know, onCreateView() is async method, so fragment instance could be accessed before setAdapter().
My suggestion is to create TestFragment2 instance in SwipeTest#onCreate(). Also, your code creates new instance every time button pressed. It seems not good idea.
The problem was within the PagerAdapter. I used getItem() to recieve the Fragment which is bound to the tab's position. The mistake was that I returned a new instance of that Fragment instead of returning the existing Fragment. Since that new Fragment has never been shown the Fragment's onCreateView() and hence setUpAdapter() has never been called. That's why I recieved NPE in
ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment
.getAdapter();
adapter.add(s);
Approach[*]:
public class TabsPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<Fragment>();
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
mFragments.add(0, new TestFragment1());
mFragments.add(1, new TestFragment2());
}
#Override
public Fragment getItem(int index) {
if (index > (mFragments.size() - 1) )
return null;
return mFragments.get(index);
}
#Override
public int getCount() {
return mFragments.size();
}
}
[*] Untested since I changed my code and don't use the PagerAdapter anymore but I think the solution is comprehensible.
If the pager has never shown the second fragment, when your fragment1 interface callback is called the pager returns null:
// This gets the fragment correct
TestFragment2 fragment = (TestFragment2) ((TabsPagerAdapter) pager
.getAdapter()).getItem(1);
So your subsequent call to getAdapter() will result in the NPE.

Navigating between Fragments while using a ViewPager

I've looked at so many questions here that I don't even know exactly what I'm looking for.
I have a simple app that uses a ViewPager. It has 3 tabs and there is a fragment for each tab. The first fragment contains a ListView. I want to be able to click on an element in the ListView and have that bring me to a different fragment.
So basically I want to remove the fragment that contained the ListView once an element is clicked and add in a new fragment. I've tried to do this in a few different ways with none working.
The last thing I tried was to edit the TabsPageAdapter once an element was clicked which pretty much works except when I press the back button it exits the app. Also it doesn't seem like the cleanest way of doing this.
TabsPagerAdapter
public class TabsPagerAdapter extends FragmentStatePagerAdapter {
SherlockFragment mf;
TalkingPointsFragment tpf;
ContactFragment gf;
int mode = 0;
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
mf = new CanvassFragment();
tpf = new TalkingPointsFragment();
gf = new ContactFragment();
}
public TabsPagerAdapter(FragmentManager fm, int mode)
{
super(fm);
if(mode == 0)
{
mf = new CanvassFragment();
tpf = new TalkingPointsFragment();
gf = new ContactFragment();
}
else if(mode == 1)
{
mf = new ContactFragment();
tpf = new TalkingPointsFragment();
gf = new ContactFragment();
}
}
#Override
public SherlockFragment getItem(int index) {
switch (index) {
case 0:
return mf;
case 1:
return tpf;
case 2:
return gf;
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object)
{
}
}
The onclick code:
ViewPager viewp = (ViewPager) getActivity().findViewById(R.id.pager);
TabsPagerAdapter mAdapter = new TabsPagerAdapter(getActivity().getSupportFragmentManager(),1);
viewp.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
layout_main.xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:actionBarTabStyle="#drawable/actionbar_tab_indicator">
I FragmentStatePagerAdapter too and when a user selects map from the ActionBar, I add the GoogleMapsFragment on top of the FragmentStatePagerAdapter:
// create a new map
mapsFragment = GoogleMapFragment.newInstance();
// Then we add it using a FragmentTransaction.
FragmentTransaction fragmentTransaction = getSupportFragmentManager()
.beginTransaction();
fragmentTransaction.add(android.R.id.content, mapsFragment,
FRAGMENT_MAP_TAG);
fragmentTransaction.commit();
For your case you would probably need to add it to the backstack too, which I have not because in my app the user has to navigate back using the ActionBar.
Thought this approach could work for you too when a user selects an item from your list.
Of course this has the disadvantage of not being able to use the FragmentStatePagerAdapter until the user navigates back. So I am not sure wether that would be acceptable for your app.
Ok, so this took a bit more code that I imagined. Hope you get the idea:
public class MainClass extends FragmentActivity implements CanvassCallback {
// save a single reference to ViewPager and TabsPagerAdapter
private ViewPager mViewPager;
private TabsPagerAdapter mAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mViewPager = (ViewPager) findViewById(R.id.pager);
this.mAdapter = new TabsPagerAdapter(getSupportFragmentManager(), this);
mViewPager.setAdapter(mAdapter);
...
}
// from the CanvassCallback interface
public void itemSelected() {
mAdapter.canvassSelected();
mAdapter.notifyDataSetChanged();
}
#Override
public void onBackPressed() {
if (mViewPager.getCurrentItem() == 0 && mAdapter.isCanvassSelected() {
mAdapter.canvassSelected();
mAdapter.notifyDataSetChanged();
}
else {
super.onBackPressed();
}
}
}
Mockup of your CanvassFragment showing the callback
public class CanvassFragment extends SherlockFragment {
public interface CanvassCallback {
public void itemSelected();
}
private CanvassCallback canvassCallback;
public void setCanvassCallback(CanvassCallback canvassCallback) {
this.canvassCallback = canvassCallback;
}
...
// The onClick of your item
private void onClick() {
// notify your activity that an item was selected
canvassCallback.itemSelected();
}
}
The registeredFragments are not strictly needed but I think it provides some value if your need to call methoods on your Fragment from activity.
public class TabsPagerAdapter extends FragmentStatePagerAdapter {
// see upvoted answer from http://stackoverflow.com/questions/8785221/retrieve-a-fragment-from-a-viewpager
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
private boolean canvassSelected = false;
private CanvassCallback canvassCallback;
public TabsPagerAdapter(FragmentManager fm, CanvassCallback canvassCallback) {
super(fm);
this.canvassCallback = canvassCallback;
}
public void canvassSelected() {
canvassSelected = !canvassSelected;
}
public boolean isCanvassSelected() {
return canvassSelected;
}
#Override
public SherlockFragment getItem(int index) {
switch (index) {
case 0:
if (canvassSelected)
return new ContactFragment();
CanvassFragment canvassFragment = new CanvassFragment();
// this ensures that your Activity gets notified when an item is clicked
canvassFragment.setCanvassCallback(canvassCallback);
return canvassFragment;
case 1:
return new TalkingPointsFragment();
case 2:
return new ContactFragment();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Log.d(TAG, "instantiateItem " + position);
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
Log.d(TAG, "destroyItem " + position);
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
}

Viewpager adapter not changing views

i have an activity with actionbarsherlock TabsNavigation (3 tabs) and when I press a tab i change the viewpager adapter of the corresponding fragment. it is working fine, the thing is that when I click on another tab besides the first created, the first page is always the one of that first tab. I tried to put invalidate() before changing the adapter, but it isnt working. anyone has any idea? here is the code:
public class Tabsteste2 extends SherlockFragmentActivity implements TabListener {
static AdapterOpiniao mOdapter;
static AdapterDados mDdapter;
static AdapterFoto mFdapter;
Bundle extras;
JSONParser jsonParser = new JSONParser();
SharedPreferences mPrefs;
static ViewPager mPager;
static int countopiniao;
static int countdados;
static int countfoto;
JSONArray perguntas = null;
PageIndicator mIndicator;
static ArrayList<HashMap<String, String>> opiniaolist;
static ArrayList<HashMap<String, String>> dadoslist;
static ArrayList<HashMap<String, String>> fotolist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabsteste2);
opiniaolist = new ArrayList<HashMap<String, String>>();
dadoslist = new ArrayList<HashMap<String, String>>();
fotolist = new ArrayList<HashMap<String, String>>();
mPager = (ViewPager)findViewById(R.id.pager);
extras = getIntent().getExtras();
Boolean opiniaoflag = extras.getBoolean("opiniaoflag");
Boolean dadosflag = extras.getBoolean("dadosflag");
Boolean fotoflag = extras.getBoolean("fotoflag");
countdados= extras.getInt("countdados");
countopiniao=extras.getInt("countopiniao");
countfoto=extras.getInt("countfoto");
mPrefs = getSharedPreferences("mPrefs1",MODE_PRIVATE);
Log.d("countdados",""+countdados);
Log.d("countfoto",""+countfoto);
Log.d("countopiniao",""+countopiniao);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
if(opiniaoflag==true){
ActionBar.Tab opiniaotab = getSupportActionBar().newTab();
opiniaotab.setText("OpiniĆ£o");
opiniaotab.setTag("op");
opiniaotab.setTabListener(this);
mOdapter = new AdapterOpiniao(getSupportFragmentManager());
Log.d("Opiniao",""+opiniaotab.getTag());
getSupportActionBar().addTab(opiniaotab);
}if(dadosflag == true){
ActionBar.Tab dadostab = getSupportActionBar().newTab();
dadostab.setText("Dados");
dadostab.setTag("dd");
mDdapter = new AdapterDados(getSupportFragmentManager());
dadostab.setTabListener(this);
Log.d("Dados",""+dadostab.getTag());
getSupportActionBar().addTab(dadostab);
}
// mDdapter = new AdapterDados(getSupportFragmentManager());
if(fotoflag==true){
ActionBar.Tab fotostab = getSupportActionBar().newTab();
fotostab.setText("Fotos");
fotostab.setTag("ft");
mFdapter = new AdapterFoto(getSupportFragmentManager());
fotostab.setTabListener(this);
Log.d("Foto",""+fotostab.getTag());
getSupportActionBar().addTab(fotostab);
}
new getpergunta().execute();
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction transaction) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction transaction) {
if(tab.getTag().equals("op")){
mPager.invalidate();
mPager.setAdapter(mOdapter);
mIndicator = (UnderlinePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}else if (tab.getTag().equals("dd")){
mPager.invalidate();
mPager.setAdapter(mDdapter);
mIndicator = (UnderlinePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}else if(tab.getTag().equals("ft")){
mPager.invalidate();
mPager.setAdapter(mFdapter);
mIndicator = (UnderlinePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction transaction) {
}
public static class AdapterOpiniao extends FragmentPagerAdapter {
public AdapterOpiniao(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return countopiniao;
}
#Override
public Fragment getItem(int position) {
return FragmentOpinioes.newInstance(position);
}
}
public static class AdapterDados extends FragmentPagerAdapter {
public AdapterDados(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return countdados;
}
#Override
public Fragment getItem(int position) {
return FragmentDados.newInstance(position);
}
}
public static class AdapterFoto extends FragmentPagerAdapter {
public AdapterFoto(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return countfoto;
}
#Override
public Fragment getItem(int position) {
return FragmentFotos.newInstance(position);
}
}
To solve your case, I used:
#Override
public void onTabSelected(Tab tab, FragmentTransaction transaction) {
this.mPager.setCurrentItem(tab.getPosition());
}
When a click on a tab, the view of the corresponding tab is automatically changed.
Edit: I must admit that I have some difficulties to really understand your code and what you are trying to do, so I add some more code to explain what i think you need.
In my optinion, only one adapter is necessary for the ViewPager, and then if I'm right, you would do so:
// I took some personal code for my example
private ViewPager mPager;
private PageIndicator mIndicator;
private TabsExampleSectionsAdapter mAdapter;
// Inside the onCreate method
this.mPager = (ViewPager) findViewById(R.id.pager);
this.mIndicator = new TabPageIndicator(this);
this.mAdapter = new TabsExampleSectionsAdapter(this.getSupportFragmentManager());
this.mPager.setAdapter(this.mAdapter);
this.mIndicator.setViewPager(this.mPager);
When everything is initialized, this is how to build tabs and pager views instructions (the two are related). Also, don't mind the Section class, it's a custom data model object which contains the tag data you need but it has nothing to do with actionbarsherlock.
private void buildTabs(Section[] sections) {
if (sections != null) {
for (Section section : sections) {
ActionBar.Tab sectionTab = getSupportActionBar().newTab();
sectionTab.setText(section.name);
sectionTab.setTabListener(this);
getSupportActionBar().addTab(sectionTab);
// The tag ("op" or "dd" in your case for example) is contained somewhere in the section object
this.mAdapter.getSections().add(section);
}
}
}
And finally, this is the view pager adapter. It will choose what type of fragment to return following the tags you defined for each tab position:
public class TabsExampleSectionsAdapter extends FragmentPagerAdapter {
private ArrayList<Section> mSectionsList = new ArrayList<Section>();
public TabsExampleSectionsAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
// Retrieving the cooresponding tag of position
Section section = this.mSectionsList.get(position % getCount());
// Here, you check the tag to know what type of fragment you must return
if (section.getTag().equals("dd")) {
return FragmentDados.newInstance(position);
} else if (section.getTag.equals("op")) {
return FragmentOp.newInstance(position);
}
}
#Override
public int getCount() {
return this.mSectionsList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return this.mSectionsList.get(position % getCount()).name.toUpperCase();
}
public ArrayList<Section> getSections() {
return this.mSectionsList;
}
}
In conclusion, when everything is set up, changing views doesn't have to be done manually by changing adapters and calling invalidate(). You can return different type of fragments from your adapter with a simple condition. Then, by calling:
this.mPager.setCurrentItem(position);
it changes automatically the current view by passing in the adapter's getItem(position) method. Basically, you just have to coordinate your tab positions and your tags in order to get the right type of fragment.
Feel free to ask for more details.

Categories

Resources