I am using a ViewPager to show my Images.
These Images are sent as a List from One Activity to another & then I show them in the ViewPager.
But the Issue is that if I click on a Delete Button them the Image is Deleted & Removed from the List but it still show on the Next Image.
e.g. 1st Image's height is fullscreen > I delete it, viewpager moves to next Image, this image has a height of 350 then the background above & below 350 shows the old Image...
Also, I get a IndexOutOfBoundsExceptiom when I try to delete the 2nd Last Item...
Heres my Code -
public class ImageViewer extends AppCompatActivity {
public int position;
private ArrayList<String> list;
private HackyViewPager pager;
private ImagePagerAdapter ipa;
private List<PhotoView> photoViewList;
private HelperMethods helperMethods;
private static boolean sendResult = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.img);
sendResult = false;
helperMethods = new HelperMethods(ImageViewer.this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().hide();
Intent i = getIntent();
position = i.getExtras().getInt("position");
list = i.getStringArrayListExtra("list");
pager = (HackyViewPager) findViewById(R.id.pager);
photoViewList = new ArrayList<PhotoView>();
for(int val = 0; val < list.size(); val++) {
PhotoView photoView = new PhotoView(this);
photoView.setZoomable(true);
Glide.with(ImageViewer.this)
.load(new File(list.get(val)))
.into(photoView);
photoViewList.add(photoView);
}
ipa = new ImagePagerAdapter(photoViewList);
pager.setAdapter(ipa);
pager.setCurrentItem(position);
FloatingActionButton dlt = (FloatingActionButton) findViewById(R.id.dlt);
dlt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(ImageViewer.this);
builder.setMessage("Sure to Delete this Image?")
.setNegativeButton("Nope", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
getFilePos().delete();
ipa.remove(pager.getCurrentItem());
Toast.makeText(ImageViewer.this, "Image Deleted", Toast.LENGTH_SHORT)
.show();
}
});
builder.create()
.show();
}
});
}
public File getFilePos() {
return new File(list.get(pager.getCurrentItem()));
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
onBackPressed();
break;
}
return true;
}
static class ImagePagerAdapter extends PagerAdapter {
private List<PhotoView> images;
public ImagePagerAdapter(List<PhotoView> images) {
this.images = images;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
PhotoView imageView = images.get(position);
container.addView(imageView);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(images.get(position));
}
#Override
public int getCount() {
return images.size();
}
void remove(int pos) {
images.remove(pos);
notifyDataSetChanged();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
}
}
After deletion of image from list you must call the
notifyitemremoved();
on method remove on adapter.
This will work for you
you have to set the adapter to viewpager again, then it will refresh the content.
removeView(int pos) in my PagerAdaper
public void removeView(int index) {
imageFileNames.remove(index);
notifyDataSetChanged();
}
wherever I am removing the file I have to do like this
imagePagerAdapter.removeView(currentPosition);
viewPager.setAdapter(imagePagerAdapter);
EDIT:
This below method is effective, you can apply the below one.
public void updateView(int pos){
viewPager.setAdapter(null);
imagePagerAdapter =new ImagePagerAdapter(YOUR_CONTEXT,YOUR_CONTENT);
viewPager.setAdapter(imagePagerAdapter);
viewPager.setCurrentItem(pos);
}
replace YOUR_CONTEXT with your context and your content with your content name i.e. updated list or something.
Related
I have an application in which I create TabItems dynamically and I add them to the TabLayout. I'll show you the code below. then I also have a mechanism that when a tabitem is created, the user can close it with a click of a button. NOW: the problem happens here. when the user deletes that tabitem and program automatically directs the user to another tab. I can no longer click on the other tabs that I created at the start of the application. I Can click on them, but the program closes with the error
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 4, found: 3 Pager
and all of this happens when I delete a tabitem with a code written for a click. below is my MainActivity.java code :
public class MainActivity extends AppCompatActivity implements ContactsFragment.CallBacks, UserDetailFragment.DetailCallBacks {
android.support.v7.widget.Toolbar toolbar;
public static List<Fragment> fragments = new ArrayList<>();
public static List<String> fragmentsTitle = new ArrayList<>();
ViewPager viewPager;
TabLayout tabLayout;
int tabposition_number;
public List<Fragment> getFragments() {
return fragments;
}
public List<String> getFragmentsTitle() {
return fragmentsTitle;
}
public void addToFragments(Fragment fragment) {
fragments.add(fragment);
}
public void addToFragmentsTitle(String title) {
fragmentsTitle.add(title);
}
public Fragment getFragmentsWithPosition(int position) {
return fragments.get(position);
}
public String getFragmentsTitleWithPosition(int position) {
return fragmentsTitle.get(position);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = new MenuInflater(this);
menuInflater.inflate(R.menu.top_main_menu,menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.remove_tab) {
remove_tab_details(3);
}
return super.onOptionsItemSelected(item);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_page_drawer);
this.tabLayout = findViewById(R.id.tab_layout);
this.viewPager = findViewById(R.id.view_pager);
tabLayout.setupWithViewPager(viewPager);
SetUpViewPager(viewPager);
this.toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
NavigationView navigationView = findViewById(R.id.navigation_view);
navigationView.setItemIconTintList(null);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
#Override
public void onTabSelected(TabLayout.Tab tab) {
if(tab.getPosition() > 2) {
tabposition_number = tab.getPosition();
}
// viewPager.setCurrentItem(tab.getPosition());
if(tab.getPosition() == 1) {
toolbar.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.tab_contacts));
tabLayout.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.main_contacts));
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(ContextCompat.getColor(MainActivity.this,R.color.status_contacts));
}
} else if(tab.getPosition() == 2) {
toolbar.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.tab_register));
tabLayout.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.main_register));
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(ContextCompat.getColor(MainActivity.this,R.color.status_register));
}
} else {
toolbar.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.tab_signin));
tabLayout.setBackgroundColor(ContextCompat.getColor(MainActivity.this,R.color.main_signin));
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(ContextCompat.getColor(MainActivity.this,R.color.status_signin));
}
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
public void SetUpViewPager(ViewPager viewPager) {
MyViewPagerAdapter Adapter = new MyViewPagerAdapter((getSupportFragmentManager()));
Adapter.AddFragmentPage(new SignInFragment(),"ورود");
Adapter.AddFragmentPage(new ContactsFragment(),"ارتباطات");
Adapter.AddFragmentPage(new RegisterFragment(),"ثبت نام");
Adapter.notifyDataSetChanged();
viewPager.setAdapter(Adapter);
}
#Override
public void create_user_detail_tab(UserObject userObject) {
MyViewPagerAdapter Adapter = new MyViewPagerAdapter(getSupportFragmentManager());
UserDetailFragment userDetailFragment = new UserDetailFragment();
Bundle bundle = new Bundle();
bundle.putString("name",userObject.getName());
bundle.putString("family",userObject.getFamily());
bundle.putString("email",userObject.getEmail());
userDetailFragment.setArguments(bundle);
Adapter.AddFragmentPage(userDetailFragment,userObject.getName());
viewPager.setAdapter(Adapter);
TabLayout.Tab tab = tabLayout.getTabAt(1);
tab.select();
}
#Override
public void delete_previous_tab(int tabposition_number) {
remove_tab_details(tabposition_number);
MyViewPagerAdapter myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager());
myViewPagerAdapter.notifyDataSetChanged();
}
#Override
public void changeTabItem(boolean mustdelete) {
ContactsFragment contactsFragment = new ContactsFragment();
if(tabposition_number > 2 && mustdelete) {
contactsFragment.setTextView(tabposition_number,mustdelete);
TabLayout.Tab tab = tabLayout.getTabAt(1);
tab.select();
}
}
public class MyViewPagerAdapter extends FragmentPagerAdapter {
public MyViewPagerAdapter(FragmentManager manager) {
super(manager);
}
public void removeTabPage(int position) {
fragments.remove(position);
fragmentsTitle.remove(position);
MyViewPagerAdapter myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager());
myViewPagerAdapter.notifyDataSetChanged();
myViewPagerAdapter.notifyDataSetChanged();
}
public void AddFragmentPage(Fragment frag,String title) {
MainActivity.this.addToFragments(frag);
MainActivity.this.addToFragmentsTitle(title);
MyViewPagerAdapter myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager());
myViewPagerAdapter.notifyDataSetChanged();
}
public Fragment getItem(int position) {
return MainActivity.this.getFragmentsWithPosition(position);
}
public CharSequence getPageTitle(int position) {
return MainActivity.this.getFragmentsTitleWithPosition(position);
}
public int getCount() {
return fragments.size();
}
}
public void remove_tab_details(int tab_to_delete) {
// TabLayout.Tab tab = tabLayout.getTabAt(2);
// tab.select();
tabLayout.removeTabAt(tab_to_delete);
MyViewPagerAdapter Adapter = new MyViewPagerAdapter(getSupportFragmentManager());
Adapter.removeTabPage(tab_to_delete);
Adapter.notifyDataSetChanged();
}
}
and the code for UserDetailFragment ( which creates when the user click on one of the items in a listview fragment .
public class UserDetailFragment extends Fragment {
View view;
DetailCallBacks detailCallBacks;
public UserDetailFragment() {}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.user_detail_fragment,null);
return view;
}
#Override
public void onResume() {
super.onResume();
final Bundle bundle = getArguments();
String name = (String) bundle.get("name");
String family = (String)bundle.get("family");
String email = (String)bundle.get("email");
TextView nameFamilytv = view.findViewById(R.id.user_detail_name_and_family);
String nameAndfamily = name + " " + family;
nameFamilytv.setText(nameAndfamily);
TextView emailtv = view.findViewById(R.id.user_detail_email);
emailtv.setText(email);
Button closebtn = view.findViewById(R.id.detail_close_button);
closebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
detailCallBacks.changeTabItem(true);
}
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
detailCallBacks = (DetailCallBacks)context;
}
public interface DetailCallBacks {
public void changeTabItem(boolean mustdelete);
}
and last but not least : the code for that list item that creates dynamic tabs when user clicks on its items :
public class ContactsFragment extends ListFragment {
CallBacks callBacks;
View view;
public static int came_fromTabItem;
public static boolean do_delete;
public ContactsFragment() { }
ArrayList<UserObject> userObjects;
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
userObjects = intent.getParcelableArrayListExtra(Intent_Service.SERVICE_PAYLOAD);
ArrayAdapter<UserObject> userObjectArrayAdapter = new UserArrayAdapter(context,0,userObjects);
setListAdapter(userObjectArrayAdapter);
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(getActivity(), Intent_Service.class);
getActivity().startService(intent);
LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).
registerReceiver(broadcastReceiver,new IntentFilter(Intent_Service.SERVICE_MESSAGE));
}
public void setTextView(int position,Boolean mustDelete) {
came_fromTabItem = position;
do_delete = mustDelete;
}
#Override
public void onResume() {
super.onResume();
if(came_fromTabItem > 2 && do_delete) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
callBacks.delete_previous_tab(came_fromTabItem);
do_delete = false;
Toast.makeText(getActivity().getApplicationContext(),String.valueOf(came_fromTabItem),Toast.LENGTH_LONG).show();
}
}, 2000);
}
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.view = inflater.inflate(R.layout.fragment_contacts,null);
return this.view;
}
public void onListItemClick(ListView l, View v, int position, long id) {
UserObject userObject = userObjects.get(position);
callBacks.create_user_detail_tab(userObject);
}
public interface CallBacks {
public void create_user_detail_tab(UserObject userObject);
public void delete_previous_tab(int positions);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.callBacks = (CallBacks)context;
}
}
So... can anyone help me please? the problem is simple, why the error The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 4, found: 3 appears when a tabitem is removed, how can I solve it?
the problem occur because you delete a tab item and your pager still has 4 in item count , you have to make pager item count dynamic , and call notifyDataSetChanged() after you remove an item
here is an example
public class MyPagerAdapter extends FragmentPagerAdapter {
int nbrItem;
public ProfilPagerAdapter(FragmentManager fm,String token,Int nbrItem) {
super(fm);
this.nbrItem= nbrItem;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0 :
new SignInFragment();
case 1 :
new ContactsFragment()
case 2 :
new RegisterFragment()
}
return null;
}
#Override
public int getCount() {
return nbrItem;
}
public void setNbrItem(int nbrItem) {
this.nbrItem= nbrItem;
}
now when you remove an item you will pass to new number of item to your adapater
getAdapter().setNbrItem(2);
getAdapter().notifyDataSetChanged();
I solved my Problem, But with a hack, you see the error was because: TabItems are counting and indexing from 0, but as my pages are dynamically creating, I set the
getCount() method of my FragmentPagerAdapter to return the ArrayList<Fragment> fragments size , with fragments.size() , on the other hand, the size of an ArrayList doesn't count 0. so for 3 elements, instead of 0 1 2, or number 2, it returns to number 3.
so back to business, I was compelled to add null to my ArrayList and one null to my ArrayList titles, so this way when I removed my last TabItem, program doesn't crash anymore, and to be more convenient, when a user closes all Tabs , everytime user opens ( adds ) a new tab, I call fragments.removeAll(Collections.singleton(null)); to clear every null element i have inserted, for the TabTitles Too .
anyway cheers you guys, I'm sure this would be a good tutorial for those who want to create such applications because I've included all of my codes. please give a thumbs up. thanks.
I am writing a simple view pager test app that loads a bunch of data from a website and creates pages to display them.
For the most part the displaying is pretty much all works. However, it falls apart when I load a new set of data to display. When I get a new set, it loads all the data perfectly well however, instead of starting from view 0 it starts at a random location. It could start at the end or somewhere in the middle.
I want all the data to load from page 1, like a book. If you load a new book the book should start from page 1 not a random page.
Reloading calls
I've tried using GotCampDetails() which sets the local variable in the class.
viewPager.setCurrentItem(0);
in my fragment but it doesn't work. Also called notifydatasetchanged() on my adapter, still didn't work.
What am I missing?
public class ViewPagerFragment extends Fragment implements WebReadResultsListener {
private ArrayList<HashMap<String, String>> campDetails;
CustomPagerAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.camp_viewpager, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (campDetails != null && ! campDetails.isEmpty()) {
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);
adapter = new CustomPagerAdapter(getActivity(), campDetails, viewPager);
viewPager.setAdapter(adapter);
viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
}
}
#Override
public boolean GotCampDetails(ArrayList<HashMap<String, String>> campDetails) {
this.campDetails = campDetails;
return true;
}
#Override
public boolean GotCampList(ArrayList<HashMap<String, String>> campDetails) {
return false;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager().putFragment(outState,"fragmentInstanceSaved",getFragmentManager().findFragmentById(R.id.content));
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Handle orientation changes here
}
}
Adapter:
public class CustomPagerAdapter extends PagerAdapter implements ColorChangeListener {
private ArrayList<HashMap<String, String>> campDetails;
private ViewGroup collection;
private Context mContext;
private boolean isRunning = false;
private ColorChangeListener colorChangeListener;
private int color= pink;
private int currentposition;
private ViewPager viewPager;
public CustomPagerAdapter(Context context, final ArrayList<HashMap<String, String>> campDetails, ViewPager viewPager) {
this.campDetails=campDetails;
this.mContext = context;
this.viewPager = viewPager;
colorChangeListener = (ColorChangeListener) mContext;
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
currentposition = pos;
if (campDetails.get(currentposition).get("color").equals("green")) {
color = green;
} else {
color = pink;
}
ColorAppBar(color);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public Object instantiateItem(ViewGroup collection, final int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.child_item, collection, false);
if (campDetails.size() <= 0) {
Toast.makeText(mContext, "Error in getting camp details", Toast.LENGTH_SHORT).show();
return null;
}
if (campDetails.get(position).get("description").equals("RD") ) {
layout.setBackgroundColor(mContext.getResources().getColor(green));
} else {
layout.setBackgroundColor(mContext.getResources().getColor(pink));
}
collection.addView(layout);
this.collection = collection;
TextView eName = (TextView) layout.findViewById(R.id.en);
TextView nEName= (TextView) layout.findViewById(R.id.nen);
TextView textView6 = (TextView) layout.findViewById(R.id.textView6);
// ImageView nextImg = (ImageView) groupLayout.get(index).findViewById(R.id.nextImg);
eName.setText(campDetails.get(position).get("name"));
if (position+1 < campDetails.size()) {
nEName.setText(campDetails.get(position+1).get("name"));
textView6.setVisibility(View.VISIBLE);
} else {
nEName.setText("You are DONE!!");
textView6.setVisibility(View.INVISIBLE);
}
return layout;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
#Override
public int getCount() {
return campDetails.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public CharSequence getPageTitle(int position) {
return campDetails.get(position).get("name");
}
#Override
public void ColorAppBar(int color) {
colorChangeListener.ColorAppBar(color);
}
}
I finally managed to get it done.
I had to delay the function call setCurrentItem by a few milliseconds. Race condition? I don't know why this is the case but now it works perfectly.
Here is what I added in case someone else may find it useful:
pager.postDelayed(new Runnable() {
#Override
public void run() {
pager.setCurrentItem(pos);
}
}, 100);
I'm having trouble following the details well enough to pinpoint the problem, but this guy seems to have accomplished what you're trying to do: dynamically add and remove view to viewpager
hope it helps
Am using a ViewPager with adapter to show some pictures (as a gallery) and I need to return the name of the picture when the user click above
my problem that I can not implement onclick from the adapter because I can't return the result to the calling activity, and when I implement the viewAdapter.addOnPageChangeListener I have to wait until the page is changed so if the user clicks on the first pic it well not work
here is my code:
for(int i=0;i<images.length;i++)
imagesArray.add(images[i]);
MyAdapter myAdapter = new MyAdapter(MyImagePicker.this,imagesArray);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(myAdapter);
//CircleIndicator indicator = (CircleIndicator) findViewById(R.id.indicator);
//indicator.setViewPager(mPager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(mPager, true);
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Toast.makeText(getApplicationContext()," pos : "+position,Toast.LENGTH_LONG).show();
// return result //
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
class MyAdapter extends PagerAdapter {
private ArrayList<Integer> images;
private LayoutInflater inflater;
private Context context;
public MyAdapter(Context context, ArrayList<Integer> images) {
this.context = context;
this.images=images;
inflater = LayoutInflater.from(context);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public int getCount() {
return images.size();
}
#Override
public Object instantiateItem(ViewGroup view, int position) {
View myImageLayout = inflater.inflate(R.layout.slider, view, false);
final ImageView myImage = (ImageView) myImageLayout
.findViewById(R.id.image);
myImage.setImageResource(images.get(position));
myImage.setTag(position+1);
myImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context," pos : "+view.getTag(),Toast.LENGTH_LONG).show();
}
});
view.addView(myImageLayout, 0);
return myImageLayout;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
}
There are a few approaches you could take:
1) Create a callback interface. In your activity implement the interface (create a listener) and pass it into the adapter's constructor, when the user clicks on an image, pass the image name back to the activity using the callback (mlistener.onImageChosen(view.getTag()).
public interface ImageChosenListener
{
void onImageChosen(String image);
}
2) Use a broadcast from the adapter and have a broadcast receiver in your activity.
try this.
mPager.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(mPager.getCurrentItem()){
case 0: // its position 0
//somthing
break;
.
.
.
}
});
Thanks jt-gilkeson,
I think using a callBack interface is the perfect and the easiest solution :
Here is my answer :
// Create a callBack interface
public interface CallBack {
void callBack(String pos);
}
// The activity hosting my picture gallery
public class MyImagePicker extends Activity implements CallBack {
private static ViewPager mPager;
private static final Integer[] images= {R.drawable.p1,R.drawable.p2,R.drawable.p3,R.drawable.p4};
private ArrayList<Integer> imagesArray = new ArrayList<Integer>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.galery_image_chooser);
init();
}
private void init() {
for(int i=0;i<images.length;i++)
imagesArray.add(images[i]);
MyAdapter myAdapter = new MyAdapter(MyImagePicker.this,imagesArray,this);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(myAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(mPager, true);
}
// Implement the call back function
public void callBack(String pos){
//return back result
Intent intent=new Intent();
intent.putExtra("imgName",pos);
setResult(2,intent);
finish();//finishing activity
}
}
I've seen quite a few posts about this "issue" with RecyclerView, but I can't manage to fix it.
Every time I scroll, my custom CheckBoxes (starStyle) keep turning on/off.
I've tried to follow other solutions here on Stack, but none seems to do the job for me.
Just to explain the structure of my app, I've a long list (each item has a StarStyle CheckBox): when I click on an item, the app takes me in the Details Page for that item, where I can set the CheckBox, too. I managed to bind the list's checkbox and the one in the detail page, but I still having this annoying problem.
Here my code for the ListFragment:
public class PetrolStationListFragment extends Fragment {
private RecyclerView mPetrolStationRecyclerView;
private PetrolStationAdapter mAdapter;
private int itemPosition;
private int mLastAdapterClickPosition = -1;
private List<Boolean> mCheckState = new ArrayList<>();
public static boolean toBeCreated;
private static final String ARG_POSITION = "position";
// Design pattern to instantiate a new fragment.
public static PetrolStationListFragment newInstance(int position) {
PetrolStationListFragment fragment = new PetrolStationListFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
/********************************************************/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_petrol_station_list, container, false);
mPetrolStationRecyclerView = (RecyclerView) view.findViewById(R.id.petrol_recycler_view);
mPetrolStationRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
#Override
public void onResume() {
super.onResume();
updateUI();
}
private void updateUI() {
PetrolStationDAO petrolStationDAO = PetrolStationDAO.get(getActivity());
List<PetrolStation> petrolStations = petrolStationDAO.getPetrolStations();
if (mAdapter == null || toBeCreated) {
mAdapter = new PetrolStationAdapter(petrolStations);
mPetrolStationRecyclerView.setAdapter(mAdapter);
toBeCreated = false;
} else {
if (mLastAdapterClickPosition < 0) {
mAdapter.setPetrolStations(petrolStations);
mAdapter.notifyDataSetChanged();
} else {
mAdapter.notifyItemChanged(mLastAdapterClickPosition);
mLastAdapterClickPosition = -1;
}
mAdapter.notifyItemChanged(itemPosition);
}
}
private class PetrolStationHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private PetrolStation mPetrolStation;
private TextView mNameTextView;
private TextView mAddressTextView;
private TextView mDistanceTextView;
private CheckBox mCheckBox;
private int mPosition;
public PetrolStationHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mNameTextView = (TextView) itemView.findViewById(R.id.list_item_station_name_text_view);
mAddressTextView = (TextView) itemView.findViewById(R.id.list_item_station_address_text_view);
mDistanceTextView = (TextView) itemView.findViewById(R.id.list_item_station_distance_text_view);
mCheckBox = (CheckBox) itemView.findViewById(R.id.checkbox);
}
public void bindPetrolStation(PetrolStation petrolStation, int position) {
mPetrolStation = petrolStation;
mNameTextView.setText(mPetrolStation.getName());
mAddressTextView.setText("Via Verdi, 19/A");
mDistanceTextView.setText("300 meters");
mPosition = position;
//mCheckBox.setChecked(mPetrolStation.isFavourite());
mCheckBox.setChecked(mCheckState.get(mPosition));
Log.d("BIND_POSITION", "position: " + mPosition + " / status: " + mCheckState.get(mPosition));
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
boolean boxChecked = mPetrolStation.isFavourite();
Log.d("BOX_CHECKED_POSITION", "boxChecked: " + boxChecked);
if (boxChecked) {
mPetrolStation.setFavourite(false);
} else {
mPetrolStation.setFavourite(true);
}
if (boxChecked) {
mCheckState.set(mPosition, false);
} else {
mCheckState.set(mPosition, true);
}
Log.d("CHECK_POSITION", "mCheckState: " + mCheckState);
// TODO: DB connection.
// PetrolStationDAO.get(getActivity()).updateItem(mCrime);
}
});
}
#Override
public void onClick(View v) {
itemPosition = mPetrolStationRecyclerView.getChildAdapterPosition(v);
Intent intent = PetrolStationPagerActivity.newIntent(getActivity(), mPetrolStation.getId());
startActivity(intent);
}
}
private class PetrolStationAdapter extends RecyclerView.Adapter<PetrolStationHolder> {
private List<PetrolStation> mPetrolStations;
public PetrolStationAdapter(List<PetrolStation> petrolStations) {
mPetrolStations = petrolStations;
for (int i = 0; i < mPetrolStations.size(); i++) {
mCheckState.add(false);
}
}
#Override
public PetrolStationHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater.inflate(R.layout.list_item_petrol_station, parent, false);
return new PetrolStationHolder(view);
}
#Override
public void onBindViewHolder(PetrolStationHolder holder, int position) {
PetrolStation petrolStation = mPetrolStations.get(position);
holder.bindPetrolStation(petrolStation, position);
// holder.setIsRecyclable(false);
}
#Override
public int getItemCount() {
return mPetrolStations.size();
}
public void setPetrolStations(List<PetrolStation> petrolStations) {
mPetrolStations = petrolStations;
}
}
}
Here the one for the DetailsFragment:
public class PetrolStationFragment extends Fragment {
private static final String ARG_PETROL_STATION_ID = "petrol_station_id";
private PetrolStation mPetrolStation;
private TextView mInfo;
private CheckBox mCheckBox;
private static TabLayout mTabLayout;
private static ViewPager mViewPager;
private static int intItems = 2;
// Navigation Tab constants.
private static final int SELF_SERVICE_POSITION = 0;
private static final int FULL_SERVICE_POSITION = 1;
// Design pattern to instantiate a new fragment.
public static PetrolStationFragment newInstance(long petrolStationId) {
Bundle args = new Bundle();
args.putLong(ARG_PETROL_STATION_ID, petrolStationId);
PetrolStationFragment fragment = new PetrolStationFragment();
fragment.setArguments(args);
return fragment;
}
/********************************************************/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
long mId = getArguments().getLong(ARG_PETROL_STATION_ID);
mPetrolStation = PetrolStationDAO.get(getActivity()).getPetrolStation(mId);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceStace) {
View view = inflater.inflate(R.layout.fragment_petrol_station, container, false);
mInfo = (TextView) view.findViewById(R.id.petrol_station);
mCheckBox = (CheckBox) view.findViewById(R.id.checkbox);
mInfo.setText(mPetrolStation.getName());
mCheckBox.setChecked(mPetrolStation.isFavourite());
// TODO: to fix.
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isFavourite) {
mPetrolStation.setFavourite(isFavourite);
}
});
// Setup Views.
mTabLayout = (TabLayout) view.findViewById(R.id.pager_header);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
// Set an Adapter for the View Pager.
TabPagerAdapter tabPagerAdapter = new TabPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(tabPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
mViewPager.setCurrentItem(SELF_SERVICE_POSITION);
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
int flag;
#Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
mInfo.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
mPetrolStation.setName(charSequence.toString());
}
#Override
public void afterTextChanged(Editable editable) {
}
});
return view;
}
class TabPagerAdapter extends FragmentPagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
// Return fragment with respect to position.
#Override
public Fragment getItem(int position) {
Fragment fragment;
switch (position) {
case SELF_SERVICE_POSITION: {
fragment = SelfServiceFragment.newInstance();
return fragment;
}
case FULL_SERVICE_POSITION: {
fragment = FullServiceFragment.newInstance();
return fragment;
}
}
return null;
}
#Override
public int getCount() {
return intItems;
}
// This method returns the title of the tab according to its position.
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case SELF_SERVICE_POSITION: {
String mSelfService = getResources().getString(R.string.self_service);
return mSelfService;
}
case FULL_SERVICE_POSITION: {
String mFullService = getResources().getString(R.string.full_service);
return mFullService;
}
}
return null;
}
}
}
Any hints about how to solve this issue?
Am I missing some kind of check?
Use a List of boolean type to hold the state of the checkbox. By default fill your collection with a false value.
When you select a checkbox change the state of the map using the set method
As you know When you scroll there will be a call to your adapter there you read the value from the map using get and set it to checkbox
List < Boolean > checkstate = new ArrayList < Boolean > ();
// Inside the adapter constructor
for (i = 0; i < itemSize; i++) {
checkstate.add(false);
}
Inside your Viewholder add below Line what it does is whatever the updated value of checkbox will set to your checkbox. Initially all the Items will be false
yourCheckbox.setChecked(checkstate.get(position));
Now inside onCheckedChanged Listener
if (boxchecked) {
checkstate.set(position, true);
} else {
checkstate.set(position, false);
}
With the help of Vivek Pratap Singh and astuetz codes from following questions(Remove Fragment Page from ViewPager in Android and Android saving dynamically added viewpager's fragment while coming back from another activity and reopening app),
In my previous question in stack overflow I used inbuild method onDestroy, as it looks like it will save all the dynamically added fragments in viewpager.
But it's not happening, I am able to see only one intial static page(i.e. fragment) when I restart my app or navigate to another activity and come back to my activity containing the viewpager with fragments.Could any one please help me on this question.
Here is my source code for your reference:
public class MainActivity extends FragmentActivity implements TextProvider {
private Button mAdd;
private Button mRemove;
private ViewPager mPager;
int position;
private MyPagerAdapter mAdapter;
private ArrayList<String> mEntries = new ArrayList<String>();
#Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putInt("currenItem", mPager.getCurrentItem());
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = (ViewPager) findViewById(R.id.pager);
if (savedInstanceState != null) {
mPager.setCurrentItem(savedInstanceState.getInt("currentItem", 0));
}
mEntries.add("page 1");
mAdd = (Button) findViewById(R.id.add);
mRemove = (Button) findViewById(R.id.remove);
mAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
addNewItem();
}
});
mRemove.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
removeCurrentItem();
}
});
mAdapter = new MyPagerAdapter(this.getSupportFragmentManager(), this);
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(3);
}
private void addNewItem() {
// int position = mPager.getCurrentItem();
mEntries.add("page ");
mAdapter.notifyDataSetChanged();
}
private void removeCurrentItem() {
int position = mPager.getCurrentItem();
if(position != 0){
mEntries.remove(position);
}else{
Toast.makeText(getApplicationContext(), "Sorry", Toast.LENGTH_LONG).show();
}
mAdapter.notifyDataSetChanged();
}
#Override
public String getTextForPosition(int position) {
return mEntries.get(position);
}
#Override
public int getCount() {
return mEntries.size();
}
private class MyPagerAdapter extends FragmentPagerAdapter {
private TextProvider mProvider;
private long baseId = 0;
public MyPagerAdapter(FragmentManager fm, TextProvider provider) {
super(fm);
this.mProvider = provider;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return FragmentOne.newInstance(mProvider.getTextForPosition(position));
case 1:
return FragmentTwo.newInstance(mProvider.getTextForPosition(position));
case 2:
return FragmentThree.newInstance(mProvider.getTextForPosition(position));
default: return FragmentOne.newInstance(mProvider.getTextForPosition(position));
}
}
#Override
public int getCount() {
return mProvider.getCount();
}
//this is called when notifyDataSetChanged() is called
#Override
public int getItemPosition(Object object) {
// refresh all fragments when data set changed
return PagerAdapter.POSITION_NONE;
}
#Override
public long getItemId(int position) {
// give an ID different from position when position has been changed
return baseId + position;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
/**
* Notify that the position of a fragment has been changed.
* Create a new ID for each position to force recreation of the fragment
* #param n number of items which have been changed
*/
public void notifyChangeInPosition(int n) {
// shift the ID returned by getItemId outside the range of all previous fragments
baseId += getCount() + n;
}
}
}