从适配器外部控制RecyclerView膨胀视图:保持选择状态

时间:2017-10-19 14:02:05

标签: android android-recyclerview android-view recycler-adapter photo-gallery

一般

我想从ViewHolder和RecyclerView类之外控制我的RecyclerView的 ViewHolder膨胀视图。换句话说,我希望从其他方法/类中控制这些视图。

我的案例(例子)

在我的具体案例中,我制作了一个照片库活动,允许用户对每个充气视图进行选择和取消选择,通过突出显示选择哪些项目。

selection

现在,用户可以通过单击每个生成的对象/视图来完成此操作;然后,由于“setOnClickListener”和“setOnLongClickListener”方法可以对RecyclerView / adapter的特定子项执行操作,这些方法在 里面 ViewHolder类中执行相应的操作。 / p>

但是当重新启动活动时(即设备轮换),选择会丢失,用户应该再次执行选择(即删除照片)。

selection lost

假设所选照片的​​位置保留(例如通过捆绑,或通过数组),可以在重新启动活动后恢复适配器视图上的选择(即突出显示相应的项目/视图)?如果是,怎么样?

一些代码

下面的代码包含Recyclerview类和AdapterView类,它们都是活动类的子类。

private class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder>  {

    private ArrayList<PhotoObject.PhotoElement> photoAL;
    private Context mContext;
    public ImageGalleryAdapter(Context context, ArrayList<PhotoObject.PhotoElement> photosToPreviewInGallery) {
        mContext = context;
        photoAL = photosToPreviewInGallery;
    }

    @Override
    public ImageGalleryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);

        // Inflate the layout
        View itemView = inflater.inflate(R.layout.item_photo, parent, false);

        ImageGalleryAdapter.MyViewHolder viewHolder = new ImageGalleryAdapter.MyViewHolder(itemView);
        // Retrieving the itemView
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ImageGalleryAdapter.MyViewHolder holder, int position) {

        PhotoObject.PhotoElement previewPhotoInGallery = photoAL.get(position);
        ImageView imageView = holder.mPhotoImageView;

        GlideApp.with(mContext)
                .load(previewPhotoInGallery.getUrl())
                .placeholder(R.drawable.ic_cloud_off_red)
                .into(imageView);
    }

    //The method which gives back the number of items to load as photo.
    @Override
    public int getItemCount() {
        return (photoAL.size());
    }

    // The class that assigns a view holder for each Image and checkbox in the RecyclerView.
    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

        public ImageView mPhotoImageView;
        public CheckBox mPhotoCheckBox;
        public MyViewHolder(View item_view) {

            super(item_view);
            mPhotoImageView = (ImageView) item_view.findViewById(R.id.item_photo_iv);
            mPhotoCheckBox = (CheckBox) item_view.findViewById(R.id.item_photo_checkbox);

            item_view.setOnClickListener(this);
            item_view.setOnLongClickListener(this);

            // Retrieving the item_view
        }

        // The method for managing the click on an image.
        @Override
        public void onClick(View view) {
            itemSelection(view);
        }

        // Manages the selection of the items.
        private void itemSelection(View item) {
            // Retrieving the item

            int position = getAdapterPosition();

            if (position != RecyclerView.NO_POSITION) {
                if (!item.isSelected()) {
                    // Add clicked item to the selected ones
                    MultiPhotoShootingActivity.manageSelection(true, position);

                    // Visually highlighting the ImageView
                    item.setSelected(true);
                    mPhotoCheckBox.setChecked(true);
                    mPhotoCheckBox.setVisibility(View.VISIBLE);
                } else {
                    // Remove clicked item from the selected ones
                    MultiPhotoShootingActivity.manageSelection(false, position);

                    // Removing the visual highlights on the ImageView
                    item.setSelected(false);
                    mPhotoCheckBox.setChecked(false);
                    mPhotoCheckBox.setVisibility(View.INVISIBLE);
                }
            }
        }

        // The method for managing the long click on an image.
        @Override
        public boolean onLongClick(View view) {

            int position = getAdapterPosition();
            if(position != RecyclerView.NO_POSITION) {
                Intent intent = new Intent(mContext, PhotoDetail.class);
                intent.putExtra("KEY4URL", activityPhotoObject.getPath(position));
                startActivity(intent);
            }

            // return true to indicate that the click was handled (if you return false onClick will be triggered too)
            return true;
        }
    }

}

感谢您的时间。

3 个答案:

答案 0 :(得分:1)

你不应该&#34;控制&#34;适配器外部的视图。而是在您的活动中覆盖onSaveState和onRestoreState。在将适配器传递给适配器时,在适配器中使用相同的方法以保存状态。保存选择到捆绑中的整数位置数组(您传递到适配器中)。以相应的方式,您可以从“还原”状态包中获取所选位置的数组。

活性:

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState){
          adapter.onRestoreInstanceState(savedInstanceState);
}
适配器中的

public void onRestoreInstanceState(Bundle state){
    selectedItemsArray = state.getIntArray("my_array_key")
}

答案 1 :(得分:0)

@Alessandro

您可以自己处理Runtime changes

在您的清单中,您可以定义您的活动将自行处理的更改,并且不会重新启动。

  

机器人:configChanges = “取向| keyboardHidden”

之后,您必须在活动中使用此方法处理在清单中声明的​​配置更改:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // Do your thing
    } 
}

答案 2 :(得分:0)

解决

找出解决问题的方法我必须完成两项小任务:

  • 保存并恢复所选项目选择状态(例如,通过数组,由@Inkognito帮助建议);
  • 根据RecyclerView内的位置检索应用选择的视图。

所以,我不得不修改一些代码 在继续之前,我想指出Activity类有一个子类,即Adapter类(名为ImageGalleryAdapter);反过来,Adapter子类有自己的子类,即ViewHolder类(名为MyViewHolder)。
所以:Activity类 - &gt; Adapter类 - &gt; ViewHolder

在父类(activity类中修改的代码,其中RecyclerView

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    adapter.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    adapter.onRestoreInstanceState(savedInstanceState);
}

onSaveInstanceStateonRestoreInstanceState方法中,我添加了用于保存和恢复&#34;适配器&#34;的实例状态的引用。子类。

在适配器类中添加的代码(在RecyclerView类中)

    private boolean [] selectedItemsArray;
    private void onSaveInstanceState(Bundle outState) {
        outState.putBooleanArray("my_array_key" , selectedItemsArray = mpsaPO.getItemsSelected());
    }

    private void onRestoreInstanceState(Bundle state) {
        if (state != null) {
            selectedItemsArray = state.getBooleanArray("my_array_key");
        }
    }

selectedItemsArray是一个布尔数组,其中包含选择RecyclerView元素的信息(true =选中; false =未选中)。
然后,在保存的实例中添加此元素并通过活动类检索,使应用程序能够知道在重新创建活动之后选择的视图。

在onBindViewHolder方法中添加了代码,该方法位于适配器类

        if (selectedItemsArray != null) {
            if (selectedItemsArray[position]) {
                holder.itemView.setSelected(true);
                holder.mPhotoCheckBox.setChecked(true);
                holder.mPhotoCheckBox.setVisibility(View.VISIBLE);
            }
        }

使用最后一部分代码,我们将根据在保存活动之前选择的项目/视图将选择应用于相应的视图。 holer对象包含itemViewmPhotoCheckBox个对象,我们可以在其上执行选择。