View Pager destroy items when i scroll down - java

I am using Image slider inside recycler View Items, each item have view pager and its own image slider, After loading all items in recycler view. first item display image slider inside its view pager, Then i scroll down to other items may be to item 10 or 11 and then i scroll up to first item then view pager destroy all items or fragments inside it and no image has been displayed now . please give me solution for this, my adapter code . Can't User FragmentStatePagerAdapter because not have access to Fragment Manager
private class ViewPagerAdapter extends PagerAdapter {
ArrayList<ImageInfo> allImages=new ArrayList<>();
private ViewPagerAdapter(ArrayList<ImageInfo> allImages){
this.allImages = allImages;
}
#Override
public int getCount() {
return allImages.size();
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
View itemView = LayoutInflater.from(myContext).inflate(R.layout.fragment_big_row_image, container, false);
ImageView imageListing = (ImageView) itemView.findViewById(R.id.imageListing);
//MH: Loading Images in slider
if(allImages.get(position).csImageFull.length()>0)
{
CommonMethods.ShowImage(myContext, imageListing, allImages.get(position).csImageFull);
}
else
{
CommonMethods.ShowImage(myContext, imageListing, allImages.get(position).csImageMedium);
}
container.addView(itemView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
// ((ViewPager) container).removeView((View) object);
// instantiateItem(container,position);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
/*****************************************************************************************************/

Set off screen pages in your viewpager. Offscreen page limit defines how many pages you want to keep in memory in your view pager. Set this number to your desired page count.
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(2);
Here view pager will keep last visited 2 pages in memory and won't destroy them.

Try Below Code:
public class SliderPagerAdapter extends PagerAdapter {
private Activity activity;
private ArrayList<String> images;
public SliderPagerAdapter(Activity activity) {
this.activity = activity;
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.item_slider, container, false);
ImageView allImages = null;
/MH: Loading Images in slider
if(images.get(position).csImageFull.length()>0)
{
CommonMethods.ShowImage(myContext, imageListing, allImages.get(position).csImageFull);
}
else
{
CommonMethods.ShowImage(myContext, allImages, images.get(position).csImageMedium);
}
container.addView(itemView);
return view;
}
public void setData(ArrayList<String> images) {
this.images = images;
notifyDataSetChanged();
}
#Override
public int getCount() {
return images == null ? 0 : images.size();
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object obj) {
return view == obj;
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
View view = (View) object;
container.removeView(view);
}
}
Call method setData from activity and set image array.
Adapter.setData(yourData);

Related

Which event is called when user exits spinner

I have a spinner and I want to show/hide something when the user exits the spinner without doing any thing. for example, when the user touches an area outside the spinner.
p.s. the onTouchEvent for the container layout (LinearLayout in my case) is also not called.
here is my implementation for the custom spineer:
public SpinnerHintAdapter(Activity context, int resourceId, int textViewId, List<SpinnerItem> list, Spinner parent){
super(context,resourceId,textViewId, list);
flater = context.getLayoutInflater();
this.items = list;
this.gender = parent;
}
#Override
public int getCount() {
return items.size();
}
#Nullable
#Override
public SpinnerItem getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
SpinnerItem spinnerItem = getItem(position);
View rowView = flater.inflate(R.layout.gender_item ,null,true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.main_text);
txtTitle.setText(spinnerItem.getName());
txtTitle.setTextColor(txtTitle.getResources().getColor(R.color.color_white));
Log.i(Tags.byEmail, "VVVVVVVVVVVVv");;
gender.setVisibility(View.VISIBLE);
return rowView;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
firstTime = false;
SpinnerItem rowItem = getItem(position);
View rowView = flater.inflate(R.layout.gender_drop_down_item ,null,true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.drop_down_text);
txtTitle.setText(rowItem.getName());
if(!isEnabled(position)){
txtTitle.setBackground(txtTitle.getResources().getDrawable(R.drawable.normal_rounded_text_field));
txtTitle.setTextColor(Color.parseColor("#777777"));
}
parent.setBackground(parent.getResources().getDrawable(R.drawable.normal_rounded_text_field));
txtTitle.setEnabled(isEnabled(position));
gender.setVisibility(View.INVISIBLE);
Log.i(Tags.byEmail, "DDDDDDDDDDDDDDDDDD");
return rowView;
}
#Override
public boolean isEnabled(int position) {
if(position == 0)
return false;
return super.isEnabled(position);
}
}
when the user exits without selecting an item the getView function is not called and hence the gender (is the spinner object itself) will not be visible.
I tried OnItemSelected and OnNothingSelected are also not called.
event OnTouch events are not called.
The following Events are not called when the user exits:
1- OnItemSlected
2- OnNothingSelected
3- OnFocusChanged.
4- OnTouch
I think that's event will work for you as magic, no?
public class CustomSpinner extends Spinner {
... Constructors ...
#Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
Log.d(CustomSpinner.class.getSimpleName(), "onWindowFocusChanged: " + hasWindowFocus);
if (hasWindowFocus) {
// User click out of window
} else {
// User click in spinner window
}
}
}
With a Spinner you set an AdapterView.OnItemSelectedListener which implements two methods; onItemSelected and onNothingSelected.
Like this:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// This is called when the user selects an item in the Spinner
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// This is called when the user closes the spinner selecting nothing
}
});

