Home | History | Annotate | Download | only in bars
      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.layoutlib.bridge.bars;
     18 
     19 import com.android.ide.common.rendering.api.ActionBarCallback;
     20 import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
     21 import com.android.ide.common.rendering.api.RenderResources;
     22 import com.android.ide.common.rendering.api.ResourceValue;
     23 import com.android.ide.common.rendering.api.SessionParams;
     24 import com.android.layoutlib.bridge.MockView;
     25 import com.android.layoutlib.bridge.android.BridgeContext;
     26 
     27 import android.annotation.NonNull;
     28 import android.annotation.Nullable;
     29 import android.view.LayoutInflater;
     30 import android.view.View;
     31 import android.view.ViewGroup;
     32 import android.view.ViewGroup.LayoutParams;
     33 import android.widget.FrameLayout;
     34 import android.widget.RelativeLayout;
     35 
     36 /**
     37  * An abstraction over two implementations of the ActionBar - framework and appcompat.
     38  */
     39 public abstract class BridgeActionBar {
     40     // Store a reference to the context so that we don't have to cast it repeatedly.
     41     @NonNull protected final BridgeContext mBridgeContext;
     42     @NonNull protected final SessionParams mParams;
     43     // A Layout that contains the inflated action bar. The menu popup is added to this layout.
     44     @Nullable protected final ViewGroup mEnclosingLayout;
     45 
     46     private final View mDecorContent;
     47     private final ActionBarCallback mCallback;
     48 
     49     @SuppressWarnings("NullableProblems")  // Should be initialized by subclasses.
     50     @NonNull private FrameLayout mContentRoot;
     51 
     52     public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) {
     53         mBridgeContext = context;
     54         mParams = params;
     55         mCallback = params.getLayoutlibCallback().getActionBarCallback();
     56         ResourceValue layoutName = getLayoutResource(context);
     57 
     58         int layoutId = 0;
     59         if (layoutName == null) {
     60             assert false : "Unable to find the layout for Action Bar.";
     61         }
     62         else {
     63             if (layoutName.isFramework()) {
     64                 layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
     65                         layoutName.getName(), 0);
     66             } else {
     67                 layoutId = context.getProjectResourceValue(layoutName.getResourceType(),
     68                         layoutName.getName(), 0);
     69 
     70             }
     71         }
     72         if (layoutId == 0) {
     73             assert false : String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"",
     74                     layoutName.getName(), layoutName.getResourceType());
     75             mDecorContent = new MockView(context);
     76             mEnclosingLayout = null;
     77         }
     78         else {
     79             if (mCallback.isOverflowPopupNeeded()) {
     80                 // Create a RelativeLayout around the action bar, to which the overflow popup may be
     81                 // added.
     82                 mEnclosingLayout = new RelativeLayout(mBridgeContext);
     83                 setMatchParent(mEnclosingLayout);
     84             } else {
     85                 mEnclosingLayout = null;
     86             }
     87 
     88             // Inflate action bar layout.
     89             mDecorContent = getInflater(context).inflate(layoutId, mEnclosingLayout,
     90                     mEnclosingLayout != null);
     91         }
     92     }
     93 
     94     /**
     95      * Returns the Layout Resource that should be used to inflate the action bar. This layout
     96      * should cover the complete screen, and have a FrameLayout included, where the content will
     97      * be inflated.
     98      */
     99     protected abstract ResourceValue getLayoutResource(BridgeContext context);
    100 
    101     protected LayoutInflater getInflater(BridgeContext context) {
    102         return LayoutInflater.from(context);
    103     }
    104 
    105     protected void setContentRoot(@NonNull FrameLayout contentRoot) {
    106         mContentRoot = contentRoot;
    107     }
    108 
    109     @NonNull
    110     public FrameLayout getContentRoot() {
    111         return mContentRoot;
    112     }
    113 
    114     /**
    115      * Returns the view inflated. This should contain both the ActionBar and the app content in it.
    116      */
    117     protected View getDecorContent() {
    118         return mDecorContent;
    119     }
    120 
    121     /** Setup things like the title, subtitle, icon etc. */
    122     protected void setupActionBar() {
    123         setTitle();
    124         setSutTitle();
    125         setIcon();
    126         setHomeAsUp(mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP);
    127     }
    128 
    129     protected abstract void setTitle(CharSequence title);
    130     protected abstract void setSubtitle(CharSequence subtitle);
    131     protected abstract void setIcon(String icon);
    132     protected abstract void setHomeAsUp(boolean homeAsUp);
    133 
    134     private void setTitle() {
    135         RenderResources res = mBridgeContext.getRenderResources();
    136 
    137         String title = mParams.getAppLabel();
    138         ResourceValue titleValue = res.findResValue(title, false);
    139         if (titleValue != null && titleValue.getValue() != null) {
    140             setTitle(titleValue.getValue());
    141         } else {
    142             setTitle(title);
    143         }
    144     }
    145 
    146     private void setSutTitle() {
    147         String subTitle = mCallback.getSubTitle();
    148         if (subTitle != null) {
    149             setSubtitle(subTitle);
    150         }
    151     }
    152 
    153     private void setIcon() {
    154         String appIcon = mParams.getAppIcon();
    155         if (appIcon != null) {
    156             setIcon(appIcon);
    157         }
    158     }
    159 
    160     public abstract void createMenuPopup();
    161 
    162     /**
    163      * The root view that represents the action bar and possibly the content included in it.
    164      */
    165     public View getRootView() {
    166         return mEnclosingLayout == null ? mDecorContent : mEnclosingLayout;
    167     }
    168 
    169     public ActionBarCallback getCallBack() {
    170         return mCallback;
    171     }
    172 
    173     protected static void setMatchParent(View view) {
    174         view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
    175                 LayoutParams.MATCH_PARENT));
    176     }
    177 }
    178