I have a ViewPagerActivity with two views. I want to register a context menu, different for each view. I tried a few things (registerForContextMenu()) but I always ended up with both views behaving like the second one. Any ideas?
public class ViewPagerActivity extends UomeActivity {
private ViewPager viewPager;
private ViewPagerAdapter viewPagerAdapter;
private ListAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager);
refreshAdapter();
}
private class ViewPagerAdapter extends PagerAdapter {
private final List<Transaction> accountTransactions;
private final List<User> accountUsers;
public ViewPagerAdapter() {
// initialize lists
}
#Override
public Object instantiateItem(View collection, int viewPosition) {
View layout;
ListView listView;
switch (viewPosition) {
case 0:
layout = LayoutInflater.from(getApplicationContext()).inflate(
R.layout.list_account_paired_transactions, null);
List<PairedTransaction> pairedTransactions = getPairedTransactions();
adapter = new AccountPairedTransactionItemAdapter(ViewPagerActivity.this,
R.layout.list_account_paired_transactions, pairedTransactions);
listView = (ListView) layout.findViewById(android.R.id.list);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// do something
}
});
registerForContextMenu(listView);
break;
case 1:
layout = LayoutInflater.from(getApplicationContext()).inflate(
R.layout.list_account_transactions, null);
initViewPagerInfo(layout, R.string.paired_transactions,
R.string.all_account_transactions, R.string.empty, viewPosition);
adapter = new TransactionItemAdapter(ViewPagerActivity.this,
R.layout.list_account_transactions, accountTransactions,
new UserDaoImpl(
getApplicationContext()));
listView = (ListView) layout.findViewById(android.R.id.list);
registerForContextMenu(listView);
break;
default:
throw new IllegalArgumentException("Unsupported number of views.");
}
listView.setAdapter(adapter);
listView.setDivider(new ColorDrawable(R.color.list_separator));
listView.setDividerHeight(1);
listView.setBackgroundColor(Color.WHITE);
listView.setCacheColorHint(Color.WHITE);
((ViewPager) collection).addView(layout);
return layout;
}
// omitted
}
#Override
protected void onResume() {
refreshAdapter();
super.onResume();
}
private void refreshAdapter() {
viewPagerAdapter = new ViewPagerAdapter();
viewPager = findById(R.id.view_pager);
viewPager.setAdapter(viewPagerAdapter);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
menu.add(R.string.show_info);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
// TODO: toast which object has been selected
}
}
The problem is that both views are instantiated at the same time (filling the viewpager). Setting the onRegisterForContextMenu in the second view is overwriting it from the first view.
A possible solution would be to check to see what view is visible in you onContextItemSelected method.
Related
I want to make my fragment wont re-load the data when configuration change with view model.
So, i try to make an App about gitHub User.
My Main Activity contain Search view to search user and show the result with recyclerview.
My Detail Activity is showing the detail of user when one of user in the list clicked, and in my detail activity i use Tab Layout and view pager to show user's followers and following.
My ViewModel for activity works well and can keep my data when orientation change.
But when i do the same to my fragment, my fragment keep re-loading new data when orientation change.
Here my fragment
i use View Model to request data
public class FollowingFragment extends Fragment {
public static final String KEY_FOLLOWING = "key_following";
private RecyclerView recyclerView;
private FollowingViewModel followingViewModel;
private FollowingAdapter followingAdapter;
ShimmerFrameLayout shimmerFrameLayout;
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
ArrayList<FollowingResponse> followingResponse = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_following, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.rv_following);
shimmerFrameLayout = view.findViewById(R.id.shimmer_frame_layout2);
followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
followingAdapter = new FollowingAdapter();
followingAdapter.setOnItemClickCallback(new FollowingAdapter.OnItemClickCallback() {
#Override
public void onItemClicked(FollowingResponse followingResponse) {
showSelectedItem(followingResponse);
}
});
//this is what i've tried and worked, but my fragment result with double or triple the data.
if (savedInstanceState == null){
}
else {
followingResponse = savedInstanceState.getParcelableArrayList(KEY_FOLLOWING);
}
showRecyclerView();
getData();
}
private void getData() {
followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
followingViewModel.getDataFollowing().observe(getViewLifecycleOwner(), new Observer<ArrayList<FollowingResponse>>() {
#Override
public void onChanged(ArrayList<FollowingResponse> followingResponses) {
shimmerFrameLayout.setVisibility(View.GONE);
shimmerFrameLayout.stopShimmer();
followingAdapter.setData(followingResponse);
followingResponse.addAll(followingResponses);
recyclerView.setAdapter(followingAdapter);
followingAdapter.notifyDataSetChanged();
}
});
}
private void showRecyclerView() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
}
#Override
public void onResume() {
super.onResume();
followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
}
private void showSelectedItem(FollowingResponse item) {
Intent intent = new Intent(getContext(), DetailUserActivity.class);
intent.putExtra("EXTRA_DATA", item.getLogin());
startActivity(intent);
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
outState.putParcelableArrayList(KEY_FOLLOWING, followingResponse);
super.onSaveInstanceState(outState);
}
}
Detail Activity
public class DetailUserActivity extends AppCompatActivity {
private TextView tvName, tvNickname, tvLocation, tvCompany, tvEmail, tvWebsite;
private TextView tvCountFollowers, tvCountRepository, tvCountFollowing;
private ImageView imgProfile;
ProgressBar progressBar;
public static String clickedUser;
UserViewModel userViewModel;
private ViewPager viewPager;
TabLayout tabLayout;
private final String EXTRA_DATA = "EXTRA_DATA";
private static final String EXTRA_FOLLOW = "extra_follow";
// Fragment followingFragment;
// FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_user_activity);
// i've tried this, but when the orientation change, my detail activity force close and throw me to my main activity.
// if (savedInstanceState != null){
// followingFragment = getSupportFragmentManager().getFragment(savedInstanceState, KEY_FOLLOWING);
// } else {
// followingFragment = new FollowingFragment();
//
// getSupportFragmentManager().beginTransaction().replace(R.id.tv_view_pager, followingFragment).commit();
// }
tvName = findViewById(R.id.tv_item_name);
tvNickname = findViewById(R.id.tv_item_nickname);
tvLocation = findViewById(R.id.tv_item_location);
tvCompany = findViewById(R.id.tv_item_company);
tvEmail = findViewById(R.id.tv_item_email);
tvWebsite = findViewById(R.id.tv_item_website);
imgProfile = findViewById(R.id.img_item_photo);
tvCountFollowers = findViewById(R.id.tv_count_follower);
tvCountRepository = findViewById(R.id.tv_count_repo);
tvCountFollowing = findViewById(R.id.tv_count_following);
progressBar = findViewById(R.id.progressbar2);
setForUserData();
setForTabLayout();
}
private void setForUserData(){
Intent detailIntent = getIntent();
clickedUser = detailIntent.getStringExtra("EXTRA_DATA");
userViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(UserViewModel.class);
userViewModel.setUserUVM(clickedUser);
userViewModel.getUserUVM().observe(this, new Observer<UserResponse>() {
#Override
public void onChanged(UserResponse userResponse) {
progressBar.setVisibility(View.GONE);
Glide.with(getApplicationContext())
.load(userResponse.getAvatarUrl())
.into(imgProfile);
tvName.setText(userResponse.getLogin());
tvLocation.setText(userResponse.getLocation());
tvNickname.setText(userResponse.getName());
tvCompany.setText(userResponse.getCompany());
tvEmail.setText(userResponse.getEmail());
tvWebsite.setText(userResponse.getBlog());
tvCountRepository.setText(String.valueOf(userResponse.getPublicRepos()));
tvCountFollowers.setText(String.valueOf(userResponse.getFollowers()));
tvCountFollowing.setText(String.valueOf(userResponse.getFollowing()));
}
});
}
private void setForTabLayout(){
tabLayout = findViewById(R.id.tv_tab_layout);
viewPager = findViewById(R.id.tv_view_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount()));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setOnTabSelectedListener(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) {
}
});
}
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
int totalTab;
#SuppressWarnings("deprecation")
ViewPagerAdapter(FragmentManager fragmentManager, int totalTabs) {
super(fragmentManager);
this.totalTab = totalTabs;
}
#SuppressWarnings("ConstantConditions")
#NonNull
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new FollowersFragment();
case 1:
return new FollowingFragment();
default:
return null;
}
}
#Override
public int getCount() {
return totalTab;
}
}
// #Override
// protected void onSaveInstanceState(#NonNull Bundle outState) {
// getSupportFragmentManager().putFragment(outState, KEY_FOLLOWING, followingFragment );
// super.onSaveInstanceState(outState);
// }
}
im trying to solve my FollowingFragment first, then ill do the same on my FollowerFragment.
im really new in programming, and have no one to ask.. can someone help me to solve my problem with keep data in fragment when orientation change?
followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
In Fragment insted of writing this code in onViewCreated() write it inside OnCreate()
onViewCreated() will get called everytime the orientation changes so it will create new instance of view model everytime the orientation changes making viewmodel to reload the data
If you need to load data only once for the FollowingViewModel a good place to do it should be inside the constructor of the view model in this way you won't need to worry about the orientation change of the fragment.
Problem:
I'm trying to open a custom dialog after pressing a button in my tabbed fragment.
It's seems like my MainActivity activity is sent to the dialog while i want my tabbed fragment(GroupFragment) to be sent so i can change the editText(for now) in this fragment.
Code:
public class GroupFragment extends Fragment implements AddGroupDialog.AddGroupDialogListener {
private Button addGroupButton;
private TextView textViewNoGroups;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_group, container, false);
addGroupButton = view.findViewById(R.id.addGroupButton);
textViewNoGroups = view.findViewById(R.id.textViewNoGroups);
addGroupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addNewGroupDialog();
}
});
scaleAnimation(addGroupButton);
return view;
}
private void scaleAnimation(View v){
Animator scale = ObjectAnimator.ofPropertyValuesHolder(v,
PropertyValuesHolder.ofFloat(View.SCALE_X, 0, 1.2f, 1),
PropertyValuesHolder.ofFloat(View.SCALE_Y, 0, 1.2f, 1)
);
scale.setDuration(600);
scale.start();
}
private void addNewGroupDialog(){
AddGroupDialog dialog = new AddGroupDialog();
assert getFragmentManager() != null;
dialog.show(getFragmentManager(), "add new group dialog");
}
#Override
public void applyString(String groupName) {
textViewNoGroups.setText(groupName);
}
}
public class AddGroupDialog extends AppCompatDialogFragment {
private EditText editTextGroupName;
private AddGroupDialogListener listener;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_add_new_group_dialog, null);
builder.setView(view)
.setTitle("")
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String groupName = editTextGroupName.getText().toString();
listener.applyString(groupName);
}
});
editTextGroupName = view.findViewById(R.id.editTextGroupName);
return builder.create();
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
listener = (AddGroupDialogListener) context;
} catch (ClassCastException e){
throw new ClassCastException(context.toString() +
"Must implement AddGroupDialogListener");
}
}
public interface AddGroupDialogListener{
void applyString(String groupName);
}
}
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
public SectionsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new GroupFragment();
break;
case 1:
fragment = new AttendanceFragment();
break;
case 2:
fragment = new StatisticsFragment();
break;
}
return fragment;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
return TAB_TITLES.length;
}
}
Error:
java.lang.ClassCastException: com.example.attendencetaker.MainActivity#26602bcMust implement AddGroupDialogListener
I hope my explanation of the problem is clear. Thank you!
Make the activity implement your interfaces and so on and then pass all data to the fragment with an method on the fragment. You will need an reference to actual Fragment that is displayed.
In your fragment add a method similar to this:
public void updateData(String data) {
editText.setText(data);
}
And in the override method of the interface in your activity to this:
#Override
public void update(String data) {
fragment.updateData(data);
}
Update
Use this Adapter instead:
public class SectionTabAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragments = new ArrayList<>();
private ArrayList<String> titles = new ArrayList<>();
public SectionTabAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
public void addFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
#NonNull
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
In your activity then do this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionTabAdapter = new SectionTabAdapter(this, getSupportFragmentManager());
Fragment groupFragment = new GroupFragment();
Fragment attendanceFragment = new AttendanceFragment();
Fragment statisticsFragment = new StatisticsFragment();
sectionTabAdapter.addFragment(groupFragment, context.getString(R.string.title_1);
sectionTabAdapter.addFragment(attendanceFragment, context.getString(R.string.title_2);
sectionTabAdapter.addFragment(statisticsFragment, context.getString(R.string.title_3);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionTabAdapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
}
:)
I'm writing an Android app which do a lot of things, but i have an issue with java GUI code and i'm not able to go on.
What I would like to achieve is a TabLayout gui user-editable. The user could add , remove or modify section. I write all the code that let me add section. To do this i used a Section Pager Adapter as shown
class SectionsPagerAdapter extends FragmentPagerAdapter {
public ArrayList<Fragment> mfragList;
public ArrayList<String> mfragtit;
public SectionsPagerAdapter(FragmentManager fm, ArrayList<Fragment> mFragList, ArrayList<String> mFragTit) {
super(fm);
this.mfragList=mFragList;
this.mfragtit=mFragTit;
}
#Override
public Fragment getItem(int position) {
return this.mfragList.get(position);
}
#Override
public int getCount() {
return this.mfragList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return this.mfragtit.get(position);
}
public void addFrag(Fragment frag, String tit){
this.mfragList.add(frag);
this.mfragtit.add(tit);
}
public void delFrag(int index){
this.mfragList.remove(index-1);
this.mfragtit.remove(index-1);
}
}
Well, i'm new in Android and what i've understand about this code is that this class, when called, takes two Arraylist: mfragList and mfragtit which contains the fragment of each section and its title. Then when this adapter is created it is set as the adapter of view pager, which it should be the object that contain the view.
So I get the first issue when i tried to delete one section. To do this i thought to delete both title and fragment from adapter, then notifydatasetChanged and then set again the adapter for the view pager. But it actually don't works (even if I only notifydatasetChanged while don't set adapter again).
What I do in MainActivity is something like this:
ad.delFrag(parseInt(elim_i)+1); //ad is the adapter declared as field
ad.notifyDataSetChanged();
mViewPager.setAdapter(ad);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
The issue was that it delete the right title but the wrong fragment, infact it ever delete the last fragment in mfragList
Any help gonna be appreciated.
Thank you guys.
Nico
FragmentAdapter internal have cache with loaded fragment. So that it's behaving like this. Try this adapter
public class MainActivity extends AppCompatActivity {
private TabLayout mTabLayout;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
List<Fragment> fragmentList = new ArrayList<>();
List<String> title = new ArrayList<>();
for (int i =0; i < 3; i++) {
fragmentList.add(new SampleViewPagerFragment());
title.add("Fragment #" + i);
}
final CustomPagerAdapter adapter = new CustomPagerAdapter(fragmentList, title);
mViewPager.setAdapter(adapter);
mTabLayout.setupWithViewPager(mViewPager);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
adapter.removeFragmentAtPosition(2);
}
}, 3000);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
adapter.addFragmentToAdapter("Title", new SampleViewPagerFragment());
}
}, 6000);
}
private static class CustomPagerAdapter extends PagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mTitle = new ArrayList<>();
CustomPagerAdapter(List<Fragment> mFragmentList, List<String> mTitle) {
this.mFragmentList = mFragmentList;
this.mTitle = mTitle;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
return mFragmentList.get(position);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
container.removeViewAt(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mTitle.get(0);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
void removeFragmentAtPosition(int position) {
mTitle.remove(position);
mFragmentList.remove(position);
notifyDataSetChanged();
}
void addFragmentToAdapter(String title, Fragment fragment) {
mTitle.add(title);
mFragmentList.add(fragment);
notifyDataSetChanged();
}
}
}
Used ViewPager for images sliding, when clicking on each image must do an action, its different action from image to another,
I'm new to android development
so I try to add onClick listener to ViewPager, but I can't achieve it,
please any suggestion how to implement OnClickListener so when I click the first image will do action and when click the second image will do another action and so on for all images, I have it inside the view pager
thanks in advance.
MainActivity:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
ImageAdapter adapter = new ImageAdapter(this);
viewPager.setAdapter(adapter);
}
}
ImageAdapter:
public class ImageAdapter extends PagerAdapter {
Context context;
private int[] GalImages = new int[] {
R.drawable.a,
R.drawable.b,
R.drawable.c,
R.drawable.d,
R.drawable.g,
R.drawable.h,
};
ImageAdapter(Context context){
this.context=context;
}
#Override
public int getCount() {
return GalImages.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((ImageView) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(context);
intpadding=context.getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin);
imageView.setPadding(padding, padding, padding, padding);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setImageResource(GalImages[position]);
((ViewPager) container).addView(imageView, 0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((ImageView) object);
}
}
To catch click events in ViewPager you have to override onTouchListener, since default implementation is not made to handle clicks
Your MainActivity should look something like this:
private ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager= (ViewPager) findViewById(R.id.view_pager);
ImageAdapter adapter = new ImageAdapter(this);
mViewPager.setAdapter(adapter);
final GestureDetector tapGestureDetector = new GestureDetector(this, new TapGestureListener());
mViewPager.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
tapGestureDetector.onTouchEvent(event);
return false;
}
});
}
private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (mViewPager.getCurrentItem() == 0) {
//do your thing tied with first page
} else if (mViewPager.getCurrentItem() == 1) {
//do your thing tied with second page
} else if (mViewPager.getCurrentItem() == 2) {
//do your thing tied with third page
}
return super.onSingleTapConfirmed(e);
}
}
Try this:
#Override
public Object instantiateItem(View collection, final int pos) { //have
to make final so we can see it inside of onClick()
LayoutInflater inflater = (LayoutInflater) collection.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View page = inflater.inflate(R.layout.YOUR_PAGE, null);
page.setOnClickListener(new OnClickListener(){
public void onClick(View v){
//this will log the page number that was click do your action
according to position
Log.i("TAG", "This page was clicked: " + pos);
}
});
((ViewPager) collection).addView(page, 0);
return page;
}
I have three tabs using the implementation below and they perform very well. When tab is changed the proper fragment is load and so on. The problem is that, when i get to the last tab and comeback to the first fragment, its like its oncreateview method is always triggered again running the other codes it in causing duplicates. Any help will be greatly appreciated.
//Activity on the tab is based
public class Dashboard extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private int[] tabIcon = {R.drawable.ic_home, R.drawable.ic_message, R.drawable.ic_person};
android.support.v7.widget.Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
//Toolbar
toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//ViewPager
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
//Tablayout
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(tabIcon[0]);
tabLayout.getTabAt(1).setIcon(tabIcon[1]);
tabLayout.getTabAt(2).setIcon(tabIcon[2]);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
switch(tab.getPosition()) {
case 0:
viewPager.setCurrentItem(0);
toolbar.setTitle("Home");
break;
case 1:
viewPager.setCurrentItem(1);
toolbar.setTitle("Messages");
break;
case 2:
viewPager.setCurrentItem(2);
toolbar.setTitle("Profile");
break;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void setupViewPager(ViewPager viewPager){
myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager());
myViewPagerAdapter.addFragments(new CategoryFragment(), "Categories");
myViewPagerAdapter.addFragments(new MessagesFragment(), "Messages");
myViewPagerAdapter.addFragments(new ProfileFragment(), "Profile");
viewPager.setAdapter(myViewPagerAdapter);
}
//View Pager Adapter
public class MyViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> fragments = new ArrayList<>();
ArrayList<String> tabTitles = new ArrayList<>();
public void addFragments(Fragment fragments, String titles){
this.fragments.add(fragments);
this.tabTitles.add(titles);
}
public MyViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
//return tabTitles.get(position);
return null;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
}
//Main first fragment code
public class CategoryFragment extends Fragment {
private DBHandler dbHandler;
private ListView listView;
private ListAdapter adapter;
ArrayList<Categories> categoriesList = new ArrayList<Categories>();
public CategoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
//Setting up the basic categories
dbHandler = new DBHandler(view.getContext());
//Get Categories from database
final Cursor cursor = dbHandler.getCategories(0);
if (cursor != null) {
if(cursor.moveToFirst()){
do{
Categories categories = new Categories();
categories.set_id(cursor.getInt(0));
categories.set_categoryname(cursor.getString(2));
categories.set_categoriescaption(cursor.getString(3));
categoriesList.add(categories);
}while (cursor.moveToNext());
}
cursor.close();
}
listView = (ListView) view.findViewById(R.id.categories);
adapter = new CategoryAdapter(view.getContext(), R.layout.cursor_row, categoriesList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Integer cid = (int) (long) adapter.getItemId(position);
TextView categoryname = (TextView) view.findViewById(R.id.cursor);
String cname = categoryname.getText().toString();
Intent i = new Intent(view.getContext(), CategoryList.class);
i.putExtra("categoryname", cname);
i.putExtra("categoryid", cid);
startActivity(i);
}
}
);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
So when i swipe back here from the last tab. OncreateView runs again. How can i handle that and prevent duplicates. Thank you
By defaults ViewPager retains only 1 page in the view hierarchy in an idle state.So when you swipe to third tab the viepager destroys the first tab in order to retain the second one.
To solve this issue add this line
viewPager.setOffscreenPageLimit(3);
after you set your adapter.
Check here the documentation for more