So I populate a ListView from the local database using Custom Adapter. What I want to do now is when I click a button the lists in the listview will change its order like what shown in the image. Can someone help me. Here's my code.
This is the current ListView --> SEE IMAGE
This is what I want to do --> SEE IMAGE
CustomAdapter.java
public CustomAdaper(Context context,ArrayList<SampleObj> items) {
super(context,0, items);
this.context = context;
this.items = items;
vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final ViewHolder holder;
final SampleObj i = items.get(position);
if (i != null) {
final SampleObj ei = (SampleObj)i;
if (v == null) {
v = vi.inflate(R.layout.log_row, null);
holder = new ViewHolder();
holder.date = (TextView)v.findViewById(R.id.date);
holder.time = (TextView)v.findViewById(R.id.time);
holder.buttonID = (TextView)v.findViewById(R.id.buttonID);
v.setTag(holder);
}
else {
holder = (ViewHolder)v.getTag();
}
holder.date.setText(ei.date);
holder.time.setText(ei.time);
holder.buttonID.setText(ei.buttonID);
}
return v;
}
private static class ViewHolder {
public TextView date;
public TextView time;
public TextView buttonID;
}
}
you need to use Expandale List
First see this
then this
then this
Related
I am having a problem in customlist view.
I have two buttons and one textView . Add and Subtract Buttons.
when click Add button the counter should be +1 and -1 respectively.
I have used a dummy string for checking whether it is actually updating the textView or not. But the problem is when I scroll down some of the items are having same value.
For example
1st item TextView is set to "HIII"
then if I scroll down the 11th ,21th ... is also set to "HIII"
Note: the max number that display can contain is 10 items so when I scroll down to 11th it is set to "HII".
public class CustomAdapter extends ArrayAdapter {
Context context;
LayoutInflater inflater;
int resource;
//ArrayList<Integer> count = new ArrayList<>();
public CustomAdapter(Context context, int resource) {
super(context, resource);
this.context = context;
this.resource = resource;
}
#Override
public int getCount() {
return 100;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder mainHolder = null;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
final ViewHolder holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
convertView.setTag(holder);
} else {
mainHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
class ViewHolder {
Button add, sub;
TextView textView;
}
Please Help me. I want to know how to set tag of one with other(I mean how you know you need to set the tag with the other object or view)
Thanks
ListView recycles Views. It creates Views that will be re-used when scrolling down.
Thus, you have to call setText() and setOnClickListener() every time getView() is called, not only when button is clicked.
To achieve what you want, you have to store set text data in a model, like a SparseArray which maps positions to data.
public class CustomAdapter extends ArrayAdapter {
Context context;
LayoutInflater inflater;
int resource;
//ArrayList<Integer> count = new ArrayList<>();
// Your data map by position
SparseArray<String> data = new SparseArray<>();
public CustomAdapter(Context context, int resource) {
super(context, resource);
this.context = context;
this.resource = resource;
}
#Override
public int getCount() {
return 100;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(data.get(position));
holder.add.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
final String text = "HIII";
data.put(position, text);
holder.textView.setText(text);
notifyDataSetChanged();
}
});
return convertView;
}
}
class ViewHolder {
Button add, sub;
TextView textView;
}
write your onclick listener after else condition.
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
Take a look at your getView function:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder mainHolder = null;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
final ViewHolder holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
convertView.setTag(holder);
} else {
mainHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
You edit the content of your holder textView and add Button only when you create a new Viewholder.
The first time your listview shows its items, there will be always a new view created (and a new Viewholder, too) for all visible cells.
As soon as you scroll down, the adapter will take a now-invisble cell (maybe the frist cell) and recycle it to show a now-visible cell. In this case, your convertView in getView won't be null anymore, as the view was recycled.
So you should handle all your text changes an Listener and so on outside of your if statement to manage both cases (recycled and new).
For example:
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
final ViewHolder holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
convertView.setTag(holder);
} else {
mainHolder = (ViewHolder) convertView.getTag();
}
holder.textView.setText("");
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
Edit
To save your data in a sparse array like Yaroslav Mytkalyk suggested would be a better approach.
Anyway, you have to handle recycled views.
I have made a customize list in which i have to give different colors to different list items.I tried doing it but the text color is always black.I don't know why this is happening;
Code-
private Context context;
private List<CommonModel> commonList = Collections.emptyList();
private LayoutInflater inflater;
private String from;
private int[] languageColours = {R.color.green, R.color.pink, R.color.grey, R.color.chetna_red};
public CommonAdapter(Context context, List<CommonModel> commonList, String from) {
this.context = context;
this.commonList = commonList;
this.from = from;
inflater = inflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.common_custom_list_item, parent, false);
holder.tvContent = (TextView) convertView.findViewById(R.id.tv_common_content);
holder.ivImage = (ImageView) convertView.findViewById(R.id.iv_common_image);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.ivImage.setImageResource(commonList.get(position).getImage());
holder.tvContent.setText(commonList.get(position).getContent());
holder.tvContent.setTextColor(languageColours[position]);
return convertView;
}
private class ViewHolder {
TextView tvContent;
ImageView ivImage;
}
I had checked that the position which i am getting is correct then to the color is not changing.
instead of using languageColours[position] use context.getResource.getColor(languageColours[position]);
Simply use this
holder.tvContent.setTextColor(R.color.Red);
It might be silly question, but I am having bit hard time to make it work.
I have a custom list view adapter which some textview and imageview.
But when I am updating listview using custom adapter it is only updating last value. here is my code
Adapter code
public class InfoListAdapter extends ArrayAdapter<aSProperty> {
Context mContext;
List<aSProperty> values= null;
public InfoListAdapter(Context mContext, List<aSProperty> data) {
super(mContext, R.layout.list_row, data);
this.mContext = mContext;
this.values = data.;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this.mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.list_row, null);
signal = (ImageView) convertView.findViewById(R.id.images);
type = (TextView) convertView.findViewById(R.id.type);
info = (TextView) convertView.findViewById(R.id.info);
image.setBackgroundResource(R.drawable.abc);
Log.d(TAG, "List Size"+values.size());
for(int i = 0; i < values.size(); i++){
Log.d(TAG, "DATA"+values.get(i).type);
type.setText(values.get(i).type);
}
}
ImageView image;
TextView type;
TextView info;
static String TAG= "InfoListAdapter";
return convertView;
}
}
Code to populate adapter
info_panel = new InfoListAdapter(esActivity.this, allData);
list.setAdapter(info_panel);
But I do not know why, it is only showing last values from values list. In addition I want to change image based on condition and data inside values, any good way to do this.
use following code
public class InfoListAdapter extends ArrayAdapter<aSProperty> {
Context mContext;
List<aSProperty> values= null;
public InfoListAdapter(Context mContext, List<aSProperty> data) {
super(mContext, R.layout.list_row, data);
this.mContext = mContext;
this.values = data.;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this.mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.list_row, null);
signal = (ImageView) convertView.findViewById(R.id.images);
type = (TextView) convertView.findViewById(R.id.type);
info = (TextView) convertView.findViewById(R.id.info);
image.setBackgroundResource(R.drawable.abc);
Log.d(TAG, "List Size"+values.size());
type.setText(values.get(position).type);
}
ImageView image;
TextView type;
TextView info;
static String TAG= "InfoListAdapter";
return convertView;
}
}
First of all, you have to override getCount() method of your adapter like this
#Override
public int getCount() {
return values .size();
}
and then in your getView() method you have to do something like this
#Override
public View getView(int arg0, View convertView, ViewGroup arg2) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = layoutInflater.inflate(R.layout.mycartslistcontents,
null);
holder.yourImageView= (ImageView) convertView
.findViewById(R.id.image);
holder.yourTextView= (TextView) convertView
.findViewById(R.id.textview);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// here set your textView text and image resource
return convertView;
}
Don't forget to take a global variable layoutInflater at the top like this
private LayoutInflater layoutInflater;
and initialise it in your constructor this way
layoutInflater = LayoutInflater.from(yourContext);
and here is your ViewHolder class
static class ViewHolder {
ImageView yourImageView;
TextView yourTextView;
}
I have a list view in my screen, every list item contains 2 text views and one button.
On button click i want to take the list item selected index to get some data from a vector.
This is my List Custom Adapter.But i don't know how to do that.
private class CustomAdapter extends ArrayAdapter<ServicesItems> {
public CustomAdapter(Context context, int resource,
int textViewResourceId, List<ServicesItems> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
TextView item = null;
TextView description = null;
Button subNowBtn;
ServicesItems ii = getItem(position);
if (null == convertView) {
convertView = mInflater.inflate(
R.layout.list_of_servics_item_2, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
// cat_name = holder.gettitle();
Resources resources = getResources();
ServicesItems bean1 = (ServicesItems) servicesVector
.elementAt(position);
String cat_name_str = bean1.getService_name().toString();
String descreption = bean1.getDescription().toString();
item = holder.getItem();
item.setText(bean1.getDescription());
description = holder.getDescription();
description.setText(bean1.getService_name());
subNowBtn=holder.getSubButton();
return convertView;
}
private class ViewHolder {
private View mRow;
private TextView description = null;
private TextView item = null;
private Button sub = null;
public ViewHolder(View row) {
mRow = row;
}
public TextView getDescription() {
if (null == description) {
description = (TextView) mRow
.findViewById(R.id.category_tv);
}
return description;
}
public TextView getItem() {
if (null == item) {
item = (TextView)
mRow.findViewById(R.id.descreption_tv);
}
return item;
}
public Button getSubButton(){
if(null==sub){
sub=(Button)findViewById(R.id.subscribe_now_btn);
}
return sub;
}
}
}
In your Adapter try this:
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = convertView;
YourWrapper wrapper = null;
if (row == null)
{
row = inflater.inflate(R.layout.layout, parent, false);
wrapper = new YourWrapper (row);
row.setTag(wrapper);
}
else
wrapper = (YourWrapper) row.getTag();
wrapper.getButton().setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// What you want
}
});
return row;
}
EDIT
Your wrapper class:
public class YourWrapper
{
private View base;
private Button button;
public YourWrapper(View base)
{
this.base = base;
}
public Button getButton()
{
if (button == null)
{
button = (Button) base.findViewById(R.id.your_button);
}
return (button`);
}
}
Change sub=(Button)findViewById(R.id.subscribe_now_btn); into sub=(Button) mRow.findViewById(R.id.subscribe_now_btn);
You can get the index of list-view on button click, here are two examples:--
You can write these in your onClick method of listener.
Example 1
View parentRow = (View) v.getParent();
ListView listView = (ListView) parentRow.getParent();
final int position = listView.getPositionForView(parentRow);
Example 2
Set position using setTag when creating view
mybutton.setTag(position);
Get position in the listener
int position = (Integer) view.getTag();
Hope this help :)
I'm trying to update my custom ArrayAdapter, but after calling updateListArray getView is called and the convertview is not null but the tag is null, giving me errors. If I make an extra null check and set a new viewholder it simply shows the wrong content.
I simply can't figure out why this gives me problems, I have following in code:
public class CustomAdapter extends ArrayAdapter<Item> {
private ArrayList<Item> mListItems;
public CustomAdapter (Context context, int rowResourceId, ArrayList<Item> items) {
super(context, rowResourceId, items);
mListItems = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
// setup holder
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_row, null);
holder.mEventStart = (TextView) convertView.findViewById(R.id.row_date);
holder.mTitle = (TextView) convertView.findViewById(R.id.row_artist);
holder.mSubTitle = (TextView) convertView.findViewById(R.id.row_description);
holder.mImage = (ImageView) convertView.findViewById(R.id.row_artist_image);
holder.mScene = (ImageView) convertView.findViewById(R.id.row_scene_image);
holder.mStatus = (ImageView) convertView.findViewById(R.id.row_new);
holder.mRowParent = (View) convertView.findViewById(R.id.row_parent);
} else {
// get existing row view
holder = (ViewHolder) convertView.getTag();
}
//setup row view content
if(!mListItems.isEmpty()) {
//set content
}
return convertView;
}
public void updateListArray(ArrayList<Item> list) {
this.clear();
for(Item item : list) {
this.add(item);
}
mListItems = list;
notifyDataSetChanged();
}
getTag() will be null unless you have used setTag(). It will probably work as you want if you remove the call to getTag()