【问题标题】:Update activity's TextView from EditText value within ListView's item从 ListView 项中的 EditText 值更新活动 TextView
【发布时间】:2016-11-17 19:40:49
【问题描述】:

所以,我有一个带有 TextView 的活动和一个带有自定义 BaseAdapter 的 ListView。此活动如下所示:

如您所见,列表中的每个项目都是自定义布局,其基本思想是:每当其中的数字 EditText 发生变化时,活动中的“总”TextView(即每个项目价格的总和)产品)也必须更新。

我想它必须以某种方式从 Adapter 类中完成,但我不知道该怎么做。

我的 Activity 文件如下所示(它通过“GetCollectionProducts”AsyncTask 从服务器获取产品数据,我在其中设置了适配器):

public class ProductAisleActivity extends AppCompatActivity implements View.OnClickListener{
ListView productList;
Button participate;

ImageButton search;
EditText searchET;
TextView productsTotal;

Product[] colProducts;
RelativeLayout collectionHeader;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_product_aisle);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    /* ...
       Irrelevant code to this question 
    */

    productsTotal = (TextView) findViewById(R.id.products_aisle_total);
    productsTotal.setText(
            getResources().getString(
                    R.string.productsTotal,
                    String.valueOf(0.00)
            )
    );

    productList = (ListView) findViewById(R.id.products_aisle_list);
    new GetCollectionProducts().execute();
}

private class GetCollectionProducts extends AsyncTask<Void,Void,JSONArray>{

    @Override
    protected JSONArray doInBackground(Void... voids) {
        /* Irrelevant code to this question */
    }

    @Override
    protected void onPostExecute(JSONArray jsonArray) {
        /* Irrelevant code to this question */
                productList.setAdapter(
                        new CollectionProductsAdapter(
                                ProductAisleActivity.this,
                                colProducts
                        )
                );
}
}

我的适配器文件如下所示:

public class CollectionProductsAdapter extends BaseAdapter {
Context context;
ProductAisleActivity.Product[] data;
private static LayoutInflater inflater = null;

public CollectionProductsAdapter(Context context, ProductAisleActivity.Product[] data) {
    this.context = context;
    this.data = data;
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return data.length;
}

@Override
public Object getItem(int i) {
    return data[i];
}

@Override
public long getItemId(int i) {
    return i;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    View v = view;
    if (v == null) {
        v = inflater.inflate(R.layout.product_row_layout, null);
    }

    ProductAisleActivity.Product product = data[i];

    /* ...
       Irrelevant code to this question 
    */

    EditText productQuantity = (EditText) v.findViewById(R.id.productQuantity);
    productQuantity.setText("0");


    return v;
}

}

我被困在这一点上,任何帮助将不胜感激。

【问题讨论】:

  • 有很多方法。您可以使用 TextWatcher 来检查 EditText 中的内容何时被修改并将其推送到 Observer 或其他东西。
  • @zgc7009 你能给我举个例子吗?谢谢!

标签: android listview textview listadapter


【解决方案1】:

首先,您需要监听 EditText 中的任何更改,这样您就可以动态地处理事情,而无需显式使用提交按钮之类的东西。您可以使用 TextWatcher 执行此操作。

productQuanity.addTextChangedListener(new TextWatcher() {
        private double originalCost = 0.0;

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // Before we change the text, set the originalCost
            // so we can know what the change is after the edit
            originalCost = getCost(s.toString());
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // You don't need to utilize this method
        }

        @Override
        public void afterTextChanged(Editable s) {
             // After the change has taken place in the text,
             // get the new cost and calculate the difference
             double newCost = getCost(s.toString());
             double changeInCost = newCost - originalCost;
        }

        private double getCost(String input){
            String count = input.toString();
            if(TextUtils.isEmpty(count))
                return 0.0;
            else
                return (double) Integer.parseInt(count) * product.getPrice();
        }
    });

既然我们有了成本变化,我们该怎么办?我们需要通知活动我们有更改。我们可以使用观察者来做到这一点,这很好,但为了好玩,我们使用一个接口来实现一个监听器。

