ListView loses position after updating adapter listView.setAdapter(new MyAdapter(...)) - java

When end items in a ListView, i upload new, and after update adapter:
ListView lvMain = (ListView) findViewById(R.id.list);
boxAdapter = null;
boxAdapter = new BoxAdapter(this, products);
lvMain.setAdapter(boxAdapter);
But after this, elements are loaded but the scroll position the top. Ie the position of ListView is lost, and look again at the beginning of all
How fix it?
BoxAdapter code:
public class BoxAdapter extends BaseAdapter {
private final Context ctx;
private final LayoutInflater lInflater;
private final ArrayList<ItemInfo> objects;
private final int loadCount = 10;
private int count = 10;
private String name, desc;
BoxAdapter(Context context, ArrayList<ItemInfo> products) {
this.ctx = context;
this.objects = products;
this.lInflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
// кол-во элементов
#Override
public int getCount() {
//return objects.size();
return this.count;
}
// элемент по позиции
#Override
public ItemInfo getItem(int position) {
return objects.get(position);
}
// id по позиции
#Override
public long getItemId(int position) {
return position;
}
public void loadAdditionalItems() {
this.count += this.loadCount;
if (this.count > this.objects.size()) {
this.count = this.objects.size();
}
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
view = lInflater.inflate(R.layout.item, parent, false);
ItemInfo p = getItem(position);
TextView desc_id = (TextView) view.findViewById(R.id.desc);
if (p.username.contains("null"))
{
name = "Автор: Неизвестен";
}
else
{
name = "Автор: " + p.username;
}
if(!p.description.contains("null"))
{
desc = p.description.replaceAll("<br />", "");
desc = desc.replaceAll(""", "");
}
else
{
desc = "";
desc_id.setVisibility(View.GONE);
}
((TextView) view.findViewById(R.id.name)).setText(name);
((TextView) view.findViewById(R.id.desc)).setText(desc);
return view;
}
}
P.S setOnScrollListener code:
lvMain.setOnScrollListener(new OnScrollListener()
{
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
ListView lvMain = (ListView) findViewById(R.id.list);
if(firstVisibleItem + visibleItemCount >= totalItemCount) {
boxAdapter.loadAdditionalItems();
loading = false;
}
if (!loading && (lvMain.getLastVisiblePosition() + 10) >= (60))
{
new LoadLastestPost().execute();
loading = true;
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
});

The best solution would be to create a setProducts method in your boxAdapter and then just call boxAdapter.notifyDataSetChanged(). For example:
boxAdapter.setProducts(products);
boxAdapter.notifyDataSetChanged();
If you implement this method, there is no need to call lvMain.setAdapter(boxAdapter) more than once.
To add the setProducts() method to your adapter:
public BoxAdapter extends BaseAdapter {
Context mContext;
ArrayList<ItemInfo> objects;
public BoxAdapter(Context context, ArrayList<ItemInfo> products) {
mContext = context;
objects = products;
}
public View getView(int position, View convertView, ViewGroup parent) {
// inflate and adjust view
}
public int getCount() {
return objects.size();
}
public Object getItem(int position) {
return objects.get(position);
}
public void setProducts(ArrayList<ItemInfo> newData) {
objects = newData;
}
}
Also, I wouldn't use a count variable. I would just use the size method in the ArrayList. I would remove count altogether.

Related

ListView Adapter with multiple Item layouts not working

I am trying to display a ListView of some docs and images with different layouts.
it worked for docs but images are still not showing.
I have used the .contains method to check if the item is doc or image. Help me with this.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = activity.getLayoutInflater();
String fileName = uriList.get(position).getFileName();
return viewSetup(position, layoutInflater, fileName);
}
private View viewSetup(final int position, LayoutInflater layoutInflater, String fileName) {
if (fileName.contains(".png") || fileName.contains(".jpg") || fileName.contains(".jpeg")) {
View inflate = layoutInflater.inflate(R.layout.main_list_item_img, null, false);
ImageView imageView = inflate.findViewById(R.id.imgPrev);
Glide.with(activity).load(uriList.get(position).getDownloadLink()).into(imageView);
itemSetup(position, fileName, inflate);
return inflate;
} else {
View inflate = layoutInflater.inflate(R.layout.main_list_item_docs, null, false);
itemSetup(position, fileName, inflate);
return inflate;
}
}
private void itemSetup(final int position, String fileName, View inflate) {
TextView title = inflate.findViewById(R.id.uriTitle);
TextView desc = inflate.findViewById(R.id.uriDesc);
ImageView download = inflate.findViewById(R.id.download);
TextView createdOn = inflate.findViewById(R.id.createdOn);
title.setText(fileName + "");
desc.setText(uriList.get(position).getDescription());
createdOn.setText(uriList.get(position).getSendTime());
download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
savefile(uriList.get(position).getDownloadLink());
}
});
}
I think there is a problem in your image loading. You can use Picasso.
Picasso.with(activity).load(yourUrl).
placeholder(R.drawable.image_loader).into(myImage);
You need to use type variable you can check how I did in below example :-
public class JobsAdapter extends BaseAdapter {
private Activity context;
private LinkedList<KeyValuesPair> listItemArrayList;
private LinkedList<Integer> type;
private LayoutInflater inflater;
public JobsAdapter(Activity context, LinkedList<KeyValuesPair> objects, LinkedList<Integer> type) {
this.context = context;
this.listItemArrayList = objects;
this.type = type;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return type.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean isEnabled(int position) {
return type.get(position) != 0;
}
#TargetApi(Build.VERSION_CODES.O)
public View getView(int position, View convertView, ViewGroup parent) {
// used new view instead of convertView so the spinner could support multiple views
View view = null;
// if type is equals to 0 it will load jobs header else jobs child
if (type.get(position) == 0) {
view = inflater.inflate(R.layout.lv_header, null, false);
TextView header = view.findViewById(R.id.jobsHeading);
header.setText(listItemArrayList.get(position).getValue());
if (position == 0) {
header.setTextSize(16);
header.setTypeface(context.getResources().getFont(R.font.raleway_regular));
header.setTextColor(context.getResources().getColor(R.color.colorPrimaryDark));
} else {
header.setTextColor(context.getResources().getColor(R.color.colorBlack));
}
} else if (type.get(position) == 1) {
view = inflater.inflate(R.layout.lv_child, null, false);
TextView child = view.findViewById(R.id.jobsChild);
child.setText(listItemArrayList.get(position).getValue());
}
return view;
}
}

how to add spacing between items in dynamic spinner

I have created a simple dynamic spinner all I need to add spacing and add a break line between each item,also I need to know how to add more attributes like item text color,item text size......etc,by the way this spinner is created in a tool bar
and this is my Simple Code with adapter
Spinner navigationSpinner = new Spinner(getSupportActionBar().getThemedContext());
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, Prests_Name);
navigationSpinner.setAdapter(adapter);
I have same requirement so i have created generic adapter class with some extra parameters. so you can check this out and make changes as per your requirement.
SpinnerAdapter
public class SpinnerAdapter<T> extends ArrayAdapter<T> {
private Context context;
private ArrayList<T> values;
private Typeface fontLight;
private int color, layoutId, textViewId;
//private int fontSize;
private boolean IsSingleLine;
private boolean IsFirstPositionSelectable, setTextSizeLimit = true;
public SpinnerAdapter(Context context, int resource, int textViewResourceId,
ArrayList<T> objects) {
super(context, resource, textViewResourceId, objects);
this.context = context;
this.values = objects;
this.layoutId = resource;
this.textViewId = textViewResourceId;
}
public SpinnerAdapter(Context context, int resource, ArrayList<T> objects, int color,
boolean isSingleLine) {
super(context, resource, objects);
this.context = context;
this.values = objects;
this.color = color;
this.IsSingleLine = isSingleLine;
}
#Override public int getCount() {
return values.size();
}
#Override public T getItem(int position) {
return values.get(position);
}
#Override public long getItemId(int position) {
return position;
}
public boolean isFirstPositionSelectable() {
return IsFirstPositionSelectable;
}
public void setFirstPositionSelectable(boolean enable) {
IsFirstPositionSelectable = enable;
}
public void setSetTextSizeLimit(boolean setTextSizeLimit) {
this.setTextSizeLimit = setTextSizeLimit;
}
public Typeface getFontLight() {
return fontLight;
}
public void setFontLight(Typeface fontLight) {
this.fontLight = fontLight;
}
#Override public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
if (layoutId == 0) {
convertView = inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
} else {
convertView = inflater.inflate(layoutId, parent, false);
}
}
TextView label;
if (textViewId == 0) {
label = (TextView) convertView.findViewById(android.R.id.text1);
} else {
label = (TextView) convertView.findViewById(textViewId);
}
if (setTextSizeLimit) {
label.setFilters(new InputFilter[] { new InputFilter.LengthFilter(2) });
}
label.setSingleLine(IsSingleLine);
label.setPaddingRelative(25, 15, 25, 15);
if (fontLight != null)
label.setTypeface(getFontLight());
label.setText(values.toArray(new Object[values.size()])[position].toString());
return label;
}
#Override public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
if (layoutId == 0) {
convertView = inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
} else {
convertView = inflater.inflate(layoutId, parent, false);
}
}
TextView label;
if (textViewId == 0) {
label = (TextView) convertView.findViewById(android.R.id.text1);
} else {
label = (TextView) convertView.findViewById(textViewId);
}
//label.setPadding(30, 10, 10, 30);
//label.setTextSize(context.getResources().getDimension(R.dimen.text_size_small));
if (fontLight != null)
label.setTypeface(fontLight);
label.setSingleLine(IsSingleLine);
label.setText(values.toArray(new Object[values.size()])[position].toString());
return label;
}
}

Custom Adapter not working for the listview from Parse.com

I am trying to create an android application using a database from Parse.com. I am using a custom adapter to create a listview. I don't find any errors with the code and yet the listeview is not showing up. Nothing there in the logcat as well. Just the listview does not show up.
lv = (ListView)findViewById(R.id.listView);
mProgress = (ProgressBar)findViewById(R.id.check_progress);
mProgress.setVisibility(View.VISIBLE);
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Sellers");
query.orderByAscending("Name");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> parseObjects, ParseException e) {
if (e == null) {
studentsList = new ArrayList<Sellers>();
for (ParseObject ob : parseObjects) {
s = new Sellers();
s.setName(ob.getString("Name").toString());
s.setAddress1(ob.getString("Address1").toString());
s.setAddress2(ob.getString("Address2").toString());
s.setShopName(ob.getString("ShopName").toString());
s.setEmail(ob.getString("Email").toString());
s.setPhone(ob.getString("Phone").toString());
s.setZipcode(ob.getString("Zipcode").toString());
studentsList.add(s);
}
adapter = new ListviewAdapter(CheckStatus.this, studentsList);
lv.setAdapter(adapter);
mProgress.setVisibility(View.GONE);
} else {
mProgress.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
This is the activity where I am invoking the listview.
public class ListviewAdapter extends BaseAdapter{
private final static String TAG = ListviewAdapter.class.getSimpleName();
private Context activity;
private LayoutInflater inflater = null;
private List<Sellers> sellers;
int layout;
public ListviewAdapter(Context activity, List<Sellers> sellers) {
this.activity = activity;
this.sellers = sellers;
inflater = LayoutInflater.from(activity);
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
public class ViewHolder {
TextView name ;
TextView shop ;
TextView address1 ;
TextView address2;
TextView phone;
TextView email;
RelativeLayout rl;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
View v =view;
ViewHolder holder = new ViewHolder();
if (view == null) {
LayoutInflater li = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(R.layout.list_item_layout,null);
holder.name = (TextView)v.findViewById(R.id.seller_name);
holder.shop = (TextView)v.findViewById(R.id.shop_name);
holder.address1 = (TextView)v.findViewById(R.id.address1);
holder.address2 = (TextView)v.findViewById(R.id.address2);
holder.phone = (TextView)v.findViewById(R.id.phone);
holder.email = (TextView)v.findViewById(R.id.emailID);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
Sellers s = sellers.get(position);
// String a = s.Name;
// Log.d(TAG, a);
holder.name.setText(s.getName());
holder.shop.setText(s.getShopName());
holder.address1.setText(s.getAddress1());
holder.address2.setText(s.getAddress2());
holder.phone.setText(s.getPhone());
holder.email.setText(s.getEmail());
Log.d("CustomAdapter.class", "CustomAdapter");
// imageView.setImageDrawable(s.getPic());
return v;
}
}
And this is the custom adapter. There are no null pointer exceptions showing up in the logcat. I can't determine why the listview is not getting populated.
Try this;
#Override
public int getCount() {
return sellers.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position:
}
You have to implement your code on getCount() by return number of item listview will be created.

Issues with a tagging system using Autocomplete android

I am trying to implement something similar to facebook's search system, where if a user starts typing in a name it brings autocomplete suggestions based on the letters typed, and with an additional option to search for more results. Each result is an object and not a string, and I have tried adding an extra result for search but every time I click on search or one of the objects a replace text occurs with the object as oppose to the name and I know it is a method of the autocomplete widget. Is there another way to go about it?
Here is my code:
private AutoCompleteTextView sx;
sx = (AutoCompleteTextView) findViewById(R.id.sx);
if(sadapter == null) {
sadapter = new Sadapter(PostActivity.this, usersFound);
sx.setAdapter(sadapter);
}
sx.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (sx.getText().toString().length() <= 3 && sadapter != null) {
usersFound.clear();
sadapter.notifyDataSetChanged();
}
if (sx.getText().toString().length() > 3) {
usersFound.clear();
sadapter.notifyDataSetChanged();
Log.d(Constants.DEBUG, "Changing text " + s);
sxname = s.toString();
testCreate();
sadapter.notifyDataSetChanged();
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
sx.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DatabaseUser newAdd = usersFound.get(position);
if(position == searchServerIndex) {
sx.setText(sxname);
usersFound.clear();
sadapter.notifyDataSetChanged();
apiGetPossibleCandidates();
} else {
sx.setText("");
}
}
});
private void testCreate() {
DatabaseUser nuser1 = new DatabaseUser("userid", "pictureid", "Jon");
DatabaseUser nuser2 = new DatabaseUser("userid", "pictureid", "Jonny");
DatabaseUser nuser3 = new DatabaseUser("userid", "pictureid", "Jong");
DatabaseUser nuser4 = new DatabaseUser("userid", "pictureid", "Joan");
DatabaseUser searchServer = new DatabaseUser("SearchId", "pictureid", "Search " + sxname);
usersFound.add(nuser1);
usersFound.add(nuser2);
usersFound.add(nuser3);
usersFound.add(nuser4);
searchServerIndex = usersFound.size();
usersFound.add(searchServer);
if(sadapter != null) {
sadapter.notifyDataSetChanged();
}
}
This is the adapter:
public class Sadapter extends ArrayAdapter<DatabaseUser> {
private Context mContext;
private List<DatabaseUser> usersSearch;
private List<DatabaseUser> usersFiltered;
public Sadapter(Context context, List<DatabaseUser> usersAdded) {
super(context, 0, usersAdded);
mContext = context;
usersSearch = usersAdded;
}
#Override
public int getCount() {
return usersSearch.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.user_autosearch_item, null);
}
//helps for recycling
final ViewHolder holder = new ViewHolder();
holder.userTxt = (TextView) v.findViewById(R.id.userTxt);
v.setTag(holder);
String name = usersSearch.get(position).getName();
holder.userTxt.setText(name);
return v;
}
static class ViewHolder {
TextView userTxt;
}
}
you can override getItem() method in your adapater and return the object of DataBaseUser of particular position from the searchlist.. like
#Override public DatabaseUser getItem(int position) {
return usersSearch.get(position);
}
So from your onClick method you can call this method and it will give you DatabaseUser object from which you can retrive your text. I hope it helps you ..

ListView - Load more items with scroll

I need help with listview I am using in a fragment. The app reads data from an API and my code works fine. I load 15 items initially and every next time I load 10 items more. However if a request to the API return less than 15 items, it doesn't work. Also, the app fails when the number of items is not a multiple of 15 or 25 or 35. That is because I load 10 items after the initial setup.
I need to modify my code for it to work with any number of list items.
My code is as follows:
(ListaFragment.java) -> Here is the ListFragment
public class ListaFragment extends ListFragment implements OnScrollListener {
public ListaFragment(){}
View rootView;
ListAdapter customAdapter = null;
ListaLugares listaLugares;
// values to pagination
private View mFooterView;
private final int AUTOLOAD_THRESHOLD = 4;
private int MAXIMUM_ITEMS;
private Handler mHandler;
private boolean mIsLoading = false;
private boolean mMoreDataAvailable = true;
private boolean mWasLoading = false;
public int ventana = 0;
public int nInitial;
private Runnable mAddItemsRunnable = new Runnable() {
#Override
public void run() {
customAdapter.addMoreItems(10);
mIsLoading = false;
}
};
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_lista, container, false);
if (container != null) {
container.removeAllViews();
}
((MainActivity) getActivity()).setBar();
// read number of places of a category
listaLugares.readNumberOfPlaces();
// set
setNumbersOfItems();
// read the places a insert in a List
listaLugares.readPlaces(15, ventana, listaLugares.idCategoria);
//ventana = ventana + 25;
return rootView;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listaLugares = ((ListaLugares)getActivity().getApplicationContext());
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Context context = getActivity();
mHandler = new Handler();
customAdapter = new ListAdapter(context, listaLugares.lista);
mFooterView = LayoutInflater.from(context).inflate(R.layout.loading_view, null);
getListView().addFooterView(mFooterView, null, false);
setListAdapter(customAdapter);
getListView().setOnScrollListener(this);
}
public void setNumbersOfItems() {
if (listaLugares.totalItems > 100) {
MAXIMUM_ITEMS = 100;
nInitial = 25;
} else {
MAXIMUM_ITEMS = listaLugares.totalItems;
nInitial = listaLugares.totalItems;
}
Log.v("NUMBER OF ITEMS", "Number: " + MAXIMUM_ITEMS + "-"+ nInitial);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//Intent myIntent = new Intent(getActivity(), DetalleActivity.class);
//myIntent.putExtra("param_id", appState.lista.get(position).id);
//getActivity().startActivity(myIntent);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (!mIsLoading && mMoreDataAvailable) {
if (totalItemCount >= MAXIMUM_ITEMS) {
mMoreDataAvailable = false;
getListView().removeFooterView(mFooterView);
} else if (totalItemCount - AUTOLOAD_THRESHOLD <= firstVisibleItem + visibleItemCount) {
ventana = ventana + 10;
listaLugares.readPlaces(10, ventana, listaLugares.idCategoria);
mIsLoading = true;
mHandler.postDelayed(mAddItemsRunnable, 1000);
}
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Ignore
}
#Override
public void onStart() {
super.onStart();
if (mWasLoading) {
mWasLoading = false;
mIsLoading = true;
mHandler.postDelayed(mAddItemsRunnable, 1000);
}
}
#Override
public void onStop() {
super.onStop();
mHandler.removeCallbacks(mAddItemsRunnable);
mWasLoading = mIsLoading;
mIsLoading = false;
ventana = ventana;
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
(ListAdapter.java) -> Method in adapter class to add more items.
public class ListAdapter extends ArrayAdapter<Lugar> {
Context context;
List<Lugar> values;
ListaLugares listaLugares;
private int mCount = 20;
public ListAdapter(Context context, List<Lugar> values) {
super(context, R.layout.row, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.row, parent, false);
TextView firstText = (TextView) row.findViewById(R.id.titulo);
TextView secondText = (TextView) row.findViewById(R.id.categoria);
firstText.setText(values.get(position).nombre);
secondText.setText(values.get(position).categoriaNombre);
return row;
}
public void addMoreItems(int count) {
mCount += count;
notifyDataSetChanged();
}
#Override
public int getCount() {
return mCount;
}
#Override
public long getItemId(int position) {
return position;
}
}
I acceded to a previous edited version to see some code.
The first call works because you are starting with a value of 15 on initiaItems and you set it on mCount on the ListAdapter constructor.
public ListAdapter(Context context, List<Lugar> values, int count) {
super(context, R.layout.row, values);
this.context = context;
this.values = values;
this.mCount = count;
}
So when android renders the listview, it acces to the function ListAdapter.getCount() and returns mCount (15).
But when you scroll it can call to
public void addMoreItems(int count, int idCategoria) {
appState = ((ListaLugares)getContext().getApplicationContext());
appState.readPlaces(15, mCount, idCategoria);
mCount += count;
notifyDataSetChanged();
}
If the number of items returned by the appState.readPlaces is unknown why are you adding a number to mCount mCount += count;?
If appState.readPlaces returns 14 and count is 15 when the listview is rendered it will suppose there are 15+15 items when there are 15+14 so the last item will crash.
mCount should obtain the length from the object that keeps the data from the API calls, in your case I think it will be appState.lista.

Categories

Resources