Merge "Add basic AnchoredWindow."

This commit is contained in:
TreeHugger Robot
2017-01-26 23:46:05 +00:00
committed by Android (Google) Code Review

View File

@@ -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);
}
}
}
}