In Custom ListView ,ArrayAdapter giving wrong position while scrolling - java

I have fetching 13 item from database and try to set it to the custom listview using ArrayAdepter, but problem is that whenever I scroll to bottom, position order is 0,1,2,3,4,5,6,7,8,9,10,11,12, but if I scroll from bottom to top its giving wrong position like 6,5,4,3,2,1,0,12,11,...
always getting wrong position from bottom scroll.
I have already read and implemented all the solution on stackoverflow, but not solve it.
Here is my arrayadepter code
public class ListAdapter_home extends ArrayAdapter {
List list = new ArrayList();
Context contect;
SharedPreferences savep;
SharedPreferences.Editor editor;
public ListAdapter_home(Context context, int resource) {
super(context, resource);
contect = context;
}
static class DataHandler {
CustomTextView name;
}
#Override
public void add(Object object) {
super.add(object);
list.add(object);
}
#Override
public void remove(Object object) {
super.remove(object);
list.remove(object);
}
#Override
public int getCount() {
return this.list.size();
}
#Override
public Object getItem(int position) {
return this.list.get(position);
}
#Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
View row;
row = convertView;
savep = getContext().getSharedPreferences("MySave", getContext().MODE_PRIVATE);
editor = savep.edit();
final DataHandler handler;
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.home_card, parent, false);
handler = new DataHandler();
handler.name = (CustomTextView) row.findViewById(R.id.catname);
row.setTag(handler);
} else {
handler = (DataHandler) row.getTag();
}
Log.d("position",""+position);
final HomeList dataProvider;
dataProvider = (HomeList) this.getItem(position);
handler.name.setText(dataProvider.getName());
return row;
}}

Related

Interact with view of a specific item in a custom ListView

I am using a custom BaseAdapter to create a custom list. What I'm trying to do is have a public function outside of getView(), in this example setName(), that can interact with a view of a specific item on the list.
For example calling setName(1); should make invisible the TextView of the second item on the list.
Thank you in advance.
public class ListAdapterNew extends BaseAdapter {
private int size;
private Context context;
private ViewHolder viewHolder;
String[][] data;
ArrayList<DataModel> listArray;
public ListAdapterNew(Context context, String[][] data, int size) {
listArray = new ArrayList<DataModel>(size);
for(int i=0;i<size;i++){
listArray.add(new DataModel(i));
}
this.context=context;
this.data=data;
this.size=size;
}
#Override
public int getCount() {
return listArray.size();
}
#Override
public Object getItem(int i) {
return listArray.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
public int getViewTypeCount() { return getCount(); }
#Override
public int getItemViewType(int position) {
return position;
}
private static class ViewHolder
{
TextView number,name;
}
#Override
public View getView(int index, View view, final ViewGroup parent) {
if (view == null) {
LayoutInflater li = (LayoutInflater) parent.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.main_user_list_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.number = view.findViewById(R.id.main_list_number);
viewHolder.name = view.findViewById(R.id.main_list_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
viewHolder.number.setText((index+1)+")");
viewHolder.name.setText(data[index][0]);
}
view.setClickable(true);
view.setFocusable(true);
return view;
}
public void setName(int index){
viewHolder.name.setVisibility(View.GONE);
}
}
The answer was simple. I use a public function inside the ListAdapterNew to update the data[][] and call notifyDataSetChanged(); on the adapter.
There is also a small change in the getView() of the adapter that allows the view to update when items become visible, as shown below.
if (view == null) {
LayoutInflater li = (LayoutInflater) parent.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.main_user_list_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.number = view.findViewById(R.id.main_list_number);
viewHolder.name = view.findViewById(R.id.main_list_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
if (view != null){
viewHolder.number.setText((index+1)+")");
viewHolder.name.setText(data[index][0]);
}
Function that updates the data
public void updateIcons(int index, int data){
this.icons[index]=data;
}

No Action while SmoothScrollToPosition in Custom List View

Hi I m using below code where when user touches the textview , list will be updated and touched list row will be in front of user.
public class AppAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
private List<AppList> listStorage;
private Context context;
SharedPreferences.Editor editor;
SharedPreferences sharedPreferences;
int pos = 0;
public AppAdapter(Context context, List<AppList> customizedListView) {
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
listStorage = customizedListView;
this.context = context;
}
#Override
public int getCount() {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
pos = sharedPreferences.getInt("pos", 0);
Log.e("POS",pos+"At Get cpiunt");
return listStorage.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
ViewHolder listViewHolder;
if (convertView == null) {
listViewHolder = new ViewHolder();
convertView = layoutInflater.inflate(R.layout.installed_app_list, parent, false);
listViewHolder.textInListView = (TextView) convertView.findViewById(R.id.list_app_name);
listViewHolder.imageInListView = (ImageView) convertView.findViewById(R.id.app_icon);
convertView.setTag(listViewHolder);
} else {
listViewHolder = (ViewHolder) convertView.getTag();
}
listViewHolder.textInListView.setText(listStorage.get(position).getName());
listViewHolder.imageInListView.setImageDrawable(listStorage.get(position).getIcon());
listViewHolder.textInListView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editor.putInt("pos", position).apply();
Log.e("Pressed", position + "");
MainActivity.installedAppAdapter.notifyDataSetChanged();
Log.e("Saved", sharedPreferences.getInt("pos", 0) + "value");
}
});
if (pos != 0) {
MainActivity.userInstalledApps.setSelection(pos);
editor.putInt("pos",0).apply();
}
return convertView;
}
static class ViewHolder {
TextView textInListView;
ImageView imageInListView;
}
}
I read many questions but did not get clear picture about how to use SmoothScrolltopostion. Though I as per info got, I captured click position and retrieved during list load to set saved position of list to user.
If I use smoothscrolltoposition, there is no action, but if I use setselection as shown in above code, I could able to see the clicked item in top of view after reloading.
Why smoothscroll is not working and m I doing correct coding for required action. pls guide.

