6

只是一个基本问题:如果我有几十个 EditText 字段是 ListAdapter 的一部分,那么各个 EditText 字段如何知道它们属于哪一行?

目前我正在使用 TextWatcher 来监听文本输入。我尝试扩展 TextWatcher,以便可以将 EditText 的位置传递给 TextWatcher 的构造函数。

但是,当软键盘弹出时,与各个 EditText 字段对应的位置会随机排列。

如何将 EditText 字段跟踪到正确位置?

我正在使用 GridView 进行布局。每个项目的布局都是一个 ImageView,下面有一个 TextView 和 EditText 字段。

每个 EditText 的文本都保存在称为字符串的全局字符串数组中。它最初是空的,由我的 TextWatcher 类更新。

public void initList()
    {
        ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, R.layout.shape, strings)
        {
            @Override
            public View getView(final int position, View convertView, ViewGroup parent)  {
                if (convertView == null)  {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.shape, null);
                }
                final String theData = getItem(position);
                final EditText editText = (EditText) convertView.findViewById(R.id.shape_edittext);
                editText.setText(theData);
                editText.addTextChangedListener(
                        new MyTextWatcher(position, editText)
                );

                ImageView image = (ImageView) convertView.findViewById(R.id.shape_image);
                image.setBackgroundResource(images[position]);

                TextView text = (TextView) convertView.findViewById(R.id.shape_text);
                if (gameType == SHAPES_ABSTRACT)
                    text.setText("Seq:");
                else
                    text.setVisibility(View.GONE);  

                return convertView;
            }

            @Override
            public String getItem(int position) {        return strings[position];       }
        };

        grid.setAdapter(listAdapter);
    }


private class MyTextWatcher implements TextWatcher {
    private int index;
    private EditText edittext;
    public MyTextWatcher(int index, EditText edittext) { 
               this.index = index; 
               this.edittext = edittext;    
        }
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    public void onTextChanged(CharSequence s, int start, int before, int count) {}
    public void afterTextChanged(Editable s) {  strings[index] = s.toString();      }
    public void setIndex(int newindex) {  index = newindex;    }
}

当我单击第一个 EditText(见图)时,EditText 会转移到笑脸下方的那个。

显示 EditText 字段的布局方式

4

5 回答 5

5

不考虑这是否是一个好的 UI 设计,你会这样做:

public class TestList
{
    public void blah()
    {
        ArrayAdapter<DataBucket> listAdapter = new ArrayAdapter<DataBucket>()
        {

            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null);
                }

                final DataBucket dataBucket = getItem(position);
                final EditText editText = (EditText) convertView.findViewById(R.id.theText);
                editText.setText(dataBucket.getSomeData());
                editText.addTextChangedListener(new TextWatcher()
                {
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
                    {

                    }

                    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
                    {

                    }

                    public void afterTextChanged(Editable editable)
                    {
                        dataBucket.setSomeData(editable.toString());
                    }
                });

                return convertView;
            }
        };
    }

    public static class DataBucket
    {
        private String someData;

        public String getSomeData()
        {
            return someData;
        }

        public void setSomeData(String someData)
        {
            this.someData = someData;
        }
    }
}

'DataBucket' 是一个占位符。您需要使用您创建的任何类来存储在编辑文本中放入和编辑的数据。TextWatcher 将具有对所引用数据对象的引用。当您滚动时,编辑文本框应该使用当前数据进行更新,并且应该保存文本更改。您可能希望跟踪用户更改了哪些对象,以使数据/网络更新更有效。

* 编辑 *

要使用 int 位置而不是直接引用对象:

ArrayAdapter<DataBucket> listAdapter = new ArrayAdapter<DataBucket>()
{

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        if (convertView == null)
        {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null);
        }

        final DataBucket dataBucket = getItem(position);
        final EditText editText = (EditText) convertView.findViewById(R.id.theText);
        editText.setText(dataBucket.getSomeData());
        editText.addTextChangedListener(new TextWatcher()
        {
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
            {

            }

            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
            {

            }

            public void afterTextChanged(Editable editable)
            {
                getItem(position).setSomeData(editable.toString());
            }
        });

        return convertView;
    }
};

