public class

ScaleFrameLayout

extends FrameLayout

 java.lang.Object

↳FrameLayout

↳androidx.leanback.widget.ScaleFrameLayout

Gradle dependencies

compile group: 'androidx.leanback', name: 'leanback', version: '1.2.0-alpha02'

  • groupId: androidx.leanback
  • artifactId: leanback
  • version: 1.2.0-alpha02

Artifact androidx.leanback:leanback:1.2.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.leanback:leanback com.android.support:leanback-v17

Androidx class mapping:

androidx.leanback.widget.ScaleFrameLayout android.support.v17.leanback.widget.ScaleFrameLayout

Overview

Subclass of FrameLayout that support scale layout area size for children.

Summary

Constructors
publicScaleFrameLayout(Context context)

publicScaleFrameLayout(Context context, AttributeSet attrs)

publicScaleFrameLayout(Context context, AttributeSet attrs, int defStyle)

Methods
public voidaddView(View child, int index, ViewGroup.LayoutParams params)

protected booleanaddViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout)

protected voidonLayout(boolean changed, int left, int top, int right, int bottom)

protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

public voidsetChildScale(float scale)

public voidsetForeground(Drawable d)

setForeground() is not supported, throws UnsupportedOperationException() when called.

public voidsetLayoutScaleX(float scaleX)

public voidsetLayoutScaleY(float scaleY)

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public ScaleFrameLayout(Context context)

public ScaleFrameLayout(Context context, AttributeSet attrs)

public ScaleFrameLayout(Context context, AttributeSet attrs, int defStyle)

Methods

public void setLayoutScaleX(float scaleX)

public void setLayoutScaleY(float scaleY)

public void setChildScale(float scale)

public void addView(View child, int index, ViewGroup.LayoutParams params)

protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout)

protected void onLayout(boolean changed, int left, int top, int right, int bottom)

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

public void setForeground(Drawable d)

setForeground() is not supported, throws UnsupportedOperationException() when called.

Source

/*
 * Copyright (C) 2014 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 androidx.leanback.widget;

import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.RestrictTo;

/**
 * Subclass of FrameLayout that support scale layout area size for children.
 * @hide
 */
@RestrictTo(LIBRARY_GROUP_PREFIX)
public class ScaleFrameLayout extends FrameLayout {

    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;

    private float mLayoutScaleX = 1f;
    private float mLayoutScaleY = 1f;

    private float mChildScale = 1f;

    public ScaleFrameLayout(Context context) {
        this(context ,null);
    }

    public ScaleFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScaleFrameLayout(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setLayoutScaleX(float scaleX) {
        if (scaleX != mLayoutScaleX) {
            mLayoutScaleX = scaleX;
            requestLayout();
        }
    }

    public void setLayoutScaleY(float scaleY) {
        if (scaleY != mLayoutScaleY) {
            mLayoutScaleY = scaleY;
            requestLayout();
        }
    }

    public void setChildScale(float scale) {
        if (mChildScale != scale) {
            mChildScale = scale;
            for (int i = 0; i < getChildCount(); i++) {
                getChildAt(i).setScaleX(scale);
                getChildAt(i).setScaleY(scale);
            }
        }
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        child.setScaleX(mChildScale);
        child.setScaleY(mChildScale);
    }

    @Override
    protected boolean addViewInLayout (View child, int index, ViewGroup.LayoutParams params,
            boolean preventRequestLayout) {
        boolean ret = super.addViewInLayout(child, index, params, preventRequestLayout);
        if (ret) {
            child.setScaleX(mChildScale);
            child.setScaleY(mChildScale);
        }
        return ret;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int count = getChildCount();

        final int parentLeft, parentRight;
        final int layoutDirection = getLayoutDirection();
        final float pivotX = (layoutDirection == View.LAYOUT_DIRECTION_RTL)
                ? getWidth() - getPivotX()
                : getPivotX();
        if (mLayoutScaleX != 1f) {
            parentLeft = getPaddingLeft() + (int)(pivotX - pivotX / mLayoutScaleX + 0.5f);
            parentRight = (int)(pivotX + (right - left - pivotX) / mLayoutScaleX + 0.5f)
                    - getPaddingRight();
        } else {
            parentLeft = getPaddingLeft();
            parentRight = right - left - getPaddingRight();
        }

        final int parentTop, parentBottom;
        final float pivotY = getPivotY();
        if (mLayoutScaleY != 1f) {
            parentTop = getPaddingTop() + (int)(pivotY - pivotY / mLayoutScaleY + 0.5f);
            parentBottom = (int)(pivotY + (bottom - top - pivotY) / mLayoutScaleY + 0.5f)
                    - getPaddingBottom();
        } else {
            parentTop = getPaddingTop();
            parentBottom = bottom - top - getPaddingBottom();
        }

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();

                final int width = child.getMeasuredWidth();
                final int height = child.getMeasuredHeight();

                int childLeft;
                int childTop;

                int gravity = lp.gravity;
                if (gravity == -1) {
                    gravity = DEFAULT_CHILD_GRAVITY;
                }

                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;

                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                    case Gravity.CENTER_HORIZONTAL:
                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2
                                + lp.leftMargin - lp.rightMargin;
                        break;
                    case Gravity.RIGHT:
                        childLeft = parentRight - width - lp.rightMargin;
                        break;
                    case Gravity.LEFT:
                    default:
                        childLeft = parentLeft + lp.leftMargin;
                }

                switch (verticalGravity) {
                    case Gravity.TOP:
                        childTop = parentTop + lp.topMargin;
                        break;
                    case Gravity.CENTER_VERTICAL:
                        childTop = parentTop + (parentBottom - parentTop - height) / 2
                                + lp.topMargin - lp.bottomMargin;
                        break;
                    case Gravity.BOTTOM:
                        childTop = parentBottom - height - lp.bottomMargin;
                        break;
                    default:
                        childTop = parentTop + lp.topMargin;
                }

                child.layout(childLeft, childTop, childLeft + width, childTop + height);
                // synchronize child pivot to be same as ScaleFrameLayout's pivot
                child.setPivotX(pivotX - childLeft);
                child.setPivotY(pivotY - childTop);
            }
        }
    }

    private static int getScaledMeasureSpec(int measureSpec, float scale) {
        return scale == 1f ? measureSpec : MeasureSpec.makeMeasureSpec(
                (int) (MeasureSpec.getSize(measureSpec) / scale + 0.5f),
                MeasureSpec.getMode(measureSpec));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mLayoutScaleX != 1f || mLayoutScaleY != 1f) {
            final int scaledWidthMeasureSpec =
                    getScaledMeasureSpec(widthMeasureSpec, mLayoutScaleX);
            final int scaledHeightMeasureSpec =
                    getScaledMeasureSpec(heightMeasureSpec, mLayoutScaleY);
            super.onMeasure(scaledWidthMeasureSpec, scaledHeightMeasureSpec);
            setMeasuredDimension((int)(getMeasuredWidth() * mLayoutScaleX + 0.5f),
                    (int)(getMeasuredHeight() * mLayoutScaleY + 0.5f));
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    /**
     * setForeground() is not supported,  throws UnsupportedOperationException() when called.
     */
    @Override
    public void setForeground(Drawable d) {
        throw new UnsupportedOperationException();
    }

}