ViewPager not responding quickly

While using a ViewPager i noticed that it wouldn't respond very quickly, meaning that it slows down when switchting through fragments, kind of in a laggy way.
Does anyone know how this code could be causing the issue?
public class List_adapter : BaseAdapter<Element>
{
public List<Element> _list;
FragmentOne _context;
public List_adapter(FragmentOne context, List<Element> list)
{
super(context, list);
_list = list;
_context = context;
}
#Override
public int getCount()
{
return _list.size();
}
#Override
public Object getItem(int position)
{
return _list.get(position);
}
#Override
public long getItemId(int position)
{
return getItem(position).hashCode();
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater)getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.row, parent, false);
Element item = getItem(position);
TextView lbl = (TextView)view.findViewById(R.id.label);
TextView prop = (TextView)view.findViewById(R.id.Prop);
lbl.setText(item.getlabel());
prop.setText(item.getprop());
return view;
}
}
Use ViewHolder pattern for smooth list scrolling
Implement Offscreen page limit for initialising a view before showing it inside ViewPager

Android onClick custom PageAdapter

So I have created a generic PageAdapter to be used in various parts on the app, which looks like this:
public class ImagePagerAdapter extends PagerAdapter {
private final LayoutInflater layoutInflater;
private final Picasso picasso;
private final int layoutResId;
private final List<AssociatedMedia> images;
public ImagePagerAdapter(Context context, int layoutResId) {
layoutInflater = LayoutInflater.from(context);
picasso = Injector.getInstance().getPicasso();
this.layoutResId = layoutResId;
this.images = new ArrayList<>();
}
public void setMedia(List<AssociatedMedia> media) {
images.clear();
for (AssociatedMedia productMedia : media) {
if (productMedia.type == AssociatedMediaType.IMAGE) {
images.add(productMedia);
}
else {
// non-images all at the end
break;
}
}
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
AssociatedMedia image = images.get(position);
ImageView imageView = (ImageView) layoutInflater.inflate(layoutResId, container, false);
container.addView(imageView);
picasso.load(Uri.parse(image.urls[0])).into(imageView);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
ImageView imageView = (ImageView) object;
container.removeView(imageView);
picasso.cancelRequest(imageView);
}
#Override
public int getCount() {
return images.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
I then call this adapter in a fragment, like this:
ImagePagerAdapter productImageAdapter = new ImagePagerAdapter(getActivity(), R.layout.photo_container_small);
productImageAdapter.setMedia(medias);
productImage.setAdapter(productImageAdapter);
My question is, how can I invoke a onClickListener in the fragment. So my scenario is that, we have a carousel of images, and once the user click on an image, it will open a large view on that image, so sort of need an onItemClickListener, but this can only be invoked in the pagerAdapter.
So is there a way to either call a onClickListener in the fragment, or notify the fragment from the adapter when an item has been clicked?
This is a response to your comment. For formating and size reasons I use an answer for it. It is a general example on how to use an interface to de-couple a fragment from an adapter class which makes the adapter re-usable in several fragments (and even other projects).
public class MyAdapter {
MyAdapterListener listener;
private MyAdapter() {}
public MyAdapter(MyAdapterListener listeningActivityOrFragment) {
listener = listeningActivityOrFragment;
}
}
public interface MyAdapterListener {
void somethingTheFragmentNeedsToKnow(Object someData);
}
public class SomeFragment extends Fragment implements MyAdapterListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.my_view, container, false);
// Do everyhting here to init your view.
// Create an Adapter and bind it to this fragment
MyAdapter myAdapter = new MyAdapter(this);
return view;
}
// Implement the listener interface
#Override
public void somethingTheFragmentNeedsToKnow(Object someData) {
// Get the data and process it.
}
}
So in your case the method within the interface may well be onClick(int position); If you need more than one method, then just add them.

How to use notifySetDataChange in adapter for refresh listview