修改你的适配器类

public class CollectionProductsAdapter extends BaseAdapter {

    public interface CostChangedListener{
        void onCostChanged(double change);
    }

    Context context;
    ProductAisleActivity.Product[] data;
    private LayoutInflater inflater = null; // THIS SHOULDN'T BE STATIC
    CostChangedListener listener;

    public CollectionProductsAdapter(Context context, ProductAisleActivity.Product[] data, CostChangedListener listener) {
        this.context = context;
        this.data = data;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.listener = listener;
    }

    // The rest of your code
}

现在,当我们在 TextWatcher 中更新成本时,我们可以调用

if(listener != null)
    listener.onCostChanged(changeInCost);

最后,为了确保我们正确使用它,我们需要在 CollectionProductsAdapter 构造函数中传递一个监听器

productList.setAdapter(new CollectionProductsAdapter(
            ProductAisleActivity.this, colProducts,
            new CostChangeListener(){
                @Override
                public void onCostChanged(double change){
                    double currentTotal = Double.valueOf(productTotal.getText());
                    double newTotal = currentTotal + change;
                    productTotal.setText(String.valueOf(newTotal));
                }));

显然,您可能需要对其进行一些调整以使其完美匹配,而且我还没有对其进行测试,因此有些事情可能会有些偏差,但这应该会让您朝着正确的方向前进。如果您有任何问题,请随时发表评论,我会尽力帮助您解决问题。

备注

  1. 不要像使用布局充气器那样保留静态引用
  2. 值得看看 RecyclerView 或至少是带有适配器的 ViewHolder 模式

【讨论】:

  • 谢谢!我现在就测试一下,告诉你效果如何!
  • 嘿!我有两个问题。 1) 我在哪里可以得到oldCost 方法中的oldCost 变量值?没有宣布! 2) 我应该把这个if(listener != null) listener.onCostChanged(changeInCost); 放在哪里?谢谢!
  • @GénessisSánchez 应该说originalCost 而不是oldCost,我已经编辑了它。感谢您的通知。在计算 changeInCost 之后,将侦听器回调放置在 afterTextChanged() 中。
  • 好吧,我试过了,现在,每次我点击 EditText 来更新它的值,它都不会在里面写任何东西。此外,它现在显示字母数字键盘,而不是以前显示的数字键盘,因为它是数字 EditText。知道发生了什么吗?
  • @GénessisSánchez EditText XML 中的inputType 控制单击所述EditText 时显示的键盘类型。关于它没有在 EditText 中写任何东西,这肯定很奇怪。你的 logcat 有什么显示吗?
【解决方案2】:

您想添加一个 textChangedListener 以在用户更改 EditText 中的值时更改项目值。

您可以在这里使用 TextChangedListener:

EditText myEditTextField = new EditText(this);

myEditTextField.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {

    }
});

您可以根据需要执行任务。它有3种方法:

1.beforeTextChanged

2.onTextChanged

3.afterTextChanged

所以你可以在“afterTextChanged”的帮助下完成你的任务。你必须简单地调用你的计算价格的方法。当用户输入特定数字时,它会显示您想要的价格。

希望对您有所帮助!

【讨论】:

  • 非常感谢,这似乎是我正在寻找的答案。不过,我有两个问题,第一个:必须在哪里声明 TextWatcher?进入活动文件还是进入适配器文件?第二个:如果在adapter文件中,如何访问activity的TextView?再次感谢您!
  • 你可以在你的editText声明下面实现你的textWatcher。如果你想在适配器文件中实现它,那么首先你必须在适配器的viewHolder和它的正下方定义editText (在同一个viewHolder类中),可以实现textWatcher
  • onTextChanged 不会提供适当的答案。 onTextChanged 提供子序列编辑。 afterTextChanged 将为他提供要计算的完整字符串。
  • 哦,对不起!这是一个很大的错误。 @zgc7009 感谢您的发现。
  • 别担心,值得一提:)
猜你喜欢
  • 2015-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-03
  • 2019-12-02
相关资源
最近更新 更多