The problem is this:
When you first choose a picture - everything is fine. If you swipe, and press the "back" button, after you open another image then will open last image which will opened.
The correct position is passed through the Bundle. I don’t understand where to look for the error.
public class ViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;
public ViewPagerAdapter() {
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.image_fullscreen, container, false);
ImageView imageView = view.findViewById(R.id.image_fScreen);
Hit hit = hits.get(position);
Picasso.get().load(hit.getLargeImageURL())
.into(imageView);
container.addView(view);
return view;
}
#Override
public int getCount() {
return hits.size();
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return view == object;
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((View) object);
}
}
DialogFragment:
public class FullScreenDialogFragment extends DialogFragment {
private ArrayList<Hit> hits;
private ViewPager viewPager;
private ViewPagerAdapter viewPagerAdapter;
private TextView author;
private TextView count;
private int selectedPosition;
private Button buttonShare;
private static FullScreenDialogFragment fullScreenDialogFragment;
private int rlyPosition;
public static FullScreenDialogFragment getInstance() {
if (fullScreenDialogFragment == null) {
fullScreenDialogFragment = new FullScreenDialogFragment();
}
return fullScreenDialogFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME, R.style.DialogStyle);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.image_viewpager, container, false);
viewPager = view.findViewById(R.id.viewpager);
author = view.findViewById(R.id.author);
buttonShare = view.findViewById(R.id.btnShare);
count = view.findViewById(R.id.count);
hits = (ArrayList<Hit>) getArguments().getSerializable("hits");
selectedPosition = getArguments().getInt("position");
viewPagerAdapter = new ViewPagerAdapter();
viewPager.setAdapter(viewPagerAdapter);
viewPager.addOnPageChangeListener(onViewPageChangeListener);
setItem(selectedPosition);
return view;
}
private void setItem(int pos) {
viewPager.setCurrentItem(pos, true);
setItemInfo(selectedPosition);
}
private void setItemInfo(int pos) {
count.setText((pos + 1) + " of " + hits.size());
Hit hit = hits.get(pos);
author.setText(hit.getUser());
}
ViewPager.OnPageChangeListener onViewPageChangeListener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
setItemInfo(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
};
I Guess the Problem is here
private void setItem(int pos) {
viewPager.setCurrentItem(pos, true);
setItemInfo(selectedPosition);
}
You might be passing the selectedPosition instead of currentPosition
Please check.
My problem was in creating DialogFramgent object.
I did it him in Singlton pattern and called it with old data.
Now in OnClick i'm created new object DialogFramget and him get new values.
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fullScreenDialog = new FullScreenDialogFragment();
fullScreenDialog.setArguments(bundle);
fullScreenDialog.show(fragmentTransaction, "");
Related
I have a pageradapter that i am using to display a slideshow of images but it crashes when i set a lower off screen limit.
Here is my code
public class ProjectPicturesAdapter extends PagerAdapter {
private List<String> pictures;
private LayoutInflater inflater;
private final RequestManager glide;
public ProjectPicturesAdapter(RequestManager glide, LayoutInflater inflater, List<String> pictures) {
this.pictures = pictures;
this.glide = glide;
this.inflater = inflater;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View image = inflater.inflate(R.layout.slider_image, container, false);
ImageView myImage = (ImageView) image.findViewById(R.id.image);
glide.load(pictures.get(position))
.centerCrop()
.crossFade()
.placeholder(R.drawable.project_placeholder)
.into(myImage);
container.addView(myImage);
return myImage;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((View) view);
}
#Override
public int getCount() {
return pictures.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
}
The way i am initializing the adapter is this
ProjectPicturesAdapter picturesAdapter = new
ProjectPicturesAdapter(Glide.with(this), LayoutInflater.from(this),
images);
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(picturesAdapter);
pager.setOffscreenPageLimit(1);
If there are more than 2 images then it crashes,i could always increase the off screen limit but what happens if there are 20 pictures,i cannot keep the offscreen limit as 20.
My crash log is gives an error saying The specified child already has a parent. You must call removeView() on the child's parent first.
Update ProjectPicturesAdapter as below:
public class ProjectPicturesAdapter extends PagerAdapter {
private List<String> pictures;
private LayoutInflater inflater;
private final RequestManager glide;
public ProjectPicturesAdapter(RequestManager glide, LayoutInflater inflater, List<String> pictures) {
this.pictures = pictures;
this.glide = glide;
this.inflater = inflater;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.slider_image, container, false);
ImageView myImage = (ImageView) view.findViewById(R.id.image);
glide.load(pictures.get(position))
.centerCrop()
.crossFade()
.placeholder(R.drawable.project_placeholder)
.into(myImage);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((View) view);
}
#Override
public int getCount() {
return pictures.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
If your aim is to show the carousel?
Just use this library and your problem will be solved https://github.com/sayyam/carouselview
The problem is caused by this:
#Override
public void destroyItem(ViewGroup container, int position, Object view)
{
container.removeView((View) view);
}
I recommend to use FragmentStatePagerAdapter instead of PagerAdapter.
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
}
mAdapter = new MyAdapter(getFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
I have a regular ViewPager with an adapter:
public class MyDialogFragment extends DialogFragment {
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private City city;
public static MyDialogFragment newInstance() {
MyDialogFragment fragment = new MyDialogFragment();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_layout, container, false);
viewPager = (ViewPager) v.findViewById(R.id.viewPager);
city = Parcels.unwrap(getArguments().getParcelable("city"));
myViewPagerAdapter = new MyViewPagerAdapter(getContext());
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// Page changed
}
});
return v;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public class MyViewPagerAdapter extends PagerAdapter {
private Context context;
private LayoutInflater layoutInflater;
public MyViewPagerAdapter(Context context) {
this.context = context;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.city_layout, container, false);
ImageView imageView = (ImageView) view.findViewById(R.id.cityImage);
Glide.with(context)
.load(city.getImage())
.into(imageView);
}
container.addView(view);
return view;
}
#Override
public int getCount() {
return city.size();
}
#Override
public boolean isViewFromObject(View view, Object obj) {
return view == ((View) obj);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
As you can see, I have a page change listener set on my ViewPager. But I need to be able to notify the adapter when the page has changed so that I can modify the adapter's ImageView. How can I do this?
Add a method to your adapter class
public class MyViewPagerAdapter extends PagerAdapter {
...
public void pageChanged(int position) {
// Do something
}
...
}
After that in your OnPageChangeListener use that method
#Override
public void onPageSelected(int position) {
myViewPagerAdapter.pageChanged(position);
}
One approach is to create a data structure in your adapter to map the pager view to its position. A SparseArray is most efficient:
private SparseArray<View> pageMap = new SparseArray<>();
Then in the adapter's instantiateItem() method, add the view to the SparseArray:
public Object instantiateItem(ViewGroup container, int position) {
...
pageMap.put(position, view);
...
}
Now in your OnPageChangeListener you can do the following:
#Override
public void onPageSelected(int position) {
View view = adapter.getView(pos);
if (view != null) {
ImageView iv = (ImageView) view.findViewById(R.id.your_image_view);
// You now have the image view
}
}
Make sure you remove views from the SparseArray in the adapter's destroyItem() method:
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
pageMap.remove(position);
...
}
You can use the constructor with imagelist to pass and that automatically called on next page..In your code will be modified like :::
ArrayList imageList=new ArrayList<>();
imageList.add("ImagePath here");
myViewPagerAdapter = new MyViewPagerAdapter(getContext(),imageList);
viewPager.setAdapter(myViewPagerAdapter);
Then your adapter will be like ::
public class MyViewPagerAdapter extends PagerAdapter {
private Context context;
private ArrayList<String> imageList
private LayoutInflater layoutInflater;
public MyViewPagerAdapter(Context context,ArrayList<String> imageList) {
this.context = context;
this.imageList = imageList;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.city_layout, container, false);
ImageView imageView = (ImageView) view.findViewById(R.id.cityImage);
Glide.with(context)
.load(imageList.get(position)) // This will be changes like
.into(imageView);
}
container.addView(view);
return view;
}
#Override
public int getCount() {
return city.size();
}
#Override
public boolean isViewFromObject(View view, Object obj) {
return view == ((View) obj);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
That done ..
After this, there are some suggestion that
- please use arraylist while using the viewpager ..
Now you just taking the parceble object from bundle..
you can do the same for the arraylist,
just receive the arraylist from the same bundle by passing the whole arraylist at once.
so you dont need to find the page change event..viewpager will automatically handle that..
Here's How to send & receiving the parceable arraylist
// while sending the list
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("citylist", new ArrayList<City>());
// while receiving the list
ArrayList<City> citylist = getIntent().getParcelableArrayListExtra("citylist");
After this just get the all image and add in the imagelist array
for (int i = 0; i < citylist.size(); i++) {
imageList.add(citylist.get(i).getImage());
}
And pass this imageList in
myViewPagerAdapter = new MyViewPagerAdapter(getContext(),imageList);
viewPager.setAdapter(myViewPagerAdapter);
Tell me if needed more assitance.
i'm trying to put ViewPager into ListView
here the code of ListView AdapterClass:
public class AdapterPager extends BaseAdapter {
.....
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.component_pager, parent, false);
new ViewHolder(view, itemData.get(position));
}
return view;
}
View Holder:
private class ViewHolder {
ViewPager pager;
PagerAdapter pagerAdapter;
public ViewHolder(View view, ModelItem model){
pager = (ViewPager) view.findViewById(R.id.pager);
pager.setId(model.getId()); /// uniq ID
pagerAdapter = new MyFragmentPagerAdapter(((FragmentActivity)view.getContext()).getSupportFragmentManager());
pager.setAdapter(pagerAdapter);
}
then, Pager Adapter:
static final int PAGE_COUNT = 2;
private class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return FragmentComponentPager.newInstance(position, mModel);
}
#Override
public float getPageWidth(int position) {
float f_width = 1f;
return f_width;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
}
and, the last, Pager Fragment:
public class FragmentComponentPager extends Fragment {
static final String ARGUMENT_PAGE_NUMBER = "arg_page_number";
static final String ARGUMENT_NAME = "arg_name";
int pageNumber;
public static FragmentComponentPager newInstance(int page, ModelItem data) {
FragmentComponentPager pageFragment = new FragmentComponentPager();
Bundle arguments = new Bundle();
arguments.putInt(ARGUMENT_PAGE_NUMBER, page);
if (data != null){
arguments.putString(ARGUMENT_NAME, data.getName());
}
pageFragment.setArguments(arguments);
return pageFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pageNumber = getArguments().getInt(ARGUMENT_PAGE_NUMBER);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.component_list, null);
TextView tvTitle = (TextView) view.findViewById(R.id.tvTitle);
tvTitle.setText(getArguments().getString(ARGUMENT_NAME));
return view;
}
}
when i run it ListView shows all items that i've added, but all of them, except the last one, with empty ViewPager.
and, if i removed pager.setId(model.getId()); the first item shows view pager, and the others empty.
guess that smth wrong with FragmentManager, but have no idea how deal with it :(
In your ViewHolder you need to call getChildFragmentManager instead of getSupportFragmentManager.
im trying to create an image gallery.
i have a ViewPager that each Fragment contains an image (swipable image gallery is what im trying to accomplish).
i also have a GridView that onitemclick triggers the ViewPager in the selected position showing the clicked image.
my problem is that one swipe to right and one swipe to left shows the same image as the clicked one.
ive tried setoffscreenpagelimit with no success.
this is my viewpager activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_gallery);
helper = new WeddHelper(this,"wedd.db",null,1);
pager = (ViewPager) findViewById(R.id.pager);
pager.setOnPageChangeListener(this);
Intent ing = getIntent();
curr = ing.getIntExtra("curr", 0);
byto = helper.getPhotos();
count = byto.size();
FragmentManager mg = getSupportFragmentManager();
fragments = new Vector<Fragment>();
for(int i = 0; i<count;i++){
fragments.add(Fragment.instantiate(this,GalleryFrag.class.getName()));
}
mAdapter = new FragmentAdapter(getSupportFragmentManager(), fragments, this);
pager.setAdapter(mAdapter);
pager.setOffscreenPageLimit(1);
pager.setCurrentItem(curr);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
mCurrentPosition = position;
curr = position;
}
#Override
public void onPageScrollStateChanged(int state) {
}
public int getClicked(){
return curr;
}
public byte[] getPhotoToBeDisplayed(){
return byto.get(curr);
}
}
this is my custom adapter:
public class FragmentAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments=null;
private FragmentManager fragmentManager=null;
private Context context;
public FragmentAdapter(FragmentManager fragmentManager,List<Fragment> fragments, Context context) {
super(fragmentManager);
this.fragments=fragments;
this.fragmentManager=fragmentManager;
this.context = context;
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object)
{
super.setPrimaryItem(container,0,object);
}
#Override
public void notifyDataSetChanged()
{
super.notifyDataSetChanged();
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
fragmentManager.executePendingTransactions();
fragmentManager.saveFragmentInstanceState(fragments.get(position));
}
public void replaceItem(int position,Fragment fragment)
{
fragments.set(position, fragment);
this.notifyDataSetChanged();
}
}
and this is the fragment:
public class GalleryFrag extends Fragment {
WeddHelper helper;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.gallery_fragment, container, false);
ImageGallery myActivity = (ImageGallery) getActivity();
int curr = myActivity.getClicked();
byte[] photoToBeDisplayed = myActivity.getPhotoToBeDisplayed();
helper = new WeddHelper(getActivity(),"wedd.db", null, 1);
ArrayList<byte[]> imgs = helper.getPhotos();
Bitmap br = BitmapFactory.decodeByteArray(photoToBeDisplayed,0,photoToBeDisplayed.length);
Bitmap bi = BitmapFactory.decodeByteArray(imgs.get(curr),0,imgs.get(curr).length);
Toast.makeText(getActivity(), curr+"this is from frag", Toast.LENGTH_SHORT).show();
ImageView iv = (ImageView) v.findViewById(R.id.fragImage);
iv.setImageBitmap(br);
return v;
}
}
I have a CarsFragment which is inculde cars. One page is one trade (Ferrari, Mercedes) and on every page has a list with models of actual trade.
The main view:
public class CarsFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cars_fragment, container, false);
pager = (ViewPager) view.findViewById(R.id.carsPager);
adapter = new CarsPagerAdapter(getChildFragmentManager());
pager.setAdapter(adapter);
return view;
}
}
Adapter:
public class CarsPagerAdapter extends FragmentStatePagerAdapter {
private final FragmentManager fm;
private String[] cars = new String[]{"Ferrari","Mercedes"};
public MatchesPageAdapter(final FragmentManager fm) {
super(fm);
this.fm = fm;
}
#Override
public int getCount() {
return cars.length;
}
#Override
public Fragment getItem(final int position) {
return FragmentModelList.newInstance(cars[position]);
}
#Override
public void destroyItem(final ViewGroup container, final int position, final Object object) {
super.destroyItem(container, position, object);
}
}
List:
public class FragmentModelList extends Fragment {
public static FragmentModelList newInstance(String trade) {
FragmentModelList fragmentModelList = new FragmentModelList();
Bundle args = new Bundle();
args.putString("trade", trade);
fragmentModelList.setArguments(args);
return fragmentModelList;
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_matches_list_view, container, false);
list = (ListView) view.findViewById(R.id.modelList);
return view;
}
#Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
modelListAdapter = new ModelListAdapter(getActivity());
list.setAdapter(modelListAdapter);
loadModels();
}
private void loadModels() {
new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(final Void... params) {
try {
List<Model> result = Downloader.getModelsByName(getArguments().getString("trade"));
modelListAdapter.setData(result);
return true;
} catch (Exception ex) {
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (!success) {
// Show error
} else {
// Update list
modelListAdapter.notifyDataSetChanged();
}
}
}.execute();
}
}
and the modelListAdapter set row where one row inculde 2 image and some textview.
And the problem:
when i swiping on the viewpager it isn't smooth :( a loged it and when created the next or previous page (depends on swipe direction) the animation will be bad, is lagging.
What is the solution?
(SGS4 android 4.2.2 - where is the project butter :(( )