我在listview
中有一个layout
,每个项目都有两个部分:一个是用户头像(ImageView
),另一个是聊天内容({{1} })。看起来像:
我有一个自定义TextView
。
我想实现:当我点击头像时,我可以进入系统库并选择一张照片作为头像。
所以我在adapter
课程中关于onClickListener
的代码是:
adapter
我还覆盖了活动中的 Intent itent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
((Activity)(context)).startActivityForResult(itent, LOAD_IMAGE_RESULT);
方法。
但是,我上面提到的解决方案无法更改onActivityResult
方法中的头像,因为我不知道如何在onActivityResult
和adapter
之间进行通信。
希望找到解决方案。
答案 0 :(得分:2)
编辑 - 最初,我刚刚展示了一种更新子视图的方法,只是让它的适配器处于不一致状态(因为原始问题不提供有关基础数据结构的更多信息)。
适配器:Adapter对象充当AdapterView与该视图的基础数据之间的桥梁。适配器提供访问权限 数据项。适配器还负责制作View for 数据集中的每个项目。
注意: 由于定义本身描述了维护状态(数据+视图)很重要。因此,您应该始终拥有一致的用户体验。
为了正确地给出示例,我还根据原始问题中给定图像的假设定义了数据模型类ItemData
。
/**
* Model Class
*/
public class ItemData {
private Uri imageUri;
private String msg;
private Date timeStamp;
public void setImageUri(Uri uri) {
this.imageUri = uri;
}
public Uri getImageUri() {
return this.imageUri;
}
...
}
<强> CustomAdapter 强>
为listView创建自定义适配器,它将相应地维护子视图及其数据集。您必须维护最后选择的行索引lastSelectedIndexRow
的引用,稍后可以使用它来更新视图。
注意: 要获取listView
中任何索引的视图,我们不应该调用适配器的getView()
方法。由于对convertView调用getView()
为null会导致适配器从适配器的布局资源中膨胀新视图(不会获取已经显示的视图)。
AdapterView 应始终根据适配器保留的当前数据集使用notifyDataSetChanged()进行更新。
public class CustomAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private List<ItemData> dataList;
private int lastSelectedRowIndex = -1;
public static int LOAD_IMAGE_RESULT = 201;
public CustomAdapter(Context context, ArrayList<ItemData> dataList) {
// hold the items
this.context = context;
this.dataList = dataList;
this.inflater = LayoutInflater.from(this.context);
}
@Override
public int getCount() {
return (dataList != null && !dataList.isEmpty()) ? dataList.size() : 0;
}
@Override
public ItemData getItem(int position) {
return (dataList != null && !dataList.isEmpty()) ? dataList.get(position) : null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
if (converView == null) {
// inflate the layout
convertView = inflater.inflate(R.layout.row_item, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.avatar = (ImageButton)view.findById(R.id.avatar);
// store the holder with the view.
convertView.setTag(viewHolder);
}
else {
// we've just avoided calling findViewById() on resource every time
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// Set row data
ItemData data = (ItemData)getItem(position);
if (data != null) {
// set message
viewHolder.message.setText(data.getMessage());
// set formatted timestamp
String formattedTimeStamp = ...; // convert data.getTimeStamp() into formatted version
viewHolder.timeStamp.setTextView(formattedTimeStamp);
// set Image and also it's action.
viewHolder.avatar.setImageUri(data.getImageUri());
viewHolder.avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
((Activity)context).startActivityForResult(intent, LOAD_IMAGE_RESULT);
} catch (Exception e) {
Log.e("Demo application", "Failed to invoke call", e);
}
}
}
}
}
/**
* Get the last selected item index
*
*/
public int getLastSelectedItemIndex() {
return lastSelectedRowIndex;
}
/**
* Update the adapater with new data
*
*/
public void updateItems(List<ItemData> dataList) {
if (this.dataList != dataList)
this.dataList = dataList;
// update the view.
notifyDataSetChanged();
// reset the last selection
lastSelectedRowIndex = -1;
}
/**
* Hold View items
*/
static class ViewHolderItem {
private ImageView avatar;
private TextView message;
private TextView timeStamp;
}
}
<强>为ExampleActivity 强>
在活动中,您需要定义自定义适配器的引用并使用onActivityResult()
方法处理图像选择结果。从库中获取所选图像后,更新dataList
内的基础数据,并通过调用updateItems()
自定义方法更新适配器。
适配器的updateItems()
方法将新数据列表作为参数,并通过调用notifyDataSetChanged()使adapterView无效。
public class ExampleActivity extend FragmentActivity {
private ListView listView;
private CustomAdapter adapter;
private List<ItemData> dataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dataList = ...; // Load the list from database
// Create the custom adapter with filled list items.
adapter = new CustomAdapter(this, dataList);
// List View and set the data adapter
listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(adapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Check if it's coming from MediaStore Selection.
if (resultCode == Activity.RESULT_OK &&
requestCode == CustomAdapter.LOAD_IMAGE_RESULT) {
// Get the selected rowIndex
if (adapter != null && dataList != null) {
// check the row index is valid
int rowIndex = adapter.getLastSelectedItemIndex();
if (rowIndex > -1 && rowIndex < dataList.size()) {
// Get the item
ItemData item = dataList.get(rowIndex);
// Update the item with imageUri
item.setImageUri(Uri.parse(data.getData()));
/**
* If you may want to update the information in database,
* then it's the best place, but please do in background thread.
*/
//Now notify the adapter with new changes
adapter.updateItems(dataList);
}
}
}
}
...
}
答案 1 :(得分:0)
您应该在onClickListener方法中保存对单击视图的引用,并在适配器中使用公共方法。当您在onActivityResult方法中获得响应时,请调用适配器的方法并使用
答案 2 :(得分:-1)
在适配器中,(不确定使用哪种适配器),为ImageView设置onClickListener。因此,
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
<INSERT CODE HERE>
mContext.startActivity(intent);
}
});
其中mImageView是该项目的ImageView。另外一个好主意可能是使用ImageButton,因为它允许图像,并且是一个你想要的按钮。然后通过添加要选择图像的代码。您可能还需要将上下文传递给适配器(但无论如何通常都会这样做)。然后,您可以在适配器所在的活动中处理onActivityResult方法,即将Image设置为您选择的图像。有几种方法可以做到这一点。
答案 3 :(得分:-1)
在自定义适配器中添加公共方法以设置图像(如public void setAvatar(Bitmap image)
)
然后,在您的onActivityResult
方法中,选择图像并使用新创建的方法在适配器中设置新图像。 (有关更多信息,请参见此处:Getting a Result from an Activity
请勿忘记在适配器的新方法末尾放置notifyDataSetChanged();
以刷新所有列表。
public void setAvatar(Bitmap image)
{
...
imageView.setImageBitmap(image);
...
notifyDataSetChanged();
}
此外,如果您需要知道点击了哪个图片,可以指定Integer
作为参数,并在onActivityResult
中进行检查。
我看到你为这个参数使用常量LOAD_IMAGE_RESULT
。而不是一个常量,放一个识别被点击项的整数。