* 再次编辑 *

我觉得不得不为后代说,我实际上不会这样编码。我猜您想要比字符串数组更结构化的数据,并且您在外部维护字符串数组以及 ArrayAdapter,因此这是一种奇怪的并行情况。但是,这将正常工作。

我将数据保存在单个字符串数组中,而不是多维数组中。原因是因为支持 GridView 的数据模型只是一个简单的列表。这可能违反直觉,但事实就是如此。GridView 应该自己进行布局,如果留给自己的设备,将使用可变数量的单元格填充行,具体取决于您拥有多少数据以及屏幕的宽度(AFAIK)。

聊够了。编码:

public class TestList extends Activity
{
    private String[] guess;

    //Other methods in here, onCreate, etc

    //Call me from somewhere else. Probably onCreate.
    public void initList()
    {
        ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, /*some resourse id*/, guess)
        {

            @Override
            public View getView(final int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null);
                }

                final String theData = getItem(position);
                final EditText editText = (EditText) convertView.findViewById(R.id.theText);
                editText.setText(theData);
                editText.addTextChangedListener(
                        new MyTextWatcher(position)
                );

                return convertView;
            }
        };

        gridView.setAdapter(listAdapter);
    }

    class MyTextWatcher extends TextWatcher {
         private int position;

         public MyTextWatcher(int position) {
                 this.position = position;
         }

         public void afterTextChanged(Editable s) {
                 guess[position] = s.toString();
         }

     // other methods are created, but empty
    }
}
于 2011-11-14T00:37:49.250 回答
3

要跟踪行号,每个侦听EditText器都必须保留对列表中某个项目的引用,并使用它getPosition(item)来获取 a 中的位置ListView。我的示例使用Button但我认为它可以应用于EditText.

class DoubleAdapter extends ArrayAdapter<Double> {
    public DoubleAdapter(Context context, List<Double> list) {
        super(context, android.R.layout.simple_list_item_1, list);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_row, null);
        }

        // keep a reference to an item in a list
        final Double d = getItem(position);

        TextView lblId = (TextView) convertView.findViewById(R.id.lblId);
        lblId.setText(d.toString());

        Button button1 = (Button) convertView.findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // the button listener has a reference to an item in the list
                // so it can know its position in the ListView
                int i = getPosition(d);
                Toast.makeText(getContext(), "" + i, Toast.LENGTH_LONG).show();
                remove(d);
            }
        });

        return convertView;
    }
}
于 2011-11-14T02:16:57.490 回答
1

是否需要将编辑文本存储在列表单元格中可能值得考虑?当用户一次只编辑一个时,这似乎有点不必要。

虽然我不知道您的应用程序是如何设计的,但我建议您稍微重新考虑您的用户体验,以便在按下列表项时显示单个文本编辑供他们编辑。这样,您就可以像通常使用列表适配器一样获取列表项引用,在用户编辑时存储它,并在完成后更新它。

于 2011-11-14T00:12:58.950 回答
1

我不确定这是否是一个不错的设计,因为一旦滚动列表视图,EditText 内容很可能会出现问题(随机播放内容、丢失文本)。考虑尝试 m6tt 的想法。

但是如果你真的想走你的路,你能发布一些代码,特别是你的 TextWatcher 吗?

于 2011-11-14T00:23:42.790 回答
0

我试图解决这个问题,你可以看到有一个简单的方法 - 我在这里发布答案,因为它可能对某人有用。

当列表视图 -> 编辑文本有文本观察器时无法获得位置。

这是对我有用的解决方案:

在获取视图 -

当我添加文本观察侦听器来编辑文本时,我还添加了以下行

edittext.setTag(R.id.position<any unique string identitiy>, position)

在你的 afterTextChanged -

 int position = edittext.getTag(R.id.position) 

给出正确的位置编号,您可以根据位置编号进行修改。

于 2017-04-26T12:57:59.947 回答