Listview with edittext - auto scroll on “next”

2019-01-27 18:24发布

问题:

I have a ListView with one EditText on each row (in addition to a couple of non-editable TextView's). When I'm editing the text in the EditText, the soft keyboard has "Next" button - and pressing it moves the focus to the next field - this is great. On the last row, the button changes to "Done".

I'm using EditText.setImeOptions to set the button to "Done" or "Next" based on whether this is the last row or not.

The problem is that the listview can have more rows that can fit on the screen. When that happens, pressing "Next" on the next visible row moves the focus onto the first row again. How can I make it scroll the list and go to the next row instead?

For reference, here's what I'm doing in my adapter:

public class AuditAdapter extends BaseAdapter {
    private Context context;
    private int layoutResourceId;
    private Audit audit;

    ...

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View row = convertView;
        final AuditItemHolder holder = (row == null ? new AuditItemHolder() : (AuditItemHolder)row.getTag());

        if(row == null)
        {
            LayoutInflater inflater = ...;
            row = inflater.inflate(layoutResourceId, parent, false);
            ...
            holder.qtyf = (EditText)row.findViewById(R.id.item_quantity);
        }

        AuditItem item = audit.getItemAt(position);

        holder.qtyf.setText("" + item.getQuantity());
        holder.qtyf.setImeOptions(position == audit.size() - 1 ? EditorInfo.IME_ACTION_DONE : EditorInfo.IME_ACTION_NEXT);

        ...

        row.setTag(holder);
        return row;
    }

    private static class AuditItemHolder {
        ...
        EditText qtyf;
    }
}

回答1:

Ok, after struggling for a long time, I finally found a hack (not a proper solution) that works for my case. In the getView of my adapter, I add the onEditorActionListener and inside it:

ediField.setOnEditorActionListener(new OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        ListView lv = (ListView)parent;
        if(actionId == EditorInfo.IME_ACTION_NEXT &&
           lv != null &&
           position >= lv.getLastVisiblePosition() &&
           position != audit.size() - 1) {  //audit object holds the data for the adapter
                lv.smoothScrollToPosition(position + 1);
                lv.postDelayed(new Runnable() {
                    public void run() {
                        TextView nextField = (TextView)holderf.qtyf.focusSearch(View.FOCUS_DOWN);
                        if(nextField != null) {
                            nextField.requestFocus();
                        }
                    }
                }, 200);
                return true;
        }
        return false;
    }
});


回答2:

I have no idea about holder, so I found a way to do without it. Inside getView add onEditorActionListener.

EditText editView = (EditText)convertView;
editView.editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(final TextView view, int actionId, KeyEvent event){
           if(actionId == EditorInfo.IME_ACTION_NEXT){
            int lastPos = lv.getLastVisiblePosition();
            lv.smoothScrollToPosition(position + 1);
            if(position >= lastPos){
                lv.postDelayed(new Runnable(){
                   @Override
                    public void run(){
                         final int posTop = lv.getFirstVisiblePosition();
                         TextView nextView = (EditText)lv.getChildAt(position - posTop + 1);
                         nextView.requestFocus();
                    }
                 }, 200);
            }
            //Delay is not required
            else{              
                final int posTop = lv.getFirstVisiblePosition();
                TextView nextView = (EditText)lv.getChildAt(position - posTop + 1);
                nextView.requestFocus();
            }
          }
      }
});