How to add value to a list dynamically in android?

I have a list in which i can assigned the values statically.
private List<ListData> mDataList = Arrays.asList(
new ListData("Arun"),
new ListData("Jega"),
new ListData("Kabilan"),
new ListData("Karthick"),
new ListData("Joushva"),
new ListData("Niranjana"),
new ListData("Paramesh"),
new ListData("Prabha"),new ListData("Test1"),new ListData("Test2") );
The problem is now i got a scenario where i should get these value dynamically from web apim and i have to set it to the List variable mDataList.
Please help me to clear this. Thanks in advance.
Here is my complete code.
public class ReportFragment extends Fragment {
View ParentView;
private static final int HIGHLIGHT_COLOR = 0x999be6ff;
// list of data items
private List<ListData> mDataList = Arrays.asList(
new ListData("Arun"),
new ListData("Jega"),
new ListData("Kabilan"),
new ListData("Karthick"),
new ListData("Joushva"),
new ListData("Niranjana"),
new ListData("Paramesh"),
new ListData("Prabha"),new ListData("Test1"),new ListData("Test2")
);
// declare the color generator and drawable builder
private ColorGenerator mColorGenerator = ColorGenerator.MATERIAL;
private TextDrawable.IBuilder mDrawableBuilder;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ParentView= inflater.inflate(R.layout.report_fragment, container, false);
init();
return ParentView;
}
public void init(){
mDrawableBuilder = TextDrawable.builder()
.round();
// init the list view and its adapter
final ListView listView = (ListView) ParentView.findViewById(R.id.listView1);
listView.setAdapter(new SampleAdapter());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
}
private class SampleAdapter extends BaseAdapter {
#Override
public int getCount() {
return mDataList.size();
}
#Override
public ListData getItem(int position) {
return mDataList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(getActivity() , R.layout.list_item_layout, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ListData item = getItem(position);
// provide support for selected state
updateCheckedState(holder, item);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// when the image is clicked, update the selected state
ListData data = getItem(position);
data.setChecked(!data.isChecked);
updateCheckedState(holder, data);
}
});
holder.textView.setText(item.data);
return convertView;
}
private void updateCheckedState(ViewHolder holder, ListData item) {
if (item.isChecked) {
holder.imageView.setImageDrawable(mDrawableBuilder.build(" ", 0xff616161));
holder.view.setBackgroundColor(HIGHLIGHT_COLOR);
holder.checkIcon.setVisibility(View.VISIBLE);
}
else {
TextDrawable drawable = mDrawableBuilder.build(String.valueOf(item.data.charAt(0)), mColorGenerator.getColor(item.data));
holder.imageView.setImageDrawable(drawable);
holder.view.setBackgroundColor(Color.TRANSPARENT);
holder.checkIcon.setVisibility(View.GONE);
}
}
}
private static class ViewHolder {
private View view;
private ImageView imageView;
private TextView textView;
private ImageView checkIcon;
private ViewHolder(View view) {
this.view = view;
imageView = (ImageView) view.findViewById(R.id.imageView);
textView = (TextView) view.findViewById(R.id.textView);
checkIcon = (ImageView) view.findViewById(R.id.check_icon);
}
}
private static class ListData {
private String data;
private boolean isChecked;
public ListData(String data) {
this.data = data;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
}
}
}
create a method to add items in your adapter class, this method will add item to
itemlist. this will add items dynamically on your list or grid.
e.g
public void addItem(Item item){
itemList.add(item);
notifydatasetchanged();}
create a adapter class and constructor, in constructor just initialize the item arraylist and create extra method called addItem() this method will add item to your arraylist. after that you just have to call notifyDatasetchanged and your new item will be added.

