14143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
34143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *
44143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
54143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * you may not use this file except in compliance with the License.
64143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * You may obtain a copy of the License at
74143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *
84143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
94143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *
104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * Unless required by applicable law or agreed to in writing, software
114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
124143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * See the License for the specific language governing permissions and
144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * limitations under the License.
154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar */
16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget;
174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL;
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL;
204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.content.Context;
224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.graphics.Color;
234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.util.AttributeSet;
244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.view.View;
254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.view.ViewGroup;
264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
27c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.annotation.NonNull;
28c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.core.util.Pair;
29c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas
308a11e6829c522aa1efcc903afa4c01d337082eabChris Craikimport org.hamcrest.BaseMatcher;
318a11e6829c522aa1efcc903afa4c01d337082eabChris Craikimport org.hamcrest.Description;
328a11e6829c522aa1efcc903afa4c01d337082eabChris Craik
334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.ArrayList;
344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.Collections;
354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.List;
364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.concurrent.atomic.AtomicLong;
374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
384143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarabstract public class BaseWrapContentWithAspectRatioTest extends BaseRecyclerViewInstrumentationTest {
394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    final BaseWrapContentTest.WrapContentConfig mWrapContentConfig;
404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    protected BaseWrapContentWithAspectRatioTest(
424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            BaseWrapContentTest.WrapContentConfig wrapContentConfig) {
434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mWrapContentConfig = wrapContentConfig;
444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    int getSize(View view, int orientation) {
474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        if (orientation == VERTICAL) {
484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return view.getHeight();
494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        return view.getWidth();
514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class LoggingView extends View {
544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        MeasureBehavior mBehavior;
564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void setBehavior(MeasureBehavior behavior) {
584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mBehavior = behavior;
594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public LoggingView(Context context) {
624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super(context);
634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public LoggingView(Context context, AttributeSet attrs) {
664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super(context, attrs);
674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public LoggingView(Context context, AttributeSet attrs, int defStyleAttr) {
704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super(context, attrs, defStyleAttr);
714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public LoggingView(Context context, AttributeSet attrs, int defStyleAttr,
744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                int defStyleRes) {
754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super(context, attrs, defStyleAttr, defStyleRes);
764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mBehavior.onMeasure(this, widthMeasureSpec, heightMeasureSpec);
814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super.onLayout(changed, left, top, right, bottom);
864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mBehavior.onLayout(changed, left, top, right, bottom);
874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void setMeasured(int w, int h) {
904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            setMeasuredDimension(w, h);
914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
934143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void prepareLayoutParams() {
944143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mBehavior.setLayoutParams(this);
954143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class AspectRatioMeasureBehavior extends MeasureBehavior {
994143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1004143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Float ratio;
1014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int control;
1024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public AspectRatioMeasureBehavior(int desiredW, int desiredH, int wMode, int hMode) {
1044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super(desiredW, desiredH, wMode, hMode);
1054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public AspectRatioMeasureBehavior aspectRatio(int control, float ratio) {
1084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.control = control;
1094143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.ratio = ratio;
1104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return this;
1114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1124143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1134143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
1144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void onMeasure(LoggingView view, int wSpec,
1154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                int hSpec) {
1164143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super.onMeasure(view, wSpec, hSpec);
1174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (control == VERTICAL) {
1184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                view.setMeasured(getSecondary(view.getMeasuredHeight()),
1194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                        view.getMeasuredHeight());
1204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            } else if (control == HORIZONTAL) {
1214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                view.setMeasured(view.getMeasuredWidth(),
1224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                        getSecondary(view.getMeasuredWidth()));
1234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
1244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public int getSecondary(int controlSize) {
1274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return (int) (controlSize * ratio);
1284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
1304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class MeasureBehavior {
1324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private static final AtomicLong idCounter = new AtomicLong(0);
1334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public List<Pair<Integer, Integer>> measureSpecs = new ArrayList<>();
1344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public List<Pair<Integer, Integer>> layouts = new ArrayList<>();
1354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int desiredW, desiredH;
1364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        final long mId = idCounter.incrementAndGet();
1374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
138de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar        ViewGroup.MarginLayoutParams layoutParams;
1394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public MeasureBehavior(int desiredW, int desiredH, int wMode, int hMode) {
1414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.desiredW = desiredW;
1424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.desiredH = desiredH;
143de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar            layoutParams = new ViewGroup.MarginLayoutParams(
1444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    wMode, hMode
1454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            );
1464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
148de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar        public MeasureBehavior withMargins(int left, int top, int right, int bottom) {
149de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar            layoutParams.leftMargin = left;
150de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar            layoutParams.topMargin = top;
151de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar            layoutParams.rightMargin = right;
152de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar            layoutParams.bottomMargin = bottom;
153de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar            return this;
154de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar        }
155de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar
1564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public long getId() {
1574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return mId;
1584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void onMeasure(LoggingView view, int wSpec, int hSpec) {
1614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            measureSpecs.add(new Pair<>(wSpec, hSpec));
1624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            view.setMeasured(
1634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    RecyclerView.LayoutManager.chooseSize(wSpec, desiredW, 0),
1644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    RecyclerView.LayoutManager.chooseSize(hSpec, desiredH, 0));
1654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public int getSpec(int position, int orientation) {
1684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (orientation == VERTICAL) {
1694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return measureSpecs.get(position).second;
1704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            } else {
1714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return measureSpecs.get(position).first;
1724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
1734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void setLayoutParams(LoggingView view) {
1764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            view.setLayoutParams(layoutParams);
1774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void onLayout(boolean changed, int left, int top, int right, int bottom) {
1804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (changed) {
1814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                layouts.add(new Pair<>(right - left, bottom - top));
1824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
1834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
1854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class WrapContentViewHolder extends RecyclerView.ViewHolder {
1884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        LoggingView mView;
1904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public WrapContentViewHolder(ViewGroup parent) {
1924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            super(new LoggingView(parent.getContext()));
1934143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mView = (LoggingView) itemView;
1944143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mView.setBackgroundColor(Color.GREEN);
1954143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
1974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class WrapContentAdapter extends RecyclerView.Adapter<WrapContentViewHolder> {
1994143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2004143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        List<MeasureBehavior> behaviors = new ArrayList<>();
2014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public WrapContentAdapter(MeasureBehavior... behaviors) {
2034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Collections.addAll(this.behaviors, behaviors);
2044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
2078a11e6829c522aa1efcc903afa4c01d337082eabChris Craik        public WrapContentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
2084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return new WrapContentViewHolder(parent);
2094143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
2128a11e6829c522aa1efcc903afa4c01d337082eabChris Craik        public void onBindViewHolder(@NonNull WrapContentViewHolder holder, int position) {
2134143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            holder.mView.setBehavior(behaviors.get(position));
2144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            holder.mView.prepareLayoutParams();
2154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2164143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
2184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public int getItemCount() {
2194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return behaviors.size();
2204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
2224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class MeasureSpecMatcher extends BaseMatcher<Integer> {
2244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private boolean checkSize = false;
2264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private boolean checkMode = false;
2274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private int mSize;
2284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private int mMode;
2294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public static MeasureSpecMatcher is(int size, int mode) {
2314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            MeasureSpecMatcher matcher = new MeasureSpecMatcher(size, mode);
2324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            matcher.checkSize = true;
2334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            matcher.checkMode = true;
2344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return matcher;
2354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public static MeasureSpecMatcher size(int size) {
2384143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            MeasureSpecMatcher matcher = new MeasureSpecMatcher(size, 0);
2394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            matcher.checkSize = true;
2404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            matcher.checkMode = false;
2414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return matcher;
2424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public static MeasureSpecMatcher mode(int mode) {
2454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            MeasureSpecMatcher matcher = new MeasureSpecMatcher(0, mode);
2464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            matcher.checkSize = false;
2474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            matcher.checkMode = true;
2484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return matcher;
2494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private MeasureSpecMatcher(int size, int mode) {
2524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mSize = size;
2534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mMode = mode;
2544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
2584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public boolean matches(Object item) {
2594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (item == null) {
2604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return false;
2614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Integer intValue = (Integer) item;
2634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            final int size = View.MeasureSpec.getSize(intValue);
2644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            final int mode = View.MeasureSpec.getMode(intValue);
2654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (checkSize && size != mSize) {
2664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return false;
2674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (checkMode && mode != mMode) {
2694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return false;
2704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return true;
2724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
2754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void describeMismatch(Object item, Description description) {
2764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Integer intValue = (Integer) item;
2774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            final int size = View.MeasureSpec.getSize(intValue);
2784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            final int mode = View.MeasureSpec.getMode(intValue);
2794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (checkSize && size != mSize) {
2804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                description.appendText(" Expected size was ").appendValue(mSize)
2814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                        .appendText(" but received size is ").appendValue(size);
2824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (checkMode && mode != mMode) {
2844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                description.appendText(" Expected mode was ").appendValue(modeName(mMode))
2854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                        .appendText(" but received mode is ").appendValue(modeName(mode));
2864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
2904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void describeTo(Description description) {
2914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (checkSize) {
2924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                description.appendText(" Measure spec size:").appendValue(mSize);
2934143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2944143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (checkMode) {
2954143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                description.appendText(" Measure spec mode:").appendValue(modeName(mMode));
2964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2994143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private static String modeName(int mode) {
3004143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            switch (mode) {
3014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                case View.MeasureSpec.AT_MOST:
3024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    return "at most";
3034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                case View.MeasureSpec.EXACTLY:
3044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    return "exactly";
3054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                default:
3064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    return "unspecified";
3074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3094143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
3104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar}
311