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.google.android.setupdesign.view; 18 19 import android.annotation.TargetApi; 20 import android.content.Context; 21 import android.content.res.TypedArray; 22 import android.graphics.Color; 23 import android.os.Build.VERSION_CODES; 24 import android.util.AttributeSet; 25 import android.view.ContextThemeWrapper; 26 import android.view.View; 27 import android.widget.Button; 28 import android.widget.LinearLayout; 29 import androidx.annotation.StyleableRes; 30 import com.google.android.setupdesign.R; 31 32 /** 33 * Custom navigation bar for use with setup wizard. This bar contains a back button, more button and 34 * next button. By default, the more button is hidden, and typically the next button will be hidden 35 * if the more button is shown. 36 * 37 * @see com.google.android.setupdesign.template.RequireScrollMixin 38 */ 39 public class NavigationBar extends LinearLayout implements View.OnClickListener { 40 41 /** 42 * An interface to listen to events of the navigation bar, namely when the user clicks on the back 43 * or next button. 44 */ 45 public interface NavigationBarListener { onNavigateBack()46 void onNavigateBack(); 47 onNavigateNext()48 void onNavigateNext(); 49 } 50 getNavbarTheme(Context context)51 private static int getNavbarTheme(Context context) { 52 // Normally we can automatically guess the theme by comparing the foreground color against 53 // the background color. But we also allow specifying explicitly using sudNavBarTheme. 54 TypedArray attributes = 55 context.obtainStyledAttributes( 56 new int[] { 57 R.attr.sudNavBarTheme, android.R.attr.colorForeground, android.R.attr.colorBackground 58 }); 59 @StyleableRes int navBarTheme = 0; 60 @StyleableRes int colorForeground = 1; 61 @StyleableRes int colorBackground = 2; 62 int theme = attributes.getResourceId(navBarTheme, 0); 63 if (theme == 0) { 64 // Compare the value of the foreground against the background color to see if current 65 // theme is light-on-dark or dark-on-light. 66 float[] foregroundHsv = new float[3]; 67 float[] backgroundHsv = new float[3]; 68 Color.colorToHSV(attributes.getColor(colorForeground, 0), foregroundHsv); 69 Color.colorToHSV(attributes.getColor(colorBackground, 0), backgroundHsv); 70 boolean isDarkBg = foregroundHsv[2] > backgroundHsv[2]; 71 theme = isDarkBg ? R.style.SudNavBarThemeDark : R.style.SudNavBarThemeLight; 72 } 73 attributes.recycle(); 74 return theme; 75 } 76 getThemedContext(Context context)77 private static Context getThemedContext(Context context) { 78 final int theme = getNavbarTheme(context); 79 return new ContextThemeWrapper(context, theme); 80 } 81 82 private Button nextButton; 83 private Button backButton; 84 private Button moreButton; 85 private NavigationBarListener listener; 86 NavigationBar(Context context)87 public NavigationBar(Context context) { 88 super(getThemedContext(context)); 89 init(); 90 } 91 NavigationBar(Context context, AttributeSet attrs)92 public NavigationBar(Context context, AttributeSet attrs) { 93 super(getThemedContext(context), attrs); 94 init(); 95 } 96 97 @TargetApi(VERSION_CODES.HONEYCOMB) NavigationBar(Context context, AttributeSet attrs, int defStyleAttr)98 public NavigationBar(Context context, AttributeSet attrs, int defStyleAttr) { 99 super(getThemedContext(context), attrs, defStyleAttr); 100 init(); 101 } 102 103 // All the constructors delegate to this init method. The 3-argument constructor is not 104 // available in LinearLayout before v11, so call super with the exact same arguments. init()105 private void init() { 106 if (isInEditMode()) { 107 return; 108 } 109 110 View.inflate(getContext(), R.layout.sud_navbar_view, this); 111 nextButton = (Button) findViewById(R.id.sud_navbar_next); 112 backButton = (Button) findViewById(R.id.sud_navbar_back); 113 moreButton = (Button) findViewById(R.id.sud_navbar_more); 114 } 115 getBackButton()116 public Button getBackButton() { 117 return backButton; 118 } 119 getNextButton()120 public Button getNextButton() { 121 return nextButton; 122 } 123 getMoreButton()124 public Button getMoreButton() { 125 return moreButton; 126 } 127 setNavigationBarListener(NavigationBarListener listener)128 public void setNavigationBarListener(NavigationBarListener listener) { 129 this.listener = listener; 130 if (this.listener != null) { 131 getBackButton().setOnClickListener(this); 132 getNextButton().setOnClickListener(this); 133 } 134 } 135 136 @Override onClick(View view)137 public void onClick(View view) { 138 if (listener != null) { 139 if (view == getBackButton()) { 140 listener.onNavigateBack(); 141 } else if (view == getNextButton()) { 142 listener.onNavigateNext(); 143 } 144 } 145 } 146 } 147