1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.support.v7.widget;
17
18import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
19import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
20
21import static org.junit.Assert.assertEquals;
22import static org.junit.Assert.assertTrue;
23
24import android.graphics.Rect;
25import android.view.View;
26import android.view.ViewGroup;
27
28import org.junit.Test;
29import org.junit.runner.RunWith;
30import org.junit.runners.Parameterized;
31
32import java.util.ArrayList;
33import java.util.List;
34
35@RunWith(Parameterized.class)
36public class GridLayoutManagerCustomSizeInScrollDirectionTest extends BaseGridLayoutManagerTest {
37    @Parameterized.Parameters(name = "addDecorOffsets:{1} addMargins:{2} config:{0}")
38    public static List<Object[]> getParams() {
39        List<Object[]> params = new ArrayList<>();
40        Boolean[] options = new Boolean[]{true, false};
41        for (boolean addMargins : options) {
42            for (boolean addDecorOffsets : options) {
43                params.add(new Object[] {
44                        new Config(3, HORIZONTAL, false), addDecorOffsets, addMargins});
45                params.add(new Object[] {
46                        new Config(3, VERTICAL, false), addDecorOffsets, addMargins});
47            }
48        }
49        return params;
50    }
51
52    private final boolean mAddDecorOffsets;
53    private final boolean mAddMargins;
54    private final Config mConfig;
55
56    public GridLayoutManagerCustomSizeInScrollDirectionTest(Config config, boolean addDecorOffsets,
57            boolean addMargins) {
58        mConfig = config;
59        mAddDecorOffsets = addDecorOffsets;
60        mAddMargins = addMargins;
61    }
62
63    @Test
64    public void customSizeInScrollDirectionTest() throws Throwable {
65        final int decorOffset = mAddDecorOffsets ? 7 : 0;
66        final int margin = mAddMargins ? 11 : 0;
67        final int[] sizePerPosition = new int[]{3, 5, 9, 21, 3, 5, 9, 6, 9, 1};
68        final int[] expectedSizePerPosition = new int[]{9, 9, 9, 21, 3, 5, 9, 9, 9, 1};
69
70        final GridTestAdapter testAdapter = new GridTestAdapter(10) {
71            @Override
72            public void onBindViewHolder(TestViewHolder holder,
73                    int position) {
74                super.onBindViewHolder(holder, position);
75                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)
76                        holder.itemView.getLayoutParams();
77                if (layoutParams == null) {
78                    layoutParams = new ViewGroup.MarginLayoutParams(
79                            ViewGroup.LayoutParams.WRAP_CONTENT,
80                            ViewGroup.LayoutParams.WRAP_CONTENT);
81                    holder.itemView.setLayoutParams(layoutParams);
82                }
83                final int size = sizePerPosition[position];
84                if (mConfig.mOrientation == HORIZONTAL) {
85                    layoutParams.width = size;
86                    layoutParams.leftMargin = margin;
87                    layoutParams.rightMargin = margin;
88                } else {
89                    layoutParams.height = size;
90                    layoutParams.topMargin = margin;
91                    layoutParams.bottomMargin = margin;
92                }
93            }
94        };
95        testAdapter.setFullSpan(3, 5);
96        final RecyclerView rv = setupBasic(mConfig, testAdapter);
97        if (mAddDecorOffsets) {
98            rv.addItemDecoration(new RecyclerView.ItemDecoration() {
99                @Override
100                public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
101                        RecyclerView.State state) {
102                    if (mConfig.mOrientation == HORIZONTAL) {
103                        outRect.set(decorOffset, 0, decorOffset, 0);
104                    } else {
105                        outRect.set(0, decorOffset, 0, decorOffset);
106                    }
107                }
108            });
109        }
110        waitForFirstLayout(rv);
111
112        assertTrue("[test sanity] some views should be laid out",
113                mRecyclerView.getChildCount() > 0);
114        for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
115            View child = mRecyclerView.getChildAt(i);
116            final int size = mConfig.mOrientation == HORIZONTAL ? child.getWidth()
117                    : child.getHeight();
118            assertEquals("child " + i + " should have the size specified in its layout params",
119                    expectedSizePerPosition[i], size);
120        }
121        checkForMainThreadException();
122    }
123}
124