使用GridLayoutManager增加RecyclerView中的单元格宽度

时间:2018-11-20 10:57:38

标签: android android-recyclerview gridlayoutmanager

我有一个RecyclerView,一个GridLayoutManager,一个spanCount=2,一个Vertical方向。

我的物品正确显示为下图:

现在,我需要添加一个动画,当单击其中一个项目(例如数字“ 3”)时,该项目会增加其宽度并将其旁边的项目(在本示例中为“ 4”)推到一部分在父级/屏幕之外。

从视觉上看,应该是这样的:

要展开该项目,我要将可见性设置为VISIBLE,并将其折叠到该项目内部的视图中,请将可见性设置为GONE

目前,我可以显示和隐藏该视图,但是它仅占用项目的空间,并且确实增加了将项目推向其旁边的宽度。

所以我的问题是:

  • 是否可以为此使用默认的GridLayoutManager?
  • 什么是实现这一目标的好方法?

2 个答案:

答案 0 :(得分:4)

可以按以下方式使用GridLayoutManager

  • 用两个跨度定义GridLayoutManager
  • 设置一个包含可点击视图和将设置为VISIBLEGONE的视图的项目布局。
  • 在适配器中,例如,单击左视图时,将可扩展视图设置为VISIBLE,将itemView的大小增加可扩展视图的宽度。通过扩展量将视图向右平移,以适应增加的左视图大小。
  • 进行一些内务处理,以确保重置回收的视图。

这里是一个例子。我假设只能单击左视图。如果也可以单击,则正确的视图的一般过程是相同的,但是细节不同,需要翻译的内容等。

此示例未保留扩展所涉及的视图状态信息,因此,如果您扩展视图然后向下滚动并向上备份,则该视图可能会重置。

enter image description here

MainActivity.java

public class MainActivity extends AppCompatActivity {  
    private LinearLayoutManager mLayoutManager;  
    private RecyclerViewAdapter mAdapter;  
    private List<String> mItems = new ArrayList<>();  
    private RecyclerView mRecycler;  

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

        for (int i = 0; i < 100; i++) {  
            mItems.add(i + 1 + "");  
        }  

        mLayoutManager = new GridLayoutManager(this, 2);  
        mRecycler = findViewById(R.id.recyclerView);  
        mAdapter = new RecyclerViewAdapter(mItems);  
        mRecycler.setLayoutManager(mLayoutManager);  
        mRecycler.setAdapter(mAdapter);  
    }  
}

RecyclerViewAdapter.java
该演示适配器假定要显示的项目数是偶数。为简单起见,未对空检查进行编码。

class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
    implements View.OnClickListener {
    private final List<String> mItems;
    private RecyclerView mRecyclerView;

    RecyclerViewAdapter(List<String> items) {
        mItems = items;
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
    }

    @Override
    public @NonNull
    RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ItemViewHolder vh = (ItemViewHolder) holder;

        vh.mItemTextView.setText(mItems.get(position));

        // Only allow clicks on left items which corresponds to even positions.
        vh.mItemTextView.setOnClickListener((position % 2 == 0) ? this : null);

        // Reset translation and expansion if viewholder is reused.
        vh.itemView.setTranslationX(0);
        if (vh.mExpansion != 0) {
            vh.itemView.getLayoutParams().width -= vh.mExpansion;
            vh.mExpansion = 0;
            vh.mGoneView.setVisibility(View.GONE);
        }

        int bgColor = (position % 2 == 0)
            ? android.R.color.holo_blue_light
            : android.R.color.holo_green_light;
        vh.mItemTextView.setBackgroundColor(vh.itemView.getContext().getResources().getColor(bgColor));
    }

    @Override
    public int getItemCount() {
        return (mItems == null) ? 0 : mItems.size();
    }

    @Override
    public int getItemViewType(int position) {
        return TYPE_ITEM;
    }

    @Override
    public void onClick(View v) {
        ItemViewHolder vh = (ItemViewHolder) mRecyclerView.findContainingViewHolder(v);
        View itemView = vh.itemView;

        // Get the child to the right. This child will be translated to the right to make room
        // for the expanded left view.
        View rightChild = mRecyclerView.getChildAt(findRightChildPos(vh.itemView));
        if (vh.mGoneView.getVisibility() == View.GONE) {
            // Reveal the "GONE" view, expand the itemView and translate the right-hand view.
            vh.mGoneView.setVisibility(View.VISIBLE);
            int translation = vh.mGoneView.getLayoutParams().width;
            itemView.getLayoutParams().width = itemView.getWidth() + translation;

            // Works with "GONE" view of fixed width. Make adjustments if width is variable.
            rightChild.setTranslationX(translation);
            vh.mExpansion = translation;
        } else { // View is expanded.
            // Undo the expansion changes.
            vh.mGoneView.setVisibility(View.GONE);
            itemView.getLayoutParams().width = itemView.getWidth() - vh.mExpansion;
            vh.mExpansion = 0;
            rightChild.setTranslationX(0);
        }
    }

    // Find the child to the right of a view within the RecyclerView.
    private int findRightChildPos(View view) {
        for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
            if (mRecyclerView.getChildAt(i) == view) {
                return i + 1;
            }
        }
        return RecyclerView.NO_POSITION;
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        final TextView mItemTextView;
        final View mGoneView;
        int mExpansion;

        ItemViewHolder(View item) {
            super(item);
            mItemTextView = item.findViewById(R.id.textView);
            mGoneView = item.findViewById(R.id.expandingView);
        }
    }

    private final static int TYPE_ITEM = 1;
}

recycler_item.xml

<LinearLayout 
    android:id="@+id/item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:clickable="true"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:textSize="48sp"
        tools:background="@android:color/holo_blue_light"
        tools:text="1" />

    <View
        android:id="@+id/expandingView"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:background="@android:color/holo_purple"
        android:visibility="gone" />

    <View
        android:layout_width="10dp"
        android:layout_height="match_parent"
        android:background="@android:color/holo_red_light" />
</LinearLayout>

答案 1 :(得分:0)

我看到了如何使用带有LinearLayoutManager的Horizo​​ntalScrollView / RecyclerView来实现这一点。可以将LinearLayoutManager与以下视图一起使用,而不是将GridLayoutManager与两列一起使用:

__|HorizontalScrollView/RecyclerView| | [Firts view] [Second view] | |---------------------------------|

然后实现扩展视图很简单。

在其他情况下,您将需要自定义布局管理器,该管理器可以水平和垂直滚动。