I've got next adapter:
public class CityAdapter extends ArrayAdapter<String> {
public CityAdapter(Context context, int resource) {
super(context, resource, Cities.TITLES);
}
public int getCount() {
return Cities.ARRAY.length;
}
#SuppressLint("InflateParams")
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.city_list_row, null);
}
TextView title = (TextView) v.findViewById(R.id.cityTitle);
title.setText(Cities.ARRAY[position].getName());
if (position==4) {
title.setTextColor(Color.parseColor("#ff0000"));
}
return v;
}
}
Please take a closer look at this line:
if (position==4)
I don't know how, but that statement works for position 0 too.
Seems really impossible. What is wrong? Also if I change my code like this:
if (position==4) {
title.setText("hey!!!");
title.setTextColor(Color.parseColor("#ff0000"));
}
I will get this:
Add an else case for your color settings like this
if (position==4) {
title.setTextColor(Color.parseColor("#ff0000"));
}
else {
title.setTextColor(Color.parseColor("#ffffff"));
}
You are not implementing the else part.
ViewHolder holder;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.city_list_row, null);
holder.title = (TextView) v.findViewById(R.id.cityTitle);
v.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
And then you need to create a class
class ViewHolder {
TextView title;
}
Also you need else part of this.
if (position==4) {
title.setText("hey!!!");
title.setTextColor(Color.parseColor("#ff0000"));
}else{
title.setText("heyfffgg!!!");
title.setTextColor(Color.parseColor("#ff0000"));
}
Related
I have created a ListView of items that each one of them looks as follows:
In simplified code, It looks like this:
public class MyBAdapter extends ArrayAdapter {
private static class ViewHolder {
public ImageButton ib_Delete;
public ToggleButton tb_Status;
}
public MyBAdapter(Context context, ArrayList<MyB> aB) {
super(context, 0, aB);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final MyB b = getItem(position);
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate( R.layout.item_b_myb, parent, false);
viewHolder.ib_DeleteB = convertView.findViewById( R.id.ib_DeleteB );
viewHolder.tb_Status = convertView.findViewById( R.id.tb_Status );
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
Now, I had like that once a user clicks on the ToggleButton of on the x button, that it will remove this item from the list and that the view will be updated on this screen.
How can I do it?
I saw that for this case notifyDataSetChanged() won't work.
Basically what I'm trying to do is to refresh the list without calling again the activity.
Thank you
You can try like this:
public static class MyBAdapter extends ArrayAdapter {
private ArrayList<String> aB;
private class ViewHolder {
public ImageButton ib_Delete;
public ToggleButton tb_Status;
public TextView text;
}
public MyBAdapter(Context context, ArrayList<String> aB) {
super(context,0, aB);
this.aB = aB;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate( R.layout.item_b_myb, parent, false);
viewHolder.ib_Delete = convertView.findViewById( R.id.ib_DeleteB );
viewHolder.tb_Status = convertView.findViewById( R.id.tb_Status );
viewHolder.text = convertView.findViewById( R.id.text );
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.tb_Status.setChecked(false);
}
viewHolder.text.setText(aB.get(position));
viewHolder.ib_Delete.setTag(position);
viewHolder.ib_Delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(viewHolder.tb_Status.isChecked()){
delete((Integer)view.getTag());
}
}
});
return convertView;
}
private void delete(int position) {
aB.remove(position);
notifyDataSetChanged();
}
#Override
public int getCount() {
return aB.size();
}
}
I'm coding a scrollable listview in android with textview and edittext in each row. Because there's the issue when you scroll, that the new data gets lost i update my ArrayList in an TextChangedListener like this:
TextWatcher txtwatch = 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 (s.length() > 0) {
if (!scrolling) {
InhalteArr.set(position, s.toString());
}
}
}
#Override
public void afterTextChanged(Editable s) {
}
};
My problem is now, that this method is working, but only for the seven first rows. The following rows are showing the right information, but they don't set the updated data at the right position in the ArrayList.
I can't understand why the first seven rows are doing what I want and the rest seems to begin setting the updated data upcounting from zero again and not going on with eight.
It's very creepy because all rows also the last rows seems to get the right data from ArrayList, but the last view rows are setting the data at wrong place in ArrayList.
In getView() Method I'm setting the data like this
viewHolder.Inhalt.setText(InhalteArr.get(position).toString());
but that works.
Has anyone any idea?
Thank you!
EDIT: Here's my adapter:
public class SyAdapter extends ArrayAdapter<ArrayList> {
Typeface bahn = Typeface.createFromAsset(getContext().getAssets(), "fonts/bahnschrift.ttf");
Typeface ih = Typeface.createFromAsset(getContext().getAssets(), "fonts/corbel.ttf");
private static class ViewHolder {
TextView Merkmal;
TextView Inhalt;
}
ArrayList MerkmaleArr;
ArrayList InhalteArr;
public SyAdapter (Context context, ArrayList Merkmale, ArrayList Inhalte) {
super(context, R.layout.listanzeige, R.id.MerkmalT, Merkmale);
this.MerkmaleArr = Merkmale;
this.InhalteArr = Inhalte;
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.listanzeige, parent, false);
viewHolder.Merkmal = (TextView) convertView.findViewById(R.id.MerkmalT);
viewHolder.Merkmal.setTypeface(bahn);
viewHolder.Inhalt = (TextView) convertView.findViewById(R.id.InhaltT);
viewHolder.Inhalt.setTypeface(ih);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
System.out.println("Aktuelle Position: " + position);
viewHolder.Inhalt.setText(InhalteArr.get(position).toString());
viewHolder.Merkmal.setText(MerkmaleArr.get(position).toString());
return convertView;
}}
EDIT2: Now i figured out that all rows with position >7 have at the beginning already convertView != null, what means, that they skip the if (convertView == null) code. But why?
Assuming size of InhalteArr and MerkmaleArr is same
Add this method to your adapter class
#Override
public int getCount() {
return InhalteArr.size();
}
Adapter Class refinement Example:
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
convertView = layoutInflater.inflate(R.layout.listanzeige, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.Inhalt.setText(InhalteArr.get(position).toString());
viewHolder.Merkmal.setText(MerkmaleArr.get(position).toString());
return convertView;
}
private class ViewHolder {
final EditText Inhalt;
final TextView Merkmal;
public ViewHolder(View v) {
Inhalt = v.findViewById(R.id.InhaltT);
Merkmal = v.findViewById(R.id.MerkmalT);
}
}
For those who have the same problem:
I solved my issue setting a tag out of the if(convertview == null), at first i was trying to set the tags into that ifmethod, but that won't work at all rows.
To get the edittext'stag into the onTextChangeListeneri found some good code here at stackoverflow:
View focView = activity.getCurrentFocus();
if (focView != null) {
EditText edit = (EditText) focView.findViewById(R.id.tvinhalt);
if (edit != null && edit.getText().toString().equals(s.toString())) {
int positionof = Integer.parseInt(edit.getTag().toString());
System.out.println("Tag= " + positionof);
YouArray.set(positionof, s.toString());
}
Hope with this answer you don't have to invest as much time as me to understand, that the tag must been set outside of that iffunction :D
I am trying to update the ListView when the Data is update in the Android.
I use mLeDeviceListAdapter.addRSSIandAddress("20"); to set the value to addRSSIandAddress function.
And in the addRSSIandAddress , it receive the value and call mLeDeviceListAdapter.notifyDataSetChanged();. But the NullPointerException happened at the viewHolder.deviceRssi.setText("RSSI:" + String.valueOf(mrssi));
It seems the viewHolder.deviceRssi is null or the viewHolder is null.
The code of ListView and the Adapter is like the following:
private LeDeviceListAdapter mLeDeviceListAdapter;
private static ListView device_list;
mLeDeviceListAdapter = new LeDeviceListAdapter(getActivity());
device_list.setAdapter(mLeDeviceListAdapter);
public class LeDeviceListAdapter extends BaseAdapter{
private LayoutInflater mInflator;
ArrayList<BluetoothDevice> mLeDevices;
private String mrssi;
public LeDeviceListAdapter(Context context) {
// TODO Auto-generated constructor stub
mInflator = LayoutInflater.from(context);
}
private void addRSSIandAddress(String rssi) {
// TODO Auto-generated method stub
mrssi = rssi;
mLeDeviceListAdapter.notifyDataSetChanged();
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder viewHolder;
Log.d(TAG, "getView");
if(view == null){
view = mInflator.inflate(R.layout.device_list, null);
viewHolder = new ViewHolder();
viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
}else {
viewHolder = (ViewHolder) view.getTag();
viewHolder.deviceRssi.setText("RSSI:" + String.valueOf(mrssi));
}
return view;
}
}
static class ViewHolder {
TextView deviceRssi;
}
How to solve this problem ? Thanks in advance.
As the others have said. I think you forgot to set
view.setTag(viewHolder).
Try Put this line here In your code
if(view == null)
{
view = mInflator.inflate(R.layout.device_list, null);
viewHolder = new ViewHolder();
viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
view.setTag(viewHolder); //THE CODE
}
else
{
viewHolder = (ViewHolder) view.getTag();
viewHolder.deviceRssi.setText("RSSI:" + String.valueOf(mrssi));
}
return view;
You use:
viewHolder = (ViewHolder) view.getTag();
But do you setTag somewhere? I don't think so.
Hope it helps
Try with below code:
if(view == null){
view = mInflator.inflate(R.layout.device_list, null);
viewHolder = new ViewHolder();
viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
view.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.deviceRssi.setText("RSSI:" + String.valueOf(mrssi));
I know questions like this one was already asked but I went through all the solutions I saw and non has worked.
This is my adapter
class Adapter extends BaseAdapter {
Activity context;
public Adapter(Activity context) {
this.context = context;
}
#Override
public int getCount() {
return Constants.CHARACTERS_NAMES.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = context.getLayoutInflater().inflate(R.layout.list_charecter_item, null);
holder = new ViewHolder();
holder.PlayerName = (TextView) convertView.findViewById(R.id.name);
holder.PlayerName.setText(Constants.CHARACTERS_NAMES[position]);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
private class ViewHolder {
TextView PlayerName;
}
}
This is a standard adapter but when I debug it with my listview Instead of getting All my 7 items which are in Constants.CHARACTERS_NAMES I get the 4 first items right, but the I get the first item twice and then the second item.
Please help.
I have made an Listview populated with list_row_layout.xml(which is populated with json serializable class), i have clickable textview and onclick changing text from "Accept" to "Accepted". But when i click it on first listview item, another textview listview items below are changing. Here's some photos to descibe you better
Activity class
feedListView.setAdapter(new CustomListAdapter(this, feedList));
adapter class
public class CustomListAdapter extends BaseAdapter
{
private ArrayList<FeedItem> listData;
private LayoutInflater layoutInflater;
private Context mContext;
public CustomListAdapter(Context context, ArrayList<FeedItem> listData)
{
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
mContext = context;
}
#Override
public int getCount()
{
return listData.size();
}
#Override
public Object getItem(int position)
{
return listData.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if (convertView == null)
{
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.title);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
holder.approve.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View argView)
{
holder.approve.setText("accepted");
}
}
);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = listData.get(position);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.approve.setTag(newsItem);
return convertView;
}
static class ViewHolder
{
TextView approve;
TextView headlineView;
TextView reportedDateView;
ImageView imageView;
}
}
textview code
<TextView
android:id="#id/approveTV"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:background="#drawable/pressed"
android:gravity="fill"
android:text="Accept"
android:clickable="true"
android:textColor="#0D98BA"
android:textSize="17sp" />
You have to write some tracking position functionality which remember the position which you have changed and make sure that only text of position changed .
you must set id to each row, and save it in one array,like integer and when you click on one row you must change the value of that, and in changing text or anything you must check the value of that row,if 0 then set default and if 1 then so what you want: my idea is create int[] with length of that is size of your list,
first you must define you int[] like below and set to zero every index.
int[] selected = new int[listData.getsize()]
something like this in getview:
holder.approve.setId(Html.fromHtml(newsItem.getId());
and after else statement in getView:
if (selected[position] == 0)
{
// set default
}
else
{
// any changing that you want
}
and in onClick:
selected[holder.approve.getId()] = 1;
// any change that you want
Try the below code:-
public View getView(final int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder.headlineView = (TextView)convertView.findViewById(R.id.title);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = listData.get(position);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.approve.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View argView)
{
holder.approve.setText("accepted");
}
}
);
return convertView;
}
Thanks!!