在 Android 中以 ArrayAdapter 中的视图为目标

Targeting a View within an ArrayAdapter in Android

我不确定我问的这个问题是否正确,因为我根本找不到任何相关信息。

我想知道是否可以从我的 Activity 中通过 ArrayAdapter 添加的视图 (ImageView) 定位。

我的 Activity 从服务器接收到 JSON,关于用户的配置文件。我将该信息显示到 ArrayAdapter 中。在 ArrayAdapter 中,我有一个 ImageView,它调用一种方法来更改用户的个人资料图像。用户选择 his/her 图片,最后 ImageView 随之改变。

问题是我实际上无法定位 ImageView。下面是我的代码:

简介Activity:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my_profile);

    userAdapter = new UserAdapter(this, new ArrayList<UserModel>());
    listView = (ListView) findViewById(R.id.myProfile_header);
    listView.setAdapter(userAdapter);

    LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    (new FetchUserTask()).execute(Constants.HOST + token.getAccessToken());

    image = (ImageView) findViewById(R.id.myProfile_avatar);
    avatarChange = (LinearLayout) findViewById(R.id.myProfile_avatar_change);
}

public String uriToPath(Uri uri) {
    String res = null;
    String[] proj = { MediaStore.Images.Media.DATA };
    Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
    if(cursor.moveToFirst()){
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        res = cursor.getString(column_index);
    }
    cursor.close();
    return res;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (data != null && (requestCode == SELECT_IMAGE_CODE || requestCode == CAMERA_IMAGE)) {

        Uri uri = Uri.parse("file://"+uriToPath(data.getData()));
        Picasso.with(this).load(uri).into(image);
    }

    /*...*/

}

配置文件适配器:

/*...*/

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.profile_header, null);
    }

    final ViewHolder viewHolder = new ViewHolder(v);
    v.setTag(viewHolder);

    final UserModel model = user.get(position);
    String userAvatar = model.getPhoto();

    viewHolder.name.setText(model.getUsername());
    viewHolder.email.setText(model.getEmail());
    viewHolder.phone.setText(model.getPhone_number());


    if (userAvatar != null && !userAvatar.isEmpty()) {
        //System.out.println(userAvatar);
        Picasso.with(getContext()).load(HOST+userAvatar).into(viewHolder.avatar);
    }

    viewHolder.avatarChange.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            selectImageFromGallery();
        }
    });

    return v;
}

public void selectImageFromGallery() {
    final CharSequence[] items = { "Take Photo", "Choose from Library",
            "Cancel" };

    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setTitle("Add Photo!");
    builder.setItems(items, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int item) {
            if (items[item].equals("Take Photo")) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File f = new File(android.os.Environment
                        .getExternalStorageDirectory(), "temp.jpg");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                ((Activity) context).startActivityForResult(intent, CAMERA_IMAGE);
            } else if (items[item].equals("Choose from Library")) {
                Intent intent = new Intent(
                        Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                ((Activity) context).startActivityForResult(
                        Intent.createChooser(intent, "Select File"),
                        SELECT_IMAGE_CODE);
            } else if (items[item].equals("Cancel")) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}

/*...*/

我必须感谢 John P. and Guardanis 提供了关于为什么我无法定位 ListView 的内部 child 的主要线索。它帮助改变了我思考问题本身的方式。我以为问题出在 Adapter 上,但在他们的建议下变得很清楚,问题出在 Activity.

代码更改本质上是:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (data != null && (requestCode == SELECT_IMAGE_CODE || requestCode == CAMERA_IMAGE)) {
        Uri imageUri = data.getData();
        View child = header.getChildAt(0);
        View image = child.findViewById(R.id.myProfile_avatar);
        Resources resources = getResources();
        ImageView imageX = (ImageView) image;

        imageX.setImageDrawable(resources.getDrawable(R.drawable.blank));
        Picasso.with(this).load(imageUri).into(imageX);
        profileAdapter.notifyDataSetChanged();
    }
}

有了这个,我可以使用 ListView.getChild(int) 访问我需要的视图,其中 "header" 是我的 ListView,0 是我的整数。然后将 View (child) 声明为 ImageView,我能够按照我想要的方式操作它的属性。在我的适配器上完成 notifyDataStateChanged() 以确保会发生更改。

旁注:我需要调用 getResources() 来改变我的 ImageView。不太清楚那是什么,我会在以后研究它。