1 /* 2 * Copyright (C) 2023 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.systemui.accessibility.accessibilitymenu.view; 18 19 import static android.view.View.LAYOUT_DIRECTION_LTR; 20 21 import android.content.res.Configuration; 22 import android.graphics.Rect; 23 import android.text.TextUtils; 24 import android.view.TouchDelegate; 25 import android.view.View; 26 import android.view.View.OnClickListener; 27 import android.view.ViewGroup; 28 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 29 import android.widget.ImageButton; 30 31 import androidx.annotation.Nullable; 32 33 import com.android.systemui.accessibility.accessibilitymenu.R; 34 35 /** 36 * This class is for Accessibility menu footer layout. Handles switching between a11y menu pages. 37 */ 38 public class A11yMenuFooter { 39 40 /** Provides an interface for footer of a11yMenu. */ 41 public interface A11yMenuFooterCallBack { 42 43 /** Calls back when user clicks the left button. */ onNextButtonClicked()44 void onNextButtonClicked(); 45 46 /** Calls back when user clicks the right button. */ onPreviousButtonClicked()47 void onPreviousButtonClicked(); 48 } 49 50 private final FooterButtonClickListener mFooterButtonClickListener; 51 52 private ImageButton mPageLeftBtn; 53 private ImageButton mPageRightBtn; 54 private View mTopListDivider; 55 private View mBottomListDivider; 56 private final A11yMenuFooterCallBack mCallBack; 57 private final ViewGroup mMenuLayout; 58 private ViewGroup mFooterContainer; 59 private int mFooterContainerBaseHeight = 0; 60 private int mRightToLeftDirection = LAYOUT_DIRECTION_LTR; 61 A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack)62 public A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack) { 63 this.mCallBack = callBack; 64 mFooterButtonClickListener = new FooterButtonClickListener(); 65 configureFooterLayout(menuLayout); 66 mMenuLayout = menuLayout; 67 } 68 getPreviousPageBtn()69 public @Nullable ImageButton getPreviousPageBtn() { 70 return mRightToLeftDirection == LAYOUT_DIRECTION_LTR 71 ? mPageLeftBtn : mPageRightBtn; 72 } 73 getNextPageBtn()74 public @Nullable ImageButton getNextPageBtn() { 75 return mRightToLeftDirection == LAYOUT_DIRECTION_LTR 76 ? mPageRightBtn : mPageLeftBtn; 77 } 78 adjustFooterToDensityScale(float densityScale)79 void adjustFooterToDensityScale(float densityScale) { 80 mFooterContainer.getLayoutParams().height = 81 (int) (mFooterContainerBaseHeight / densityScale); 82 } 83 getHeight()84 int getHeight() { 85 return mFooterContainer.getLayoutParams().height; 86 } 87 88 /** Sets right to left direction of footer. */ updateRightToLeftDirection(Configuration configuration)89 public void updateRightToLeftDirection(Configuration configuration) { 90 mRightToLeftDirection = TextUtils.getLayoutDirectionFromLocale( 91 configuration.getLocales().get(0)); 92 getPreviousPageBtn().setContentDescription(mMenuLayout.getResources().getString( 93 R.string.previous_button_content_description)); 94 getNextPageBtn().setContentDescription(mMenuLayout.getResources().getString( 95 R.string.next_button_content_description)); 96 } 97 configureFooterLayout(ViewGroup menuLayout)98 private void configureFooterLayout(ViewGroup menuLayout) { 99 mFooterContainer = menuLayout.findViewById(R.id.footerlayout); 100 mFooterContainer.setVisibility(View.VISIBLE); 101 mFooterContainerBaseHeight = mFooterContainer.getLayoutParams().height; 102 103 mPageLeftBtn = menuLayout.findViewById(R.id.menu_left_button); 104 mPageRightBtn = menuLayout.findViewById(R.id.menu_right_button); 105 mTopListDivider = menuLayout.findViewById(R.id.top_listDivider); 106 mBottomListDivider = menuLayout.findViewById(R.id.bottom_listDivider); 107 108 // Registers listeners for footer buttons. 109 setListener(mPageLeftBtn); 110 setListener(mPageRightBtn); 111 112 menuLayout 113 .getViewTreeObserver() 114 .addOnGlobalLayoutListener( 115 new OnGlobalLayoutListener() { 116 @Override 117 public void onGlobalLayout() { 118 menuLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); 119 expandBtnTouchArea(mPageLeftBtn, menuLayout); 120 expandBtnTouchArea(mPageRightBtn, (View) mPageRightBtn.getParent()); 121 } 122 }); 123 } 124 expandBtnTouchArea(ImageButton btn, View btnParent)125 private void expandBtnTouchArea(ImageButton btn, View btnParent) { 126 Rect btnRect = new Rect(); 127 btn.getHitRect(btnRect); 128 btnRect.top -= getHitRectHeight(mTopListDivider); 129 btnRect.bottom += getHitRectHeight(mBottomListDivider); 130 btnParent.setTouchDelegate(new TouchDelegate(btnRect, btn)); 131 } 132 getHitRectHeight(View listDivider)133 private static int getHitRectHeight(View listDivider) { 134 Rect hitRect = new Rect(); 135 listDivider.getHitRect(hitRect); 136 return hitRect.height(); 137 } 138 setListener(@ullable View view)139 private void setListener(@Nullable View view) { 140 if (view != null) { 141 view.setOnClickListener(mFooterButtonClickListener); 142 } 143 } 144 145 /** Handles click event for footer buttons. */ 146 private class FooterButtonClickListener implements OnClickListener { 147 @Override onClick(View view)148 public void onClick(View view) { 149 if (view.getId() == getPreviousPageBtn().getId()) { 150 mCallBack.onPreviousButtonClicked(); 151 } else if (view.getId() == getNextPageBtn().getId()) { 152 mCallBack.onNextButtonClicked(); 153 } 154 } 155 } 156 } 157