Custom multiselected listview Android

I have been trying create a multiselected ListView like it looks on picture in this link:
picture
When user unchecked the checkbox in the top-left corner listviewItem layout must be changed to unchecked state.
Now I use it:
public class ProcedureAdapter : BaseAdapter<Procedure>
{
List<Procedure> items;
Activity context;
Dictionary<int, bool> CheckedItems = new Dictionary<int, bool>();
public ProcedureAdapter(Activity context, List<Procedure> items)
: base()
{
this.context = context;
this.items = items;
for (int i = 0; i < items.Count; i++)
{
CheckedItems.Add(i, false);
}
}
public override long GetItemId(int position)
{
return position;
}
public override Procedure this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public void toggleCheck(int position)
{
if (CheckedItems.ContainsKey(position))
{
CheckedItems[position] = !CheckedItems[position];
base.NotifyDataSetChanged();
}
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
View view = convertView;
if (view == null)
view = context.LayoutInflater.Inflate(Resource.Layout.ProcedureListViewItem, null);
if (!CheckedItems.ContainsKey(position))
CheckedItems.Add(position, false);
if (CheckedItems[position])
{
checkBox.Visibility = ViewStates.Visible;
checkBox.Checked = true;
ProcedureTypeImage.Visibility = ViewStates.Gone;
}
else
{
checkBox.Visibility = ViewStates.Gone;
checkBox.Checked = false;
ProcedureTypeImage.Visibility = ViewStates.Visible;
}
return view;
}
}
In the activity:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = inflater.Inflate(Resource.Layout.ProceduresLayout, container, false);
listView = view.FindViewById<ListView>(Resource.Id.listView1);
listView.ItemLongClick += listView_ItemLongClick;
procAdapter = new ProcedureAdapter(Activity, procedures);
listView.Adapter = procAdapter;
return view;
}
void listView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
{
procAdapter.toggleCheck(e.Position);
}
but i faced with problem:
how can I change layout when user unchecked the checkbox?
I have tried processing CheckedChange event in the Adapter, but how I will know position of this ListViewItem?
My solution seems to me not very good, please give me advice how can I do it better.
I was wondering if you show to me a simple example on C# or Java.
Thanks
I made a simple example that might help you. It's a list and each list item has a TextView and CheckBox. Text view is showing position in green or red color depending on if check box checked or not. It is simplified version of your problem. Don't know if it's best solution but it will work.
Only thing to note. Since views are being reused when you bind check box it can trigger CheckedChange event. That is why Tag is first changed when doing the binding.
using System.Globalization;
using Android.App;
using Android.Graphics;
using Android.Views;
using Android.Widget;
using Object = Java.Lang.Object;
namespace AndroidApplication1
{
public class LvAdapter : BaseAdapter
{
private readonly Activity _context;
public bool[] Bools = new bool[15];
public LvAdapter(Activity context)
{
_context = context;
}
public override Object GetItem(int position)
{
return null;
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
ViewHolder vh;
var view = convertView;
if (view == null)
{
view = _context.LayoutInflater.Inflate(Resource.Layout.list_item, parent, false);
vh = new ViewHolder();
vh.Initialize(view, this);
view.Tag = vh;
}
vh = view.Tag as ViewHolder;
if (vh != null) vh.Bind(position, Bools);
return view;
}
public override int Count
{
get { return Bools.Length; }
}
private class ViewHolder : Object
{
private TextView _text;
private CheckBox _check;
public void Initialize(View view, LvAdapter adapter)
{
_text = view.FindViewById<TextView>(Resource.Id.tvText);
_check = view.FindViewById<CheckBox>(Resource.Id.cbCheck);
_check.CheckedChange += (sender, args) =>
{
var tagHoldr = (((View) sender).Tag) as TagHolder;
adapter.Bools[tagHoldr.Positon] = args.IsChecked;
tagHoldr.TextView.SetTextColor(args.IsChecked ? Color.Green : Color.Red);
};
}
public void Bind(int position, bool[] bools)
{
_check.Tag = new TagHolder { Positon = position, TextView = _text };
_text.Text = position.ToString(CultureInfo.InvariantCulture);
_check.Checked = bools[position];
_text.SetTextColor(bools[position] ? Color.Green : Color.Red);
}
}
private class TagHolder : Object
{
public int Positon { get; set; }
public TextView TextView { get; set; }
}
}
}

