Android Focusable EditText inside ListView


Hi,

I was trying to implement something from here. But I don’t understand what he is doing. Using this works well to get focus on EditText.

The main issue I face later, when I have lots of item in ListView. I found this answer very helpful to understand recycling view. You can’t save anything on ListView Item. You must need to handle another data-source that maintain your changes in ListView’s item. Not talking too much, I’m just presenting working example, so readers can understand quickly.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<ListView android:id="@+id/MyList" android:layout_height="fill_parent"
		android:layout_width="fill_parent" android:descendantFocusability="beforeDescendants">
	</ListView>
</LinearLayout>

item.xml

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

	<EditText android:id="@+id/ItemCaption"
		android:layout_height="wrap_content" android:layout_width="fill_parent"
		android:layout_marginLeft="2dip" android:singleLine="true">
	</EditText>

</LinearLayout>

AndroidCustomListViewActivity.java

package com.isummation.android;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;

public class AndroidCustomListViewActivity extends Activity {
	private ListView myList;
	private MyAdapter myAdapter;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		myList = (ListView) findViewById(R.id.MyList);
		myList.setItemsCanFocus(true);
		myAdapter = new MyAdapter();
		myList.setAdapter(myAdapter);

	}

	public class MyAdapter extends BaseAdapter {
		private LayoutInflater mInflater;
		public ArrayList myItems = new ArrayList();

		public MyAdapter() {
			mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			for (int i = 0; i < 20; i++) {
				ListItem listItem = new ListItem();
				listItem.caption = "Caption" + i;
				myItems.add(listItem);
			}
			notifyDataSetChanged();
		}

		public int getCount() {
			return myItems.size();
		}

		public Object getItem(int position) {
			return position;
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(R.layout.item, null);
				holder.caption = (EditText) convertView
						.findViewById(R.id.ItemCaption);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			//Fill EditText with the value you have in data source
			holder.caption.setText(myItems.get(position).caption);
			holder.caption.setId(position);

			//we need to update adapter once we finish with editing
			holder.caption.setOnFocusChangeListener(new OnFocusChangeListener() {
				public void onFocusChange(View v, boolean hasFocus) {
					if (!hasFocus){
						final int position = v.getId();
						final EditText Caption = (EditText) v;
						myItems.get(position).caption = Caption.getText().toString();
					}
				}
			});

			return convertView;
		}
	}

	class ViewHolder {
		EditText caption;
	}

	class ListItem {
		String caption;
	}
}