47222

Different “visibility” values in each row in a ListView

Question:

I have developed a very simple app that uses a custom adapter for a ListView.

Each row has two TextViews:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/text2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:visibility="gone" /> </LinearLayout>

The first TextView is named "text1", and the second "text2". As you see, <strong>text2 is hidden (visibility="gone")</strong>.

Also, the list has a header that only contains an EditText widget:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>

Each row is represented by a very simple object named "Item" that has 2 properties (text1 and text2), and its getters/setters. Also, it has a "hasText2" method that just checks if the object has the text2 property value's length > 0:

public class Item { private String text1; private String text2; public String getText1() { return text1; } public void setText1(String text1) { this.text1 = text1; } public boolean hasText2() { return text2.length() > 0; } public String getText2() { return text2; } public void setText2(String text2) { this.text2 = text2; } }

Okay, I'll initialize the list with just 2 items in my main app file:

Item item1 = new Item(); item1.setText1("Item 1"); item1.setText2("optional 1"); Item item2 = new Item(); item2.setText1("Item 2"); item2.setText2(""); getListView().addHeaderView(getLayoutInflater().inflate(R.layout.list_header, null), false, false); m_items = new ArrayList<Item>(); m_adapter = new CustomListAdapter(this, R.layout.list_row, m_items); setListAdapter(m_adapter); m_items.add(item1); m_items.add(item2); m_adapter.notifyDataSetChanged();

This is the getView method of my custom adapter (that extends ArrayAdapter):

@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.list_row, null); } // get the two text widgets of this row layout TextView text1 = (TextView) convertView.findViewById(R.id.text1); TextView text2 = (TextView) convertView.findViewById(R.id.text2); // get the Item object of this row Item list_item = items.get(position); // we set the text1 property of this Item to the text1 widget text1.setText(list_item.getText1()); // if this Item has a text2 (value length > 0), then set it to the text2 widget and make it visible if (list_item.hasText2()) { text2.setText(list_item.getText2()); text2.setVisibility(0); } return convertView; }

So, what I want is to <strong>show the text2 widget only if the Item object has it defined (value's length > 0)</strong>.

And this is the result after running the app:

<img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/UNmdV.png" data-original="https://i.stack.imgur.com/UNmdV.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" />

That's good, it works just as I expected!! :)

But what if I tap the EditText of the list header? (so I force to update the list):

<img alt="enter image description here" class="b-lazy" data-src="https://i.stack.imgur.com/33OcI.png" data-original="https://i.stack.imgur.com/33OcI.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" />

What happened here? That's impossible. The second row has no text2 defined, and Android just has taken the text2 from the first row! Why??

The only reason I could imagine is that I cannot use rows with different visibility... but then, why Android let me do it when I just run the app? It seems to fail only when the keyboard appears (list update).

Answer1:

This has a problem for the exact same reason I described in notes on your previous question. The view is being recycled, so the customization performed in the clause if (list_item.hasText2()) { is permanently set on that view; even when recycled to a view for which that clause would not be true.

In this case the following modification would probably fix the issue:

if (list_item.hasText2()) { text2.setText(list_item.getText2()); text2.setVisibility(View.VISIBLE); } else { text2.setVisibility(View.GONE); }

Recommend

  • Java library to map request parameters onto an object
  • Get Items in a PurchaseOrder using SuiteTalk
  • Getters and Setters in Eclipse for Hungarian Style Members
  • Spring creating bean but not injecting it
  • Conditionally ignore primitive typed fields with Jackson
  • Mapping ManyToMany with composite Primary key and Annotation:
  • Should a C# struct have only read-only properties
  • How to count amount of elements in a row of a matrix in C
  • Using an enum contained in a Cloud Endpoint model on a Android client
  • XSLT foreach repeating nodes to flat
  • Does Apple allow the usage of sysctl.h within iOS applications?
  • gspread or such: help me get cell coordinates (not value)
  • How to add git credentials to the build so it would be able to be used within a shell code?
  • How do I exclude a dependency in provided scope when running in Maven test scope?
  • Database structure design with variable amounts of fields
  • Q promise. Difference between .when and .then
  • How do I fake an specific browser client when using Java's Net library?
  • How to get a value (ex: baseURL) in every Karate feature?
  • How to apply VCL Styles to DLL-based forms in Inno Setup?
  • Trying to switch camera back to front but getting exception
  • Comma separated Values
  • retrieve vertices with no linked edge in arangodb
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • Free memory of cv::Mat loaded using FileStorage API
  • C# - Getting references of reference
  • JTable with a ScrollPane misbehaving
  • Angular 2 constructor injection vs direct access
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • How do I configure my settings file to work with unit tests?
  • Change div Background jquery
  • Turn off referential integrity in Derby? is it possible?
  • apache spark aggregate function using min value
  • Add sale price programmatically to product variations
  • unknown Exception android
  • Checking variable from a different class in C#
  • Programmatically clearing map cache
  • failed to connect to specific WiFi in android programmatically
  • Unable to use reactive element in my shiny app
  • How can I use threading to 'tick' a timer to be accessed by other threads?
  • How do I use LINQ to get all the Items that have a particular SubItem?