如何解决Android 使用带有 ArrayAdapter 的自定义对象,并传达回视图
有一些与此类似的问题,但我找不到符合我要求的问题。我正在使用存储在 ArrayAdapter 中的自定义类来填充具有线性布局的 ListView,我可以通过修改该类来自定义该类 - 这是因为我在每个按钮中都有一个按钮,它完全符合我的要求。 LinearLayout 看起来像: [TextView][EditText][Button] 并且当单击 Button 时,它会使用 EditText 的内容执行一些 DB 操作。没关系。
我遇到的问题是我想(例如)在我的活动中而不是在创建视图和设置按钮侦听器的类中更新 ListView 中 1 个布局中的 EditText 的文本内容在。我可能还想说“禁用列表视图第二项中的按钮”等。
我尝试了很多不同的方法,在适配器上与在实际对象列表上传递上下文或调用方法,使 EditText 成为具有 getter 的成员变量,我总是要么什么也没发生,要么我达到按 ID 查找 EditText 时出现 NullPointerException。
这甚至可能吗?我是否需要创建一个最终变量来保存每个 EditText 并以某种方式将其传递回活动或其他东西?我最终会在我的 Activity 中得到多个具有相同 ID 的视图,但它们将由不同的对象创建
最终我想要做的就是制作它,以便我可以稍微抽象一下我的 GUI。目前我有 8 个大约 90% 相同的活动,但是我在每个活动中设置了重复的代码。我想将其抽象为类,在其中我可以说“给我一个带有任何标签的新文本输入行,我将覆盖按钮行为”,然后将此任务重构为 1 个活动。当用户在“行”之一中输入数据时,活动可能需要更新其他行之一(或在按下后退按钮时清除 1 等),这就是为什么我希望能够回调阵列适配器内对象内布局内的特定视图:D
例如,我希望能够创建 3 个新的 textInputLineBuilder 对象(可能最终将其子类化)并将它们显示为:
[名称:][名称编辑文本][按钮]
[股票:][StockEditText][按钮]
[数量:][数量编辑文本][按钮]
这是(缩减的)布局,activity_row.xml
自定义对象膨胀并返回到 ArrayAdapter
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<TextView
android:id="@+id/rowLabel"/>
<EditText
android:id="@+id/rowInput"/>
<Button
android:id="@+id/rowButton"/>
</LinearLayout>
这是活动中的相关代码:
public class AnActivity implements UICallBack {
private ListView listOfInputs;
private ArrayList<UIElementInterface> listOfUIElements;
private UIElementsAdapter UIAdapter;
protected void onCreate() {
listOfInputs = (ListView) findViewById(R.id.listInputs);
listOfUIElements = new ArrayList<>();
listOfUIElements.add(new textInputLineBuilder("<label>",this)); //this implements a callback interface
//add a few more
UIAdapter = new UIElementsAdapter(this.getApplicationContext(),listOfUIElements);
UIAdapter.notifyDataSetChanged();
listOfInputs.setAdapter(UIAdapter);
}
public void updateUIState() {
//I have tried all sorts here
for (int i=0; i<listOfUIElements.size(); i++) {
UIAdapter.setTheText("test "+i,i);
}
UIAdapter.notifyDataSetChanged;
listOfInputs.setAdapter(UIAdapter);
}
}
然后我有我的 ArrayAdapter 类 UIElementsAdapter.java
,它从列表中检索适当的对象,然后调用 getRowView
以使对象膨胀将构成此“行”的布局
public class UIElementsAdapter extends ArrayAdapter<UIElementInterface> {
private final Context context;
public UIElementsAdapter(Context context,ArrayList<UIElementInterface> listOfUIElements) {
super(context,listOfUIElements);
this.context = context;
}
@Override
public View getView(int position,View convertView,ViewGroup parent) {
return getItem(position).getRowView(context,parent); //retrieves the UIElementInterface object aka textInputLineBuilder object
}
public void setTheText(String s,Integer position) {
try {
getItem(position).setEditText(s);
} catch(NullPointerException e) {
e.printStackTrace();
}
}
}
最后我有 textInputLineBuilder.java
实现了 UIElementInterface (getRowView & setEditText)
public class textInputLineBuilder implements UIElementInterface {
private View convertView;
public textInputLineBuilder(String label,UICallBack callback) {
this.labelText = label;
this.callback = callback; //used with button onclicklistener
}
public View getRowView(Context context,ViewGroup parent) {
LayoutInflater layout = LayoutInflater.from(context);
convertView = layout.inflate(R.layout.activity_row,parent,false);
label = (TextView) convertView.findViewById(R.id.rowLabel);
fuzzy = (Button) convertView.findViewById(R.id.rowButton);
input = (EditText) convertView.findViewById(R.id.rowInput);
final EditText inputFinal = input; //for the button listener. was trying using input as a member variable for setEditText but that didn't work
label.setText(labelText);
//add onclicklistener for the fuzzy button. works fine
return convertView;
}
public void setEditText(String s) {
//I have tried all sorts here,passing in context from various places,passing in layout inflaters etc
EditText e = (EditText) convertView.findViewById(R.id.rowInput);
e.setText(s);
}
}
解决方法
在 updateUIState()
中,您目前尝试通过调用 EditText
直接修改 setTheText()
。使用调试器,我能够看到这在一定程度上是有效的 - EditText
在 setEditText()
的末尾具有所需的值。但是由于 EditText
是由适配器管理的,单独设置文本并不能达到预期的效果。如果之后调用 e.invalidate()
,则文本显示正确,if 还会跳过 adapter.notifyDatasetChanged()
。
所以基本上可以修改View
。但这样做是个坏主意。
相反,您应该更改数据类。在您的情况下,您需要一种方法来为 String
中的 EditText
设置所需的文本 (TextInputLineBuilder
)。然后当 getRowView()
被调用时,这个更新的文本应该与 EditText input
一起使用。
回到updateUIState()
:修改数据列表后调用notifyDatasetChanged()
是正确的,但是不需要将适配器重新分配给ListView
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。