I used fragment in my app and i'm using SQLite to save local data. But when I finished saving data, and I swipe the page, my listView is not refreshed with new data (Only showing old data). I have tried to provide a method notifyDataSetChanged() on my adapter, but it's not working.
My Base Adapter class :
public class LocalDataAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<LocalDataBean> data;
private static LayoutInflater inflater = null;
public LocalDataAdapter(Activity a, ArrayList<LocalDataBean> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setItem(ArrayList<LocalDataBean> data){
this.data = data;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView nama_konsumen = (TextView) v.findViewById(R.id.nama_konsumen);
TextView no_telp = (TextView) v.findViewById(R.id.no_telp);
TextView no_hp_cdma = (TextView) v.findViewById(R.id.no_hp_cdma);
TextView no_hp_gsm = (TextView) v.findViewById(R.id.no_hp_gsm);
LocalDataBean obj = (LocalDataBean) getItem(position);
nama_konsumen.setText(obj.getNamaKonsumen());
no_telp.setText(obj.getNoTelp());
no_hp_cdma.setText(obj.getNoCMDA());
no_hp_gsm.setText(obj.getNoGSM());
return v;
}
}
My fragment class :
public class LocalDataFragment extends Fragment {
View view;
Activity act;
SQLHandlerBean utilSql;
ArrayList<LocalDataBean> localdatabean = new ArrayList<LocalDataBean>();
LocalDataAdapter adapter;
ListView list;
public static final String TAG = LocalDataFragment.class.getSimpleName();
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_local_data, null);
act = getActivity();
list = (ListView) view.findViewById(R.id.listViewLocalData);
utilSql = new SQLHandlerBean(this.act);
adapter = new LocalDataAdapter(act, localdatabean);
localdatabean = new ArrayList<LocalDataBean>();
list.setAdapter(adapter);
if (utilSql.ReadAllLocalData().size() < 1) {
Toast.makeText(act, "DATA EMPTY!", Toast.LENGTH_LONG).show();
} else {
localdatabean = utilSql.ReadAllLocalData();
Log.e(TAG, "TOTAL DATA : "+localdatabean.size());
adapter.setItem(localdatabean);
adapter.notifyDataSetChanged();
}
return view;
}
}
Is adapter.notifyDataSetChanged() placement correct?
No, the placement is not in the right place.
As you have placed the notifyDataSetChanged() inside of the onCreateView() method. It will be only invoked 1st time the fragment is launched.
Rather you can add a refresh button in your layout (or in you action bar). And along with the insertion/deletion method of the data, place the notifyDataSetChanged() at the bottom of the click event of that button.
By doing this user can refresh the page whenever they want.
And if you want to refresh the page by swipping the view then, SwipeRefreshLaoyout could be a perfect alternative.
You can check this blog.

How to refer back to a created viewPager to add more imageViews dynamically

I have a PagerAdapter that displays images gathered from a string array of locations passed from the MainActivity class. I wish to make it so that I can refer to this PagerAdapter in the future, to create more views dynamically. I am curious as to how one goes about to doing this? My code for the PagerAdapter (the converted ArrayList is the one passed from the MainActivity class):
public class ViewPagerAdapter extends PagerAdapter {
// Declare Variables
Context context;
ArrayList<String> converted;
ArrayList<View> views = new ArrayList<View>();
LayoutInflater inflater;
public ImageView imgzoomer;
public ViewPagerAdapter(Context context, ArrayList<String> converted) {
this.context = context;
this.converted = converted;
}
#Override
public int getCount() {
return converted.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((RelativeLayout) object);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if(position==converted.size()-1){
// Declare Variables and Views
// Capture position and set to the ImageView
Bitmap bitmap = BitmapFactory.decodeFile(converted.get(position));
bitmap.recycle();
imgzoomer.setImageBitmap(bitmap);
// Add layout_fullscreen_image.xml to ViewPager
container.removeAllViewsInLayout();
container.removeAllViews();
container.addView(container, position+1);
notifyDataSetChanged();
}
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
// Declare Variables and Views
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.layout_fullscreen_image, container,false);
imgzoomer = (ImageView) itemView.findViewById(R.id.zoomer);
// Capture position and set to the ImageView
Bitmap bitmap = BitmapFactory.decodeFile(converted.get(position));
imgzoomer.setImageBitmap(bitmap);
// Add layout_fullscreen_image.xml to ViewPager
container.addView(itemView, 0);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
// Remove viewpager_item.xml from ViewPager
container.removeView(imgzoomer);
}
}
The part where I want to refer to the ViewPager again in my MainActivityClass:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//get the view
setContentView(R.layout.viewpager_main);
ImageView imgzoomer;
//Doinbackground ASYNCTASK (returns the converted arraylist, which is the location of the pics in the storage)
new XMLParse().execute(url);
//Locate ViewPager
viewPager = (ViewPager) findViewById(R.id.pager);
//PageChangeListener
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
//THIS PART HERE<------------
public void onPageScrolled(int position, float v, int i2) {
if(position>=converted.size()-1){
}
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
}

Categories

Resources