2

I am using a custom base adapter to implement a customListView. The listView class (extends ListView) is used within a flipper flipper.addView(mListView) in the main activity.

The list View has 3 types of rows. The 1 st in the list is a row with spinner, the next 2 are rows with edittext where text is inputed. The 3rd row and beyond are all the same with an edittext that has numbers in it. I wanted to make it so that when I click on the text version the softkeypad will appear with the text only and for the number version the phone keypad.
They display ok but the problem comes when you click on an edittext, the softkeyboard pops up fine in the phone format. It is all setup and values set within getView() but when the softkeyboard pops up in the phone format getView() gets called again (logical) but as soon as it hits 1 of the text type EditTexts the keyboard type switches back to text input. It will cannot easily be turned back to a phone style display after that. The view appears to be jumping around and struggling to focus on the EditText I want I am really lost here and can't figure this out. Here are the 2 main bits of code.

public class MethodEditorAdapter extends BaseAdapter{

private Context context;
private ArrayList<String[]>  scanparam;

private LayoutInflater mInflater; 

public MethodEditorAdapter(Context context, ArrayList<String[]> scanparam ) { 
    super();
    this.scanparam = scanparam;
    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}
@Override
public long getItemId(int position) {
    int i = 0;
    if(position == 0) i = 0;
    if(position ==1) i = 1;         
    if(position == 2)i = 1;
    if (position > 2)i = 2;
    return i;
}
@Override
public int getViewTypeCount() {
    return 3;
}

@Override
public int getItemViewType(int position) {
    int i = 0;
    if(position == 0) i = 0;
    if(position ==1) i = 1;         
    if(position == 2)i = 1;
    if (position > 2)i = 2;
    return i;
}

public View getView(int position, View convertView, ViewGroup parent) { 

    Formatnames(position);
    View rowView = convertView;
    ViewHolder holder = null;
    int type = getItemViewType(position);

    if (rowView == null ) {

        holder = new ViewHolder();
        switch (type) {
        case 0:
            rowView = mInflater.inflate(R.layout.method_editor_row_spin, null);
            holder.paramname = (TextView) rowView.findViewById(R.id.techniquetag);
            holder.techniquespinner = (Spinner) rowView.findViewById(R.id.techniquespinner);
            break;
        case 1:
            rowView = mInflater.inflate(R.layout.method_editor_row_text, null);
            holder.paramname = (TextView) rowView.findViewById(R.id.paramnameT);
            holder.paramvalue = (EditText) rowView.findViewById(R.id.paramvalT);
            break;
        case 2:
            rowView = mInflater.inflate(R.layout.method_editor_row_number, parent, false);
            holder.paramnameNum = (TextView) rowView.findViewById(R.id.paramnameN);
            holder.paramvalueNum = (EditText) rowView.findViewById(R.id.paramvalN);
            break;
        }
        rowView.setTag(holder);


    }else {
        holder = (ViewHolder) rowView.getTag();
    }

    setSelectedPosition(position);


    switch (type) {
    case 0:
        holder.paramname.setText(namestg + " " + nd);
        holder.techniquespinner.setSelection(Integer.valueOf(scanparam.get(position)[1]));
        break;
    case 1:
        holder.paramname.setText(namestg + " " + nd);
        holder.paramvalue.setText(scanparam.get(position)[1]);
        break;
    case 2:
    holder.paramnameNum.setText(namestg + " " + nd);
    holder.paramvalueNum.setText(scanparam.get(position)[1]);
    }

    return rowView;
}

static class ViewHolder {
    public TextView paramname;
    public EditText paramvalue;
    public Spinner techniquespinner;
    public TextView paramnameNum;
    public EditText paramvalueNum;

}

the main view

public class MethodEditorView extends ListView {

private ArrayList<String[]> thismethod = new ArrayList<String[]>();

public MethodEditorAdapter editorAdapter;

private ListView mListView;

private Context mContext;

public MethodEditorView(Context context, ArrayList<String[]> methodlist) { 
    super(context);
    // TODO Auto-generated constructor stub
    this.thismethod = methodlist;
    mContext = context;enter code here
initview(context);
}

 private void initview(Context context){
    editorAdapter = new MethodEditorAdapter(context, thismethod );
    this.setAdapter(editorAdapter);

 }

}

the xml, sorry I couldn't insert it properly. this is for the number type.

<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="fill_parent" android:id="@+id/methodrownumber">
    <TextView android:layout_height="wrap_content" android:layout_weight="1" android:textSize="16sp" android:textStyle="bold" android:id="@+id/paramnameN" android:layout_width="fill_parent" android:padding="5dp"></TextView>
    <EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:textSize="16sp" android:layout_weight="1" android:id="@+id/paramvalN" android:imeOptions="actionNext" android:inputType="phone" android:focusable="true" android:focusableInTouchMode="true" android:clickable="true"></EditText>

user960914
  • 197
  • 1
  • 3
  • 12

2 Answers2

3

After days and days here's my solution for a smooth flowing editable listview. There are 2 absolutely paramount things you have to set to make them work and editable without losing focus all the time.

The most critical 1 is. in the manifest

<activity android:name=".youractivity" android:windowSoftInputMode="adjustPan"/>

then in the xml of the listview

android:descendantFocusability="beforeDescendants"

or

mListView.setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);

