1 /* 2 * Copyright 2019 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.car.apps.common; 18 19 import android.content.Context; 20 import android.graphics.drawable.Drawable; 21 import android.util.AttributeSet; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.FrameLayout; 26 import android.widget.ImageButton; 27 import android.widget.ImageView; 28 import android.widget.TextView; 29 30 import androidx.annotation.Nullable; 31 import androidx.constraintlayout.widget.ConstraintLayout; 32 33 /** 34 * This is a compact CarControlBar that provides a fixed number of controls (with no overflow), 35 * along with some metadata (title, subtitle, icon) 36 */ 37 public class MinimizedControlBar extends ConstraintLayout implements CarControlBar { 38 39 // All slots in this action bar where 0 is the bottom-start corner of the matrix, and 40 // mNumColumns * nNumRows - 1 is the top-end corner 41 private FrameLayout[] mSlots; 42 43 /** Views to set in a particular {@link ControlBar.SlotPosition} */ 44 private final View[] mFixedViews = new View[3]; 45 // Holds the views to show as buttons 46 private View[] mViews; 47 48 protected TextView mTitle; 49 protected TextView mSubtitle; 50 protected ImageView mContentTile; 51 52 private static final int NUM_COLUMNS = 3; 53 MinimizedControlBar(Context context)54 public MinimizedControlBar(Context context) { 55 this(context, null, 0); 56 } 57 MinimizedControlBar(Context context, AttributeSet attrs)58 public MinimizedControlBar(Context context, AttributeSet attrs) { 59 this(context, attrs, 0); 60 } 61 62 MinimizedControlBar(Context context, AttributeSet attrs, int defStyleAttrs)63 public MinimizedControlBar(Context context, AttributeSet attrs, int defStyleAttrs) { 64 this(context, attrs, defStyleAttrs, R.layout.minimized_control_bar); 65 } 66 MinimizedControlBar(Context context, AttributeSet attrs, int defStyleAttrs, int layoutId)67 protected MinimizedControlBar(Context context, AttributeSet attrs, int defStyleAttrs, 68 int layoutId) { 69 super(context, attrs, defStyleAttrs); 70 init(context, layoutId); 71 } 72 init(Context context, int layoutId)73 private void init(Context context, int layoutId) { 74 inflate(context, layoutId, this); 75 mViews = new View[NUM_COLUMNS]; 76 mTitle = findViewById(R.id.minimized_control_bar_title); 77 mSubtitle = findViewById(R.id.minimized_control_bar_subtitle); 78 mContentTile = findViewById(R.id.minimized_control_bar_content_tile); 79 80 mSlots = new FrameLayout[NUM_COLUMNS]; 81 82 mSlots[0] = findViewById(R.id.minimized_control_bar_left_slot); 83 mSlots[1] = findViewById(R.id.minimized_control_bar_main_slot); 84 mSlots[2] = findViewById(R.id.minimized_control_bar_right_slot); 85 } 86 87 @Override setView(@ullable View view, @SlotPosition int slotPosition)88 public void setView(@Nullable View view, @SlotPosition int slotPosition) { 89 mFixedViews[slotPosition] = view; 90 updateViewsLayout(); 91 } 92 93 @Override setViews(@ullable View[] views)94 public void setViews(@Nullable View[] views) { 95 mViews = views; 96 updateViewsLayout(); 97 } 98 99 @Override createIconButton(Drawable icon)100 public ImageButton createIconButton(Drawable icon) { 101 return createIconButton(icon, R.layout.control_bar_button); 102 } 103 104 @Override createIconButton(Drawable icon, int viewId)105 public ImageButton createIconButton(Drawable icon, int viewId) { 106 LayoutInflater inflater = LayoutInflater.from(mSlots[0].getContext()); 107 final boolean attachToRoot = false; 108 ImageButton button = (ImageButton) inflater.inflate(viewId, mSlots[0], attachToRoot); 109 button.setImageDrawable(icon); 110 return button; 111 } 112 updateViewsLayout()113 private void updateViewsLayout() { 114 int viewIndex = 0; 115 // Fill in slots with provided views 116 for (int i = 0; i < NUM_COLUMNS; i++) { 117 View viewToUse = null; 118 if (mFixedViews[i] != null) { 119 viewToUse = mFixedViews[i]; 120 } else if (mViews != null && viewIndex < mViews.length) { 121 // If views are not provided explicitly for a slot, use the next value in the list 122 viewToUse = mViews[viewIndex]; 123 viewIndex++; 124 } 125 setView(viewToUse, mSlots[CarControlBar.getSlotIndex(i, NUM_COLUMNS)]); 126 } 127 } 128 setView(@ullable View view, FrameLayout container)129 private void setView(@Nullable View view, FrameLayout container) { 130 container.removeAllViews(); 131 if (view != null) { 132 ViewGroup parent = (ViewGroup) view.getParent(); 133 // As we are removing views (on BT disconnect, for example), some items will be 134 // shifting from expanded to collapsed - remove those from the group before adding to 135 // the new slot 136 if (view.getParent() != null) { 137 parent.removeView(view); 138 } 139 container.addView(view); 140 container.setVisibility(VISIBLE); 141 } else { 142 container.setVisibility(INVISIBLE); 143 } 144 } 145 146 } 147