I am attempting to make a list view row empty if it has no text. I have achieved this before, but I'm not sure how I did it. At the moment, I have managed to get it to not show anything when the text is equal to nothing, however it still shows the row border.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_2, android.R.id.text1, MainActivity.values) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text1 = (TextView) view.findViewById(android.R.id.text1);
TextView text2 = (TextView) view.findViewById(android.R.id.text2);
text1.setText(MainActivity.values[position]);
text2.setText(MainActivity.numvalues[position]);
if (MainActivity.values[position].equals("")) {
text1.setVisibility(View.INVISIBLE);
text1.setVisibility(View.GONE);
text2.setVisibility(View.INVISIBLE);
text2.setVisibility(View.GONE);
//convertView.setVisibility(View.INVISIBLE);
//convertView.setVisibility(View.GONE);
view.setVisibility(View.INVISIBLE);
view.setVisibility(View.GONE);
}
else {
text1.setVisibility(View.VISIBLE);
text2.setVisibility(View.VISIBLE);
//convertView.setVisibility(View.INVISIBLE);
//convertView.setVisibility(View.GONE);
view.setVisibility(View.VISIBLE);
}
return view;
}
};
Before init ArrayAdapter remove from MainActivity.values and MainActivity.numvalues items that don't need to show.
VIEW.GONE won't work as you want, i've tried it, but there is one thing you can do to avoid this problem at all, maybe you should remove all of your empty rows before you past your items into adapter?
Related
I'm using the Activity with Navigation Drawer project template within Android Studio, which generates the navigation menu like this:
mDrawerListView.setAdapter(new ArrayAdapter<String>(
getActionBar().getThemedContext(),
android.R.layout.simple_list_item_1,
android.R.id.text1,
new String[]{
getString(R.string.title_section1),
getString(R.string.title_section2),
getString(R.string.title_section3),
}));
I'm looking for an easy way to be able to iterate through those items and update the subtext on some of them with new information. So I attempted to change android.R.layout.simple_list_item_1 to android.R.layout.simple_list_item_2 within the setAdapter() call, and loop through them like this:
View v;
TextView tv;
for(int i = 0; i < mDrawerListView.getCount(); i++){
v = mDrawerListView.getAdapter().getView(i,null,null);
tv = (TextView) v.findViewById(android.R.id.text2);
tv.setText("Sub Item");
}
Which doesn't work, but it doesn't throw any errors. I've also tried just using getChildAt() rather than going through getAdapter(), which has resulted in a null reference error.
What's the best way to approach this particular issue?
I had the same issue, but the solution is pretty simple. You just need to override the getView method of the adapter:
public View getView(int position, View convertView, ViewGroup parent)
You can keep the normal behaviour of this method and add whatever you want to do, so for example in your case you'd want to add something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view= super.getView(position, convertView, parent);
TextView tv= (TextView) view.findViewById(android.R.id.text2);
tv.setText("sub text");
}
This should work.
I have a listview adapter
adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1, listItems){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = (TextView) super.getView(position, convertView, parent);
if(tv.getText().equals("TEXT1") || tv.getText().equals("TEXT2")) {
tv.setBackgroundColor(Color.parseColor("#FF0000"));
}
return tv;
}
};
I want ONLY the items with the text : TEXT1 and TEXT2 to have their backgrounds changed.
No more items. Only those. But as i scroll more and more more items have their backgrounds changed, items that do NOT have the text TEXT1 or TEXT2.
How can i achieve this?
Thank you.
this is due of the recycling mechanism of the ListView:
to fix it you can "reset" the background colour it the if guard is false
if(tv.getText().equals("TEXT1") || tv.getText().equals("TEXT2")) {
tv.setBackgroundColor(Color.parseColor("#FF0000"));
} else {
tv.setBackgroundColor(Color.parseColor(OTHERCOLOR));
}
I've an ListView with different count of entries every in runtime (normal -> depends at the user)
I read a post to change the color of the TextViews in the getView() of the Adapter.
It worked well, if I wouldn't scroll -> then there are more colored entries...!
And I want only ONE.
I'm trying to change only one specific row, and not the others. The others have the 'correct color'.
listview_otherSubnets.setAdapter(new ArrayAdapter<String>(this, R.layout.networks_list_item, list) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view=super.getView(position, convertView, parent);
TextView textView=(TextView) view.findViewById(R.id.networkslistitem);
//index_network specifies the specific network row
/*YOUR CHOICE OF COLOR*/
if(index_network==-1) {//get the error entry
//always one entry and if calculation above is not correct then there would be an error text in the TextView
textView.setTextColor(Color.parseColor("#ff4444"));
textView.setTypeface(null, Typeface.BOLD);
}
if(index_network!=-1 && index_network==position){//get the specific one
Log.i("OtherSubnet", "Adapter Current Network");
textView.setTextColor(Color.parseColor("#33b5e5"));
textView.setTypeface(null, Typeface.BOLD);
}
//otherwise default color (from the xml) -> see image
view.setClickable(false);
return view;
}
});
after scrolling (without error message)
correct would be: only one row
Is it possible to get the text of the TextView, if it's on the first run?The text which should be set?
As I tried, I got an exception.
The adapter class is designed that way, that while scrolling views will be reused, but not created again. Your colored textview, after scrolling is reused, so some other element will be colored. If you scrool again there will be more colored elements. That's why you have to color your marked element with desired color, and color ALL OTHER elements with normal color.
listview_otherSubnets.setAdapter(new ArrayAdapter<String>(this, R.layout.networks_list_item, list) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view=super.getView(position, convertView, parent);
TextView textView=(TextView) view.findViewById(R.id.networkslistitem);
if(index_network==position){
Log.i("OtherSubnet", "Adapter Current Network");
textView.setTextColor(Color.parseColor("#33b5e5"));
textView.setTypeface(null, Typeface.BOLD);
} else {
textView.setTextColor(Color.parseColor("#ff4444"));
textView.setTypeface(null, Typeface.BOLD);
}
view.setClickable(false);
return view;
}
});
You have to add one more condition which sets the color to something else.
if(index_network!=-1 && index_network!=position){//get the specific one
Log.i("OtherSubnet", "Adapter Current Network");
textView.setTextColor(Color.parseColor("#Something else"));
textView.setTypeface(null, Typeface.BOLD);
}
I have a ListView in which each row is a TextView, and display a line of text. I'm getting a problem where occasionally an unwanted empty row appears. The empty row goes away once list scrolls past that particular area.
I've verified my list rows contain the correct information by using the following code after pausing the app in the debugger. Nothing in the output shows up empty or null, etc.
for (int i = 0; i<list.getChildCount(); i++) {
System.out.print((TextView) list.getChildAt(i)).getText());
}
This shows the information I expected.
I also checked the data backing my Adapter for empty entries, new lines, etc.
My getView() method inside the Adapter is as follows:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView t;
if (convertView == null) {
convertView = mInflator.inflate(R.layout.single_message_row, null);
t = (TextView) convertView;
t.setMovementMethod(LinkMovementMethod.getInstance());
t.setTextSize(mMsgSize);
}
else {
t = (TextView) convertView;
}
CharSequence text = get(position);
t.setText(text);
return t;
}
Below is an image demonstrating the problem (the area in red):
Try after changing getView method as:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if(row==null){
LayoutInflater inflater=getLayoutInflater();
row=inflater.inflate(R.layout.single_message_row, parent, false);
}
TextView t=(TextView)row.findViewById(R.id.yourtextview);
t.setText("position "+position);
t.setMovementMethod(LinkMovementMethod.getInstance());
t.setTextSize(mMsgSize);
CharSequence text = get(position);
t.setText(text);
return row;
}
It seems the problem was caused by using match_parent for my TextView width in the ListView. Changing it to wrap_content seems to have fixed it.
For an unwanted empty list item occurring in the ListView, I tried this:
List<String> listofItems;
String strlist=listofItems.get(position);
if(strlist.isEmpty())
{
remove(strlist);
}
'position' is what i got as a parameter in View getView method, because i was implementing a custom adapter.
it worked fine for me!
I was using SimpleCursorAdapter with an xml file with some views defined in it:
<LinearLayout ...>
<ImageView android:id="#+id/listIcon" />
<TextView android:id="#+id/listText" />
</LinearLayout>
My aim was to set the text color of the TextView, and the background color of the LinearLayout (that is, each row in the ListView) programmatically; the color is returned from a database.
I was getting NPEs when trying to manipulate the TextView for example, after it had found it with no complaints:
TextView tv = (TextView) findViewById(R.id.listText);
tv.setTextColor(color); // NPE on this line
Which is fair; if there's multiple entries in the list, it's reasonable to assume that "R.id.listText" will not work. So I extended SimpleCursor Adapter:
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
TextView text = (TextView) row.findViewById(R.id.listText);
// ImageView icon = (ImageView) row.findViewById(R.id.listIcon);
// If there's an icon defined
if (mIcon_id != 0) {
// icon.setImageResource(mIcon_id);
}
// If text color defined
if (mTextColor != 0) {
text.setTextColor(mTextColor);
}
// If background color set
if (mBackgroundColor != 0) {
row.setBackgroundColor(mBackgroundColor);
}
return(row);
}
And I get two different errors:
A similar NPE is thrown at
"text.setTextColor(mTextColor)"
If the lines with the ImageView are
uncommented, I get a
"ClassCastException:
android.widget.TextView" where I am
calling
"row.findViewById(R.id.listIcon)"
For reference, I was trying to use Commonsware's sample code, applying it to my situation. link (pdf)
Changed to this:
public View getView(int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
if (convertView == null) convertView = View.inflate(mContext, R.layout.theme_item, null);
TextView text = (TextView) convertView.findViewById(R.id.listText_tv);
ImageView icon = (ImageView) convertView.findViewById(R.id.listIcon_iv);
// If there's an icon defined
if (mIcon_id != 0) {
icon.setImageResource(mIcon_id);
}
// If text color defined
if (mTextColor != 0) {
text.setTextColor(mTextColor);
}
// If background color set
if (mBackgroundColor != 0) {
convertView.setBackgroundColor(mBackgroundColor);
}
bindView(convertView, mContext, mCursor);
return(convertView);
}
Now I get a ClassCastException in the next activity (on list item click). Nothing has been modified in the next activity; it worked when using a SimpleListAdapter for the list which had entries (upon which clicking would lead to Activity2), so I think it's still something I'm doing wrong in the this extended class.
It's not true that convertView will always be an existing instance; you should check if it's null and then instantiate it. If not, you can change it just as you did.
This should be like:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null)
convertView = //inflate your row here
View row = convertView;
//Manipulate the row here
return(row);
}
I would modify the getView method:
public View getView(int position, View convertView, ViewGroup parent) {
convertView = View.inflate(getContext(), R.layout.myLayout, null);
TextView text = (TextView) convertView.findViewById(R.id.listText);
ImageView icon = (ImageView) convertView.findViewById(R.id.listIcon);
// If there's an icon defined
if (mIcon_id != 0) {
icon.setImageResource(mIcon_id);
}
// If text color defined
if (mTextColor != 0) {
text.setTextColor(mTextColor);
}
// If background color set
if (mBackgroundColor != 0) {
convertView.setBackgroundColor(mBackgroundColor);
}
return convertView;
}
I think that you're getting NPE because you're trying to create a textview and an imageview in a view where they aren't there.
When you want inflate a ListView with entries from a database, in your activity you define main.xml whith a ListView:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listView1">
</ListView>
and in the onCreate method you set the view to this xml with setContentView(R.layout.main);. Then you create your cursor to your database and your custom adapter:
MySimpleCursorAdapter adapter = new MySimpleCursorAdapter(this, R.layout.entry,
names, new String[] {Phones.NAME, Phones.NUMBER}, new int[] {
R.id.listIcon, R.id.listText});
startManagingCursor(cursor);
ListView listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(adapter);
and you define an entry.xml with your listIcon and listText, where the adapter points. In my example, I'm querying the names and numbers from contact list.
In your custom adapter, you should access to your textview and imageview inside getView or bindView without any problem.
Here you have and example to get all the contacts in your contact list with its picture, name and number, but using ListActivity instead of activity, and only one xml with two text views and an imageview. If you use ListActivity you don't need to use a ListView and you don't need to set the content view in the activity.
I hope it helps!
Don't forget to put : layout_width and layout_heigth for each of your views .