Merge "Add basic AnchoredWindow."
This commit is contained in:
committed by
Android (Google) Code Review
commit
4e816831e2
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.server.autofill;
|
||||
|
||||
import static com.android.server.autofill.Helper.DEBUG;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Slog;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* A window above the application that is smartly anchored to a rectangular region.
|
||||
*/
|
||||
final class AnchoredWindow {
|
||||
private static final String TAG = "AutoFill";
|
||||
|
||||
private final WindowManager mWm;
|
||||
private final View mRootView;
|
||||
private final View mView;
|
||||
private final int mWidth;
|
||||
private final int mHeight;
|
||||
private boolean mIsShowing = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param wm window manager that draws the view on a window
|
||||
* @param view singleton view in the window
|
||||
* @param width requested width of the view
|
||||
* @param height requested height of the view
|
||||
*/
|
||||
AnchoredWindow(WindowManager wm, View view, int width, int height) {
|
||||
mWm = wm;
|
||||
mRootView = wrapView(view, width, height);
|
||||
mView = view;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the window.
|
||||
*
|
||||
* @param bounds the rectangular region this window should be anchored to
|
||||
*/
|
||||
void show(Rect bounds) {
|
||||
LayoutParams params = createBaseLayoutParams();
|
||||
params.x = bounds.left;
|
||||
params.y = bounds.bottom;
|
||||
|
||||
if (!mIsShowing) {
|
||||
if (DEBUG) Slog.d(TAG, "adding view " + mView);
|
||||
mWm.addView(mRootView, params);
|
||||
} else {
|
||||
if (DEBUG) Slog.d(TAG, "updating view " + mView);
|
||||
mWm.updateViewLayout(mRootView, params);
|
||||
}
|
||||
mIsShowing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the window.
|
||||
*/
|
||||
void hide() {
|
||||
if (DEBUG) Slog.d(TAG, "removing view " + mView);
|
||||
if (mIsShowing) {
|
||||
mWm.removeView(mRootView);
|
||||
}
|
||||
mIsShowing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a view with a SelfRemovingView and sets its requested width and height.
|
||||
*/
|
||||
private View wrapView(View view, int width, int height) {
|
||||
ViewGroup viewGroup = new SelfRemovingView(view.getContext());
|
||||
viewGroup.addView(view, new ViewGroup.LayoutParams(width, height));
|
||||
return viewGroup;
|
||||
}
|
||||
|
||||
private static LayoutParams createBaseLayoutParams() {
|
||||
LayoutParams params = new LayoutParams();
|
||||
// TODO(b/33197203): LayoutParams.TYPE_AUTOFILL
|
||||
params.type = LayoutParams.TYPE_SYSTEM_ALERT;
|
||||
params.flags =
|
||||
LayoutParams.SOFT_INPUT_STATE_UNCHANGED
|
||||
| LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
| LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
|
||||
params.gravity = Gravity.TOP | Gravity.LEFT;
|
||||
params.width = LayoutParams.WRAP_CONTENT;
|
||||
params.height = LayoutParams.WRAP_CONTENT;
|
||||
return params;
|
||||
}
|
||||
|
||||
/** FrameLayout that listens for touch events removes itself if the touch event is outside. */
|
||||
private final class SelfRemovingView extends FrameLayout {
|
||||
public SelfRemovingView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
|
||||
hide();
|
||||
return true;
|
||||
} else {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user