[go: nahoru, domu]

1f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski/*
2f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Copyright (C) 2015 The Android Open Source Project
3f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
4f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Licensed under the Apache License, Version 2.0 (the "License");
5f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * you may not use this file except in compliance with the License.
6f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * You may obtain a copy of the License at
7f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
8f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *      http://www.apache.org/licenses/LICENSE-2.0
9f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
10f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Unless required by applicable law or agreed to in writing, software
11f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * distributed under the License is distributed on an "AS IS" BASIS,
12f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * See the License for the specific language governing permissions and
14f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * limitations under the License.
15f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski */
16f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
17f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskipackage android.support.percent;
18f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
19f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.content.Context;
20f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.content.res.TypedArray;
21f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.util.AttributeSet;
22f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.view.ViewGroup;
23f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskiimport android.widget.RelativeLayout;
24f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
25f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski/**
26f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * Subclass of {@link android.widget.RelativeLayout} that supports percentage based dimensions and
27f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * margins.
28f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
29f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * You can specify dimension or a margin of child by using attributes with "Percent" suffix. Follow
30f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * this example:
31f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
32f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <pre class="prettyprint">
33f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * &lt;android.support.percent.PercentRelativeLayout
34f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         xmlns:android="http://schemas.android.com/apk/res/android"
35f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         xmlns:app="http://schemas.android.com/apk/res-auto"
36f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         android:layout_width="match_parent"
37300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski *         android:layout_height="match_parent"&gt
38f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     &lt;ImageView
39f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         app:layout_widthPercent="50%"
40f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         app:layout_heightPercent="50%"
41f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         app:layout_marginTopPercent="25%"
42f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *         app:layout_marginLeftPercent="25%"/&gt
43b17223fee6f704203a441db2fbaaefc61fef91c5Andrew Solovay * &lt;/android.support.percent.PercentFrameLayout&gt
44f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * </pre>
45f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
46f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * The attributes that you can use are:
47f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * <ul>
48f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_widthPercent}
49f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_heightPercent}
50f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginPercent}
51f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginLeftPercent}
52f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginTopPercent}
53f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginRightPercent}
54f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginBottomPercent}
55f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginStartPercent}
56f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *     <li>{@code layout_marginEndPercent}
57300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski *     <li>{@code layout_aspectRatio}
58f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * </ul>
59f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski *
60f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * It is not necessary to specify {@code layout_width/height} if you specify {@code
61f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * layout_widthPercent.} However, if you want the view to be able to take up more space than what
62f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * percentage value permits, you can add {@code layout_width/height="wrap_content"}. In that case
63f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * if the percentage size is too small for the View's content, it will be resized using
64f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski * {@code wrap_content} rule.
65300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski *
66300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * <p>
67300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * You can also make one dimension be a fraction of the other by setting only width or height and
68300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * using {@code layout_aspectRatio} for the second one to be calculated automatically. For
69300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * example, if you would like to achieve 16:9 aspect ratio, you can write:
70300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * <pre class="prettyprint">
71300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski *     android:layout_width="300dp"
72300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski *     app:layout_aspectRatio="178%"
73300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * </pre>
74300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * This will make the aspect ratio 16:9 (1.78:1) with the width fixed at 300dp and height adjusted
75300da29db1ab98a0e0e1ac5bf15c836f40ebfd5fFilip Gruszczynski * accordingly.
76f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski */
77f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynskipublic class PercentRelativeLayout extends RelativeLayout {
78f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    private final PercentLayoutHelper mHelper = new PercentLayoutHelper(this);
79f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
80f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public PercentRelativeLayout(Context context) {
81f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        super(context);
82f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
83f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
84f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public PercentRelativeLayout(Context context, AttributeSet attrs) {
85f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        super(context, attrs);
86f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
87f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
88f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public PercentRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
89f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        super(context, attrs, defStyle);
90f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
91f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
92f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    @Override
931ddfd71aa6dd24a5f87f93c55dd774f5eb7320e4Bryce Lee    protected LayoutParams generateDefaultLayoutParams() {
941ddfd71aa6dd24a5f87f93c55dd774f5eb7320e4Bryce Lee        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
951ddfd71aa6dd24a5f87f93c55dd774f5eb7320e4Bryce Lee    }
961ddfd71aa6dd24a5f87f93c55dd774f5eb7320e4Bryce Lee
971ddfd71aa6dd24a5f87f93c55dd774f5eb7320e4Bryce Lee    @Override
98f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public LayoutParams generateLayoutParams(AttributeSet attrs) {
99f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        return new LayoutParams(getContext(), attrs);
100f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
101f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
102f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    @Override
103f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
104f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec);
105f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
106f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        if (mHelper.handleMeasuredStateTooSmall()) {
107f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
108f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
109f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
110f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
111f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    @Override
112f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
113f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        super.onLayout(changed, left, top, right, bottom);
114f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        mHelper.restoreOriginalParams();
115f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
116f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
117f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    public static class LayoutParams extends RelativeLayout.LayoutParams
118f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            implements PercentLayoutHelper.PercentLayoutParams {
119f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo;
120f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
121f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public LayoutParams(Context c, AttributeSet attrs) {
122f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            super(c, attrs);
123f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs);
124f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
125f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
126f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public LayoutParams(int width, int height) {
127f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            super(width, height);
128f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
129f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
130f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public LayoutParams(ViewGroup.LayoutParams source) {
131f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            super(source);
132f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
133f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
134f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public LayoutParams(MarginLayoutParams source) {
135f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            super(source);
136f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
137f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
138f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        @Override
139f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() {
140796a29bc6265696029863ec22ee753ff4065a8dbBryce Lee            if (mPercentLayoutInfo == null) {
141796a29bc6265696029863ec22ee753ff4065a8dbBryce Lee                mPercentLayoutInfo = new PercentLayoutHelper.PercentLayoutInfo();
142796a29bc6265696029863ec22ee753ff4065a8dbBryce Lee            }
143796a29bc6265696029863ec22ee753ff4065a8dbBryce Lee
144f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            return mPercentLayoutInfo;
145f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
146f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski
147f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        @Override
148f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
149f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski            PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr);
150f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski        }
151f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski    }
152f9cabe2ad76a19d555b5b656d8167bdb167c9d03Filip Gruszczynski}
153