Files
app_Settings/src/com/android/settings/inputmethod/TouchpadGestureDialogFragment.java
Harry Cutts ae3e005ff9 Touchpad: fix some NullAway warnings
Change I930e9fc85e09e03da3513e5f8443077fa8ea91b0 triggered some NullAway
warnings that are unrelated to the change, but some are trivial to fix,
for example by replacing member variables with local ones.

At the same time, add some `@NonNull` annotations to overriding methods
on Android Studio's recommendation.

Test: check touchpad gesture tutorial and pointer speed settings work
Test: $ atest SettingsRoboTests:com.android.settings.inputmethod
Bug: 245989146
Flag: EXEMPT refactor
Change-Id: I717eb2a2d68a46dce8ebaa95bef1183d09380f51
2025-01-08 11:53:14 +00:00

327 lines
12 KiB
Java

/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.inputmethod;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.android.settings.R;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import java.util.ArrayList;
import java.util.Arrays;
public class TouchpadGestureDialogFragment extends BottomSheetDialogFragment {
private Context mContext;
private ArrayList<View> mPageList;
private ImageView[] mDotIndicators;
private View[] mViewPagerItems;
private Button mButtonStartSkip;
private Button mButtonStartRestart;
private Button mButtonEndNext;
private Button mButtonEndDone;
private static final int DOT_INDICATOR_SIZE = 12;
private static final int DOT_INDICATOR_LEFT_PADDING = 6;
private static final int DOT_INDICATOR_RIGHT_PADDING = 6;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
mContext = context;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
final Dialog dialog = getDialog();
if (dialog == null) {
return;
}
Window window = dialog.getWindow();
if (window == null) {
return;
}
setLayoutEdgeToEdge(window);
final Point size = getScreenSize();
final WindowManager.LayoutParams attributes = window.getAttributes();
attributes.width = (int) (size.x * 0.75);
window.setAttributes(attributes);
}
@Override
public void onPause() {
super.onPause();
dismiss();
}
private static void setLayoutEdgeToEdge(Window window) {
View windowDecorView = window.getDecorView();
windowDecorView.setSystemUiVisibility(
windowDecorView.getSystemUiVisibility()
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
window.setNavigationBarColor(Color.TRANSPARENT);
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
View contentView = inflater.inflate(R.layout.touchpad_gesture_preview, null);
addViewPager(contentView, inflater);
dialog.setContentView(contentView);
Window gestureDialogWindow = dialog.getWindow();
gestureDialogWindow.setType(TYPE_SYSTEM_DIALOG);
// Workaround for solve issue about dialog not full expanded when landscape.
FrameLayout bottomSheet = (FrameLayout)
dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
bottomSheet.setBackgroundResource(android.R.color.transparent);
BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
if (!isGestureNavigationEnabled()) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
ViewTreeObserver observer = contentView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
contentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int contentViewHeight = contentView.getMeasuredHeight();
int navigationBarHeight = getNavigationBarHeight();
behavior.setPeekHeight(contentViewHeight - navigationBarHeight);
}
});
// The gesture education view shouldn't be draggable."
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
if (isGestureNavigationEnabled()) {
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// Do nothing.
}
});
return dialog;
}
private ArrayList<Integer> getViewPagerResource() {
return new ArrayList<Integer>(
Arrays.asList(
R.layout.gesture_tip1_go_home,
R.layout.gesture_tip2_go_back,
R.layout.gesture_tip3_recent_apps,
R.layout.gesture_tip4_notifications,
R.layout.gesture_tip5_switch_apps));
}
private void addViewPager(View preview, LayoutInflater inflater) {
ViewPager viewPager = preview.findViewById(R.id.viewpager);
int viewPagerResourceSize = getViewPagerResource().size();
mViewPagerItems = new View[viewPagerResourceSize];
for (int i = 0; i < viewPagerResourceSize; i++) {
mViewPagerItems[i] = inflater.inflate(getViewPagerResource().get(i), null /* root */);
}
mPageList = new ArrayList<View>();
for (int i = 0; i < mViewPagerItems.length; i++) {
mPageList.add(mViewPagerItems[i]);
}
viewPager.setAdapter(new GesturePagerAdapter(mPageList));
mButtonStartRestart = (Button) preview.findViewById(R.id.button_restart);
mButtonStartRestart.setOnClickListener(v -> {
final int firstPos = viewPager.getCurrentItem() - mViewPagerItems.length;
viewPager.setCurrentItem(firstPos, true);
});
mButtonEndDone = (Button) preview.findViewById(R.id.button_done);
mButtonEndDone.setOnClickListener(v -> {
dismiss();
});
mButtonStartSkip = (Button) preview.findViewById(R.id.button_skip);
mButtonStartSkip.setOnClickListener(v -> {
dismiss();
});
mButtonEndNext = (Button) preview.findViewById(R.id.button_next);
mButtonEndNext.setOnClickListener(v -> {
final int nextPos = viewPager.getCurrentItem() + 1;
viewPager.setCurrentItem(nextPos, true);
});
viewPager.addOnPageChangeListener(createPageListener());
final ViewGroup viewGroup = (ViewGroup) preview.findViewById(R.id.viewGroup);
mDotIndicators = new ImageView[mPageList.size()];
for (int i = 0; i < mPageList.size(); i++) {
final ImageView imageView = new ImageView(mContext);
final ViewGroup.MarginLayoutParams lp =
new ViewGroup.MarginLayoutParams(DOT_INDICATOR_SIZE, DOT_INDICATOR_SIZE);
lp.setMargins(DOT_INDICATOR_LEFT_PADDING, 0, DOT_INDICATOR_RIGHT_PADDING, 0);
imageView.setLayoutParams(lp);
mDotIndicators[i] = imageView;
viewGroup.addView(mDotIndicators[i]);
}
}
private static class GesturePagerAdapter extends PagerAdapter {
private final ArrayList<View> mPageViewList;
GesturePagerAdapter(ArrayList<View> pageViewList) {
mPageViewList = pageViewList;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position,
@NonNull Object object) {
if (mPageViewList.get(position) != null) {
container.removeView(mPageViewList.get(position));
}
}
@NonNull
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mPageViewList.get(position));
return mPageViewList.get(position);
}
@Override
public int getCount() {
return mPageViewList.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return object == view;
}
}
private ViewPager.OnPageChangeListener createPageListener() {
return new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(
int position, float positionOffset, int positionOffsetPixels) {
if (positionOffset != 0) {
for (int i = 0; i < mPageList.size(); i++) {
mViewPagerItems[i].setVisibility(View.VISIBLE);
}
} else {
updateIndicator(position);
}
}
@Override
public void onPageSelected(int position) {}
@Override
public void onPageScrollStateChanged(int state) {}
};
}
private void updateIndicator(int position) {
for (int i = 0; i < mPageList.size(); i++) {
if (position == i) {
mDotIndicators[i].setBackgroundResource(
R.drawable.ic_color_page_indicator_focused);
mViewPagerItems[i].setVisibility(View.VISIBLE);
} else {
mDotIndicators[i].setBackgroundResource(
R.drawable.ic_color_page_indicator_unfocused);
mViewPagerItems[i].setVisibility(View.INVISIBLE);
}
}
if (position >= 0 && position < mViewPagerItems.length - 1) {
mButtonStartSkip.setVisibility(View.VISIBLE);
mButtonEndNext.setVisibility(View.VISIBLE);
mButtonStartRestart.setVisibility(View.GONE);
mButtonEndDone.setVisibility(View.GONE);
} else {
mButtonStartSkip.setVisibility(View.GONE);
mButtonEndNext.setVisibility(View.GONE);
mButtonStartRestart.setVisibility(View.VISIBLE);
mButtonEndDone.setVisibility(View.VISIBLE);
}
}
private Point getScreenSize() {
final Point size = new Point();
final Activity activity = (Activity) mContext;
final Display display = activity.getWindowManager().getDefaultDisplay();
display.getSize(size);
return size;
}
private int getNavigationBarHeight() {
final Activity activity = (Activity) mContext;
WindowInsets insets =
activity.getWindowManager().getCurrentWindowMetrics().getWindowInsets();
return insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
}
private boolean isGestureNavigationEnabled() {
return NAV_BAR_MODE_GESTURAL == mContext.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode);
}
}