Increase cell width in a RecyclerView with GridLayoutManager












6















I have a RecyclerView with a GridLayoutManager with spanCount=2 and a Vertical orientation.



My items are correctly displayed as the image below:





Now I need to add an animation that when a click on one of the items, let's say number "3", that item increases its width and push the item next to it (in this example, number "4") partially outside the parent/screen.



Visually, it would be something like this:





To expand the item I am setting the visibility to VISIBLE to a view inside the item and to collapse it, set the visibility to GONE.



At the moment, I am able to show and hide that view, but it only takes the space of the item, it does increase the width pushing the item next to it.



So my questions are:




  • Is this possible to use the default GridLayoutManager for this?

  • What would be a good approach to achieve this?










share|improve this question





























    6















    I have a RecyclerView with a GridLayoutManager with spanCount=2 and a Vertical orientation.



    My items are correctly displayed as the image below:





    Now I need to add an animation that when a click on one of the items, let's say number "3", that item increases its width and push the item next to it (in this example, number "4") partially outside the parent/screen.



    Visually, it would be something like this:





    To expand the item I am setting the visibility to VISIBLE to a view inside the item and to collapse it, set the visibility to GONE.



    At the moment, I am able to show and hide that view, but it only takes the space of the item, it does increase the width pushing the item next to it.



    So my questions are:




    • Is this possible to use the default GridLayoutManager for this?

    • What would be a good approach to achieve this?










    share|improve this question



























      6












      6








      6


      1






      I have a RecyclerView with a GridLayoutManager with spanCount=2 and a Vertical orientation.



      My items are correctly displayed as the image below:





      Now I need to add an animation that when a click on one of the items, let's say number "3", that item increases its width and push the item next to it (in this example, number "4") partially outside the parent/screen.



      Visually, it would be something like this:





      To expand the item I am setting the visibility to VISIBLE to a view inside the item and to collapse it, set the visibility to GONE.



      At the moment, I am able to show and hide that view, but it only takes the space of the item, it does increase the width pushing the item next to it.



      So my questions are:




      • Is this possible to use the default GridLayoutManager for this?

      • What would be a good approach to achieve this?










      share|improve this question
















      I have a RecyclerView with a GridLayoutManager with spanCount=2 and a Vertical orientation.



      My items are correctly displayed as the image below:





      Now I need to add an animation that when a click on one of the items, let's say number "3", that item increases its width and push the item next to it (in this example, number "4") partially outside the parent/screen.



      Visually, it would be something like this:





      To expand the item I am setting the visibility to VISIBLE to a view inside the item and to collapse it, set the visibility to GONE.



      At the moment, I am able to show and hide that view, but it only takes the space of the item, it does increase the width pushing the item next to it.



      So my questions are:




      • Is this possible to use the default GridLayoutManager for this?

      • What would be a good approach to achieve this?







      android android-recyclerview gridlayoutmanager






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 '18 at 11:04









      Ali

      1




      1










      asked Nov 20 '18 at 10:57









      ampamp

      4,10195298




      4,10195298
























          2 Answers
          2






          active

          oldest

          votes


















          4





          +200









          It is possible to useGridLayoutManager as follows:




          • Define the GridLayoutManager with two spans.

          • Set up an item layout that incorporates the clickable view and the view that will be set to VISIBLE and GONE.

          • In the adapter, when, say, the left view is clicked, set the expandable view to VISIBLE, increase the size of the itemView by the width of the expandable view. Translate the view to the right by the amount of the expansion to accommodate the increased size of the left view.

          • Do some housekeeping to make sure that recycled views are reset.


          Here is an example. I assume that only the left view can be clicked. The general process is the same for the right view if if it can also be clicked, but the details differ in what needs to be translated, etc.



          This example does not retained information of the status of view that are involved in an expansion, so if you expand a view then scroll down and back up, the view may be reset.



          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

          This demo adapter assumes that there are an even number of items to display. For simplicity, null checks have not been coded.



          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>





          share|improve this answer


























          • Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

            – amp
            Nov 27 '18 at 11:09






          • 1





            @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

            – Cheticamp
            Nov 27 '18 at 11:45



















          0














          I see how to implement this using HorizontalScrollView/RecyclerView with LinearLayoutManager. Instead of using GridLayoutManager with two columns you can use LinearLayoutManager with such views:



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



          Then it's trivial to implement expanded views.



          In other case you'll need custom layout manager, which can scroll horizontally and vertically.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53391494%2fincrease-cell-width-in-a-recyclerview-with-gridlayoutmanager%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            4





            +200









            It is possible to useGridLayoutManager as follows:




            • Define the GridLayoutManager with two spans.

            • Set up an item layout that incorporates the clickable view and the view that will be set to VISIBLE and GONE.

            • In the adapter, when, say, the left view is clicked, set the expandable view to VISIBLE, increase the size of the itemView by the width of the expandable view. Translate the view to the right by the amount of the expansion to accommodate the increased size of the left view.

            • Do some housekeeping to make sure that recycled views are reset.


            Here is an example. I assume that only the left view can be clicked. The general process is the same for the right view if if it can also be clicked, but the details differ in what needs to be translated, etc.



            This example does not retained information of the status of view that are involved in an expansion, so if you expand a view then scroll down and back up, the view may be reset.



            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

            This demo adapter assumes that there are an even number of items to display. For simplicity, null checks have not been coded.



            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>





            share|improve this answer


























            • Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

              – amp
              Nov 27 '18 at 11:09






            • 1





              @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

              – Cheticamp
              Nov 27 '18 at 11:45
















            4





            +200









            It is possible to useGridLayoutManager as follows:




            • Define the GridLayoutManager with two spans.

            • Set up an item layout that incorporates the clickable view and the view that will be set to VISIBLE and GONE.

            • In the adapter, when, say, the left view is clicked, set the expandable view to VISIBLE, increase the size of the itemView by the width of the expandable view. Translate the view to the right by the amount of the expansion to accommodate the increased size of the left view.

            • Do some housekeeping to make sure that recycled views are reset.


            Here is an example. I assume that only the left view can be clicked. The general process is the same for the right view if if it can also be clicked, but the details differ in what needs to be translated, etc.



            This example does not retained information of the status of view that are involved in an expansion, so if you expand a view then scroll down and back up, the view may be reset.



            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

            This demo adapter assumes that there are an even number of items to display. For simplicity, null checks have not been coded.



            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>





            share|improve this answer


























            • Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

              – amp
              Nov 27 '18 at 11:09






            • 1





              @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

              – Cheticamp
              Nov 27 '18 at 11:45














            4





            +200







            4





            +200



            4




            +200





            It is possible to useGridLayoutManager as follows:




            • Define the GridLayoutManager with two spans.

            • Set up an item layout that incorporates the clickable view and the view that will be set to VISIBLE and GONE.

            • In the adapter, when, say, the left view is clicked, set the expandable view to VISIBLE, increase the size of the itemView by the width of the expandable view. Translate the view to the right by the amount of the expansion to accommodate the increased size of the left view.

            • Do some housekeeping to make sure that recycled views are reset.


            Here is an example. I assume that only the left view can be clicked. The general process is the same for the right view if if it can also be clicked, but the details differ in what needs to be translated, etc.



            This example does not retained information of the status of view that are involved in an expansion, so if you expand a view then scroll down and back up, the view may be reset.



            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

            This demo adapter assumes that there are an even number of items to display. For simplicity, null checks have not been coded.



            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>





            share|improve this answer















            It is possible to useGridLayoutManager as follows:




            • Define the GridLayoutManager with two spans.

            • Set up an item layout that incorporates the clickable view and the view that will be set to VISIBLE and GONE.

            • In the adapter, when, say, the left view is clicked, set the expandable view to VISIBLE, increase the size of the itemView by the width of the expandable view. Translate the view to the right by the amount of the expansion to accommodate the increased size of the left view.

            • Do some housekeeping to make sure that recycled views are reset.


            Here is an example. I assume that only the left view can be clicked. The general process is the same for the right view if if it can also be clicked, but the details differ in what needs to be translated, etc.



            This example does not retained information of the status of view that are involved in an expansion, so if you expand a view then scroll down and back up, the view may be reset.



            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

            This demo adapter assumes that there are an even number of items to display. For simplicity, null checks have not been coded.



            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>






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 26 '18 at 3:14

























            answered Nov 25 '18 at 19:42









            CheticampCheticamp

            29.4k43063




            29.4k43063













            • Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

              – amp
              Nov 27 '18 at 11:09






            • 1





              @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

              – Cheticamp
              Nov 27 '18 at 11:45



















            • Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

              – amp
              Nov 27 '18 at 11:09






            • 1





              @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

              – Cheticamp
              Nov 27 '18 at 11:45

















            Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

            – amp
            Nov 27 '18 at 11:09





            Thank you, that is a great starting point. I just have one problem. If the expandable view is on the right, if I change the width of the itemView like itemView.getLayoutParams().width = itemView.getWidth() + translation;, the width will increase to the right, instead of growing to the left? Is that true?

            – amp
            Nov 27 '18 at 11:09




            1




            1





            @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

            – Cheticamp
            Nov 27 '18 at 11:45





            @amp The view will grow to the right. You will then need to do some translations to the left to make the itemView shows completely. The itemView in the left-hand column will also need to shift to the left.

            – Cheticamp
            Nov 27 '18 at 11:45













            0














            I see how to implement this using HorizontalScrollView/RecyclerView with LinearLayoutManager. Instead of using GridLayoutManager with two columns you can use LinearLayoutManager with such views:



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



            Then it's trivial to implement expanded views.



            In other case you'll need custom layout manager, which can scroll horizontally and vertically.






            share|improve this answer




























              0














              I see how to implement this using HorizontalScrollView/RecyclerView with LinearLayoutManager. Instead of using GridLayoutManager with two columns you can use LinearLayoutManager with such views:



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



              Then it's trivial to implement expanded views.



              In other case you'll need custom layout manager, which can scroll horizontally and vertically.






              share|improve this answer


























                0












                0








                0







                I see how to implement this using HorizontalScrollView/RecyclerView with LinearLayoutManager. Instead of using GridLayoutManager with two columns you can use LinearLayoutManager with such views:



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



                Then it's trivial to implement expanded views.



                In other case you'll need custom layout manager, which can scroll horizontally and vertically.






                share|improve this answer













                I see how to implement this using HorizontalScrollView/RecyclerView with LinearLayoutManager. Instead of using GridLayoutManager with two columns you can use LinearLayoutManager with such views:



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



                Then it's trivial to implement expanded views.



                In other case you'll need custom layout manager, which can scroll horizontally and vertically.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 23 '18 at 9:51









                Konstantin BerkowKonstantin Berkow

                60611122




                60611122






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53391494%2fincrease-cell-width-in-a-recyclerview-with-gridlayoutmanager%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Wiesbaden

                    Marschland

                    Dieringhausen