/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.percent;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.FrameLayout;
/**
* Subclass of {@link android.widget.FrameLayout} that supports percentage based dimensions and
* margins.
*
* You can specify dimension or a margin of child by using attributes with "Percent" suffix. Follow
* this example:
*
* <pre class="prettyprint">
* <android.support.percent.PercentFrameLayout
* xmlns:android="http://schemas.android.com/apk/res/android"
* xmlns:app="http://schemas.android.com/apk/res-auto"
* android:layout_width="match_parent"
* android:layout_height="match_parent"/>
* <ImageView
* app:layout_widthPercent="50%"
* app:layout_heightPercent="50%"
* app:layout_marginTopPercent="25%"
* app:layout_marginLeftPercent="25%"/>
* </android.support.percent.PercentFrameLayout/>
* </pre>
*
* The attributes that you can use are:
* <ul>
* <li>{@code layout_widthPercent}
* <li>{@code layout_heightPercent}
* <li>{@code layout_marginPercent}
* <li>{@code layout_marginLeftPercent}
* <li>{@code layout_marginTopPercent}
* <li>{@code layout_marginRightPercent}
* <li>{@code layout_marginBottomPercent}
* <li>{@code layout_marginStartPercent}
* <li>{@code layout_marginEndPercent}
* </ul>
*
* It is not necessary to specify {@code layout_width/height} if you specify {@code
* layout_widthPercent.} However, if you want the view to be able to take up more space than what
* percentage value permits, you can add {@code layout_width/height="wrap_content"}. In that case
* if the percentage size is too small for the View's content, it will be resized using
* {@code wrap_content} rule.
*/
public class PercentFrameLayout extends FrameLayout {
private final PercentLayoutHelper mHelper = new PercentLayoutHelper(this);
public PercentFrameLayout(Context context) {
super(context);
}
public PercentFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PercentFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mHelper.handleMeasuredStateTooSmall()) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mHelper.restoreOriginalParams();
}
public static class LayoutParams extends FrameLayout.LayoutParams
implements PercentLayoutHelper.PercentLayoutParams {
private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(int width, int height, int gravity) {
super(width, height, gravity);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
public LayoutParams(FrameLayout.LayoutParams source) {
super((MarginLayoutParams) source);
gravity = source.gravity;
}
public LayoutParams(LayoutParams source) {
this((FrameLayout.LayoutParams) source);
mPercentLayoutInfo = source.mPercentLayoutInfo;
}
@Override
public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() {
if (mPercentLayoutInfo == null) {
mPercentLayoutInfo = new PercentLayoutHelper.PercentLayoutInfo();
}
return mPercentLayoutInfo;
}
@Override
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr);
}
}
}