This last 1 simply enlarges the listview with an open editor over the top of any other views outside the listview such as an action bar. Nice for a small screen! Found in the middle of this conversation stackoverflow link

Community
  • 1
  • 1
user960914
  • 197
  • 1
  • 3
  • 12
  • I'm going to vote down my own answer because ListViews with focusables are well...crap. DON'T do them!!. ScrollView is definitely the way forward and I implemented a custom "BaseAdapter" style class for populating the scrollview with my rows. – user960914 Jul 17 '12 at 11:07
  • Thanks for describing and trying to solve the issue. Its been 6 years since you suggested using a ScrollView instead of a ListView. Are you still using the same approach ? Is it as simple as adding controls to a vertical LinearLayout, thats inside a scrollview, at runtime ? – Reyn Jul 31 '18 at 07:57
  • 1
    HIya yes I do still use a ScrollView but my Views are not very big. I use a tablelayout with rows within the scrollview to control layout positions. My scrollview has typically 30 rows – user960914 Dec 21 '18 at 13:44
1

Let me save you a lot of headache with the edittext in your listview. Don't do it. I spent well over a week trying to get edittext in a listview to not recycle inputs, to make sure the right input is in the right field when you onresume. I would recommend making a scroll view with a tablelayout that looks like a listview at the end of the day. As long as you don't have a huge number of rows this will work and run fine. Now if lets say you have 100 rows, not gonna be pretty.

    public class inputpage extends Activity implements OnClickListener{

        public TableLayout tl;
        static Map<Integer, String> inputValues = new LinkedHashMap<Integer, String>();
        private dbadapter mydbhelper;
        public static int editCount;
        private PopupWindow pw;
        public Cursor cursor;
        private ArrayList<EditText> m_edit = new ArrayList<EditText>();

        @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        mydbhelper = new dbadapter(this);
        mydbhelper.open();
        setContentView(R.layout.tablelayout);
        tl=(TableLayout) this.findViewById(R.id.table);
        getCursor();
        editCount = cursor.getCount();
        buildRow();

        View footer = getLayoutInflater().inflate(R.layout.footer_layout, null);
        tl.addView(footer);





        }
//This lets me get a cursor so I can settext on my textviews
        public void getCursor(){
        if(main.quickStart == "Cate"){
            cursor = mydbhelper.getUserWord();
        }...

            //add my rows in a loop based off how many items my cursor brought back
        public void buildRow(){
            //params for my different items
            LayoutParams textparam = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT, .30f);
            LayoutParams editparam = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT, .70f);
            textparam.setMargins(2, 2, 2, 2);
            editparam.setMargins(2, 2, 2, 2);
            editparam.gravity=17;
            LayoutParams rowparam = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
            cursor.moveToFirst(); //make sure cursor starts at beginning
            for (int i = 0; i < editCount; i++){
                TableRow tr = new TableRow(this);
                tr.setLayoutParams(rowparam); 

                //textview
                TextView tv=new TextView(this);
                tv.setLayoutParams(textparam);
                tv.setText(cursor.getString(cursor.getColumnIndex("userword")));
                tv.setTextSize(35f);
                tv.setGravity(Gravity.CENTER);
                tv.setWidth(175);
                tv.setTextColor(getResources().getColor(R.color.black));
                tr.addView(tv);

                //edittext
                EditText edit = new EditText(this);
                edit.setLayoutParams(editparam);
                tr.addView(edit);
                edit.setGravity(Gravity.LEFT);
                edit.setId(editCount);
                m_edit.add(i, edit);
                edit.setText("");

                cursor.moveToNext();
                tl.addView(tr, new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
            }}

Hope this helps and saves you a lot of trouble. BTW I build what I can in xml (tablelayout, footer etc) and just make my table row via java.

maebe
  • 553
  • 1
  • 6
  • 18
  • Sorry for the delayed response, personal reasons. I like this idea and my list is never more than 20 lines long. But I forgot to mention that I dynamically build it because I have about 12 different listviews each slightly in different layout so I just recycle the rows. I posted another alternative below – user960914 Mar 02 '12 at 09:13
  • see below I used ScrollView in the end – user960914 Jul 17 '12 at 11:09