Home | History | Annotate | Download | only in launcher3
      1 /*
      2  * Copyright (C) 2015 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  */
     16 
     17 package com.android.launcher3;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.graphics.Rect;
     22 import android.graphics.drawable.Drawable;
     23 import android.graphics.drawable.InsetDrawable;
     24 import android.util.AttributeSet;
     25 import android.view.View;
     26 import android.widget.FrameLayout;
     27 
     28 /**
     29  * A base container view, which supports resizing.
     30  */
     31 public abstract class BaseContainerView extends FrameLayout implements Insettable {
     32 
     33     private final static String TAG = "BaseContainerView";
     34 
     35     // The window insets
     36     private final Rect mInsets = new Rect();
     37     // The computed padding to apply to the container to achieve the container bounds
     38     protected final Rect mContentPadding = new Rect();
     39     // The inset to apply to the edges and between the search bar and the container
     40     private final int mContainerBoundsInset;
     41 
     42     private final Drawable mRevealDrawable;
     43 
     44     private View mRevealView;
     45     private View mContent;
     46 
     47     protected final int mHorizontalPadding;
     48 
     49     public BaseContainerView(Context context) {
     50         this(context, null);
     51     }
     52 
     53     public BaseContainerView(Context context, AttributeSet attrs) {
     54         this(context, attrs, 0);
     55     }
     56 
     57     public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
     58         super(context, attrs, defStyleAttr);
     59         mContainerBoundsInset = getResources().getDimensionPixelSize(R.dimen.container_bounds_inset);
     60 
     61         TypedArray a = context.obtainStyledAttributes(attrs,
     62                 R.styleable.BaseContainerView, defStyleAttr, 0);
     63         mRevealDrawable = a.getDrawable(R.styleable.BaseContainerView_revealBackground);
     64         a.recycle();
     65 
     66         int maxSize = getResources().getDimensionPixelSize(R.dimen.container_max_width);
     67         int minMargin = getResources().getDimensionPixelSize(R.dimen.container_min_margin);
     68         int width = ((Launcher) context).getDeviceProfile().availableWidthPx;
     69 
     70         if (maxSize > 0) {
     71             mHorizontalPadding = Math.max(minMargin, (width - maxSize) / 2);
     72         } else {
     73             mHorizontalPadding = Math.max(minMargin,
     74                     (int) getResources().getFraction(R.fraction.container_margin, width, 1));
     75         }
     76     }
     77 
     78     @Override
     79     protected void onFinishInflate() {
     80         super.onFinishInflate();
     81 
     82         mContent = findViewById(R.id.main_content);
     83         mRevealView = findViewById(R.id.reveal_view);
     84     }
     85 
     86     @Override
     87     final public void setInsets(Rect insets) {
     88         mInsets.set(insets);
     89         updateBackgroundAndPaddings();
     90     }
     91 
     92     /**
     93      * Sets the search bar bounds for this container view to match.
     94      */
     95     final public void setSearchBarBounds(Rect bounds) {
     96         // Post the updates since they can trigger a relayout, and this call can be triggered from
     97         // a layout pass itself.
     98         post(new Runnable() {
     99             @Override
    100             public void run() {
    101                 updateBackgroundAndPaddings();
    102             }
    103         });
    104     }
    105 
    106     /**
    107      * Update the backgrounds and padding in response to a change in the bounds or insets.
    108      */
    109     protected void updateBackgroundAndPaddings() {
    110         Rect padding;
    111         padding = new Rect(
    112                 mHorizontalPadding,
    113                 mInsets.top + mContainerBoundsInset,
    114                 mHorizontalPadding,
    115                 mInsets.bottom + mContainerBoundsInset
    116         );
    117 
    118         // The container padding changed, notify the container.
    119         if (!padding.equals(mContentPadding)) {
    120             mContentPadding.set(padding);
    121             onUpdateBackgroundAndPaddings(padding);
    122         }
    123     }
    124 
    125     private void onUpdateBackgroundAndPaddings(Rect padding) {
    126         // Apply the top-bottom padding to itself so that the launcher transition is
    127         // clipped correctly
    128         setPadding(0, padding.top, 0, padding.bottom);
    129 
    130         InsetDrawable background = new InsetDrawable(mRevealDrawable,
    131                 padding.left, 0, padding.right, 0);
    132         mRevealView.setBackground(background.getConstantState().newDrawable());
    133         mContent.setBackground(background);
    134 
    135         // We let the content have a intent background, but still have full width.
    136         // This allows the scroll bar to be used responsive outside the background bounds as well.
    137         mContent.setPadding(0, 0, 0, 0);
    138 
    139         Rect bgPadding = new Rect();
    140         background.getPadding(bgPadding);
    141         onUpdateBgPadding(padding, bgPadding);
    142     }
    143 
    144     protected abstract void onUpdateBgPadding(Rect padding, Rect bgPadding);
    145 
    146     public final View getContentView() {
    147         return mContent;
    148     }
    149 
    150     public final View getRevealView() {
    151         return mRevealView;
    152     }
    153 }