Search code examples
androidandroid-listviewandroid-edittextgetview

How to implement selectable ListView with EditText in ListItem in Android


I'm trying to implement a custom list view which has list items with spinner and edittext. And the list item needs to be selectable, also the edittext in list item needs to be editable. But the problem is when I set the edittext editable with setFocusable(true), the list item isn't selectable, and when I set the edittext not editable with setFocusable(false), the list item is selectable. Does anyone know how to solve this?

Below is my code

@Override
public View getView(int position, View convertView, ViewGroup parent) {
  View listItemView = convertView;

  if (listItemView == null) {
    listItemView = inflater.inflate(R.layout.listitem, null);
    ViewHolder viewHolder = new ViewHolder();
    viewHolder.view1 = (Spinner) listItemView.findViewById(R.id.view1);
    viewHolder.view2 = (EditText) listItemView.findViewById(R.id.view2);

    viewHolder.view1.setFocusable(false);
    viewHolder.view2.setFocusable(false);

    viewHolder.view1.setAdapter(view1Adapter);
    viewHolder.view1.setOnItemSelectedListener(this);

    viewHodler.view2.setOnFocusChangeListener(this);

    listItemView.setTag(viewHolder);
  }

  CustomListItem item = listViewItemList.get(position);
  ViewHolder viewHolder = listItemView.getTag();
  viewHolder.view1.setSelection(item.view1Value);
  viewHolder.view1.setTag(item);
  viewHolder.view2.setText(item.view2Value);
  viewHolder.view2.setTag(item);

  return listItemView;
}

===== updated to add xml =====

Below is my xml files for list view and item.

For list view.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FFFFFF"
tools:context="namespace">

  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
    <ListView android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:listSelector="#AAAAAA"
        android:background="#FFFFFF"
        android:descendantFocusability="beforeDescendants" />
    <TextView android:id="@android:id/empty" android:layout_width="match_parent"
        android:layout_height="match_parent" android:gravity="center"
        android:text="@string/empty"/>
  </FrameLayout>

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="@string/add"
        android:id="@+id/btn_add" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="@string/delete"
        android:id="@+id/btn_delete" />
  </LinearLayout>
</LinearLayout>

For list item.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"
android:weightSum="3">

<Spinner
    android:id="@+id/view1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1" />

<EditText
    android:id="@+id/view2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/empty"
    android:layout_weight="2"
    android:textSize="15sp"
    android:inputType="number" />

</LinearLayout>

Solution

  • Finally I found a solution for this requirement, however it requires a bit code works and it was different with what I expected at first.

    Anyway below is a code block from my list adapter which implements AdapterView.OnItemSelectedListener, View.OnFocusChangeListener and View.OnTouchListener

    private EditText activatedEditText;
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      View listItemView = convertView;
    
      if (listItemView == null) {
        listItemView = inflater.inflate(R.layout.listitem, null);
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.view1 = (Spinner) listItemView.findViewById(R.id.view1);
        viewHolder.view2 = (EditText) listItemView.findViewById(R.id.view2);
    
        viewHolder.view1.setFocusable(false);
        viewHolder.view2.setFocusable(false);
    
        viewHolder.view1.setOnTouchListener(this);
        viewHolder.view2.setOnTouchListener(this);
    
        viewHolder.view1.setAdapter(view1Adapter);
        viewHolder.view1.setOnItemSelectedListener(this);
    
        viewHodler.view2.setOnFocusChangeListener(this);
    
        listItemView.setTag(viewHolder);
      }
    
      CustomListItem item = listViewItemList.get(position);
      ViewHolder viewHolder = listItemView.getTag();
      viewHolder.view1.setSelection(item.view1Value);
      viewHolder.view1.setTag(item);
      viewHolder.view2.setText(item.view2Value);
      viewHolder.view2.setTag(item);
    
      return listItemView;
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      if(v.getClass() == EditText.class) {
        activatedEditText = (EditText)v;
        activatedEditText.setFocusable(true);
        activatedEditText.setFocusableInTouchMode(true);
        activatedEditText.requestFocus();
      }
      else {
        activatedEditText.clearFocus();
        activatedEditText.setFocusable(false);
        activatedEditText.setFocusableInTouchMode(false);
    
        InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(activatedEditText.getWindowToken(), 0);
      }
    }