update listview from an Array adapter

I'm trying to refresh the list view when I click on a single item of the list view.
For example I'm trying to do something like this:
public class RssItemsAdapter extends ArrayAdapter<Item> {
private TextView txtTitle;
private ImageView imgFavourite;
private int resourceId;
private Context context;
private List<Item> items = new ArrayList<Item>();
public RssItemsAdapter(Context context, int resourceId, List<Item> items)
{
super(context, resourceId, items);
this.context = context;
this.items = items;
this.resourceId = resourceId;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Item getItem(int index) {
return items.get(index);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
Item item = getItem(position);
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(resourceId, parent, false);
}
txtTitle = (TextView) row.findViewById(R.id.title);
txtTitle.setText(item.getTitle());
imgFavourite = (ImageView) row.findViewById(R.id.favourite);
imgFavourite.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (item.isFavourite() == true) {
imgFavourite.setBackgroundResource(android.R.drawable.btn_star_big_off);
}
else {
imgFavourite.setBackgroundResource(android.R.drawable.btn_star_big_on);
}
}
});
// add a "star" icon on favourite items
if (item.isFavourite() == true)
imgFavourite.setBackgroundResource(android.R.drawable.btn_star_big_on);
else
imgFavourite.setBackgroundResource(android.R.drawable.btn_star_big_off);
return row;
}
Every time I click on the imgFavourite icon it should change. Where is the problem?
It doesn't look like you are ever changing the value of item.isFavourite(). Assuming you want to toggle when that item is clicked...
imgFavourite.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Toggle the current state
item.setIsFavourite(!item.isFavourite());
if (item.isFavourite() == true) {
imgFavourite.setBackgroundResource(android.R.drawable.btn_star_big_off);
}
else {
imgFavourite.setBackgroundResource(android.R.drawable.btn_star_big_on);
}
}
});
Also, you should be doing this kind of work in the ListView's onItemClickListsner. As is, this will create a new onClickListener each time a new row is brought into view. Beyond that, check into the "view holder pattern".

Categories