144 lines
5.1 KiB
Java
144 lines
5.1 KiB
Java
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.gecko.widget;
|
|
|
|
import org.mozilla.gecko.AppConstants.Versions;
|
|
import org.mozilla.gecko.R;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.view.Gravity;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.PopupWindow;
|
|
import org.mozilla.gecko.util.HardwareUtils;
|
|
|
|
/**
|
|
* AnchoredPopup is the base class for doorhanger notifications, and is anchored to the urlbar.
|
|
*/
|
|
public abstract class AnchoredPopup extends PopupWindow {
|
|
public interface OnVisibilityChangeListener {
|
|
public void onDoorHangerShow();
|
|
public void onDoorHangerHide();
|
|
}
|
|
|
|
private View mAnchor;
|
|
private OnVisibilityChangeListener onVisibilityChangeListener;
|
|
|
|
protected RoundedCornerLayout mContent;
|
|
protected boolean mInflated;
|
|
|
|
protected final Context mContext;
|
|
|
|
public AnchoredPopup(Context context) {
|
|
super(context);
|
|
|
|
mContext = context;
|
|
|
|
setAnimationStyle(R.style.PopupAnimation);
|
|
}
|
|
|
|
protected void init() {
|
|
// Hide the default window background. Passing null prevents the below setOutTouchable()
|
|
// call from working, so use an empty BitmapDrawable instead.
|
|
setBackgroundDrawable(new BitmapDrawable(mContext.getResources()));
|
|
|
|
// Allow the popup to be dismissed when touching outside.
|
|
setOutsideTouchable(true);
|
|
|
|
// PopupWindow has a default width and height of 0, so set the width here.
|
|
int width = (int) mContext.getResources().getDimension(R.dimen.doorhanger_width);
|
|
setWindowLayoutMode(0, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
setWidth(width);
|
|
|
|
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
|
final View layout = inflater.inflate(R.layout.anchored_popup, null);
|
|
setContentView(layout);
|
|
|
|
mContent = (RoundedCornerLayout) layout.findViewById(R.id.content);
|
|
|
|
mInflated = true;
|
|
}
|
|
|
|
/**
|
|
* Sets the anchor for this popup.
|
|
*
|
|
* @param anchor Anchor view for positioning the arrow.
|
|
*/
|
|
public void setAnchor(View anchor) {
|
|
mAnchor = anchor;
|
|
}
|
|
|
|
public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) {
|
|
onVisibilityChangeListener = listener;
|
|
}
|
|
|
|
/**
|
|
* Shows the popup with the arrow pointing to the center of the anchor view. If the anchor
|
|
* isn't visible, the popup will just be shown at the top of the root view.
|
|
*/
|
|
public void show() {
|
|
if (!mInflated) {
|
|
throw new IllegalStateException("ArrowPopup#init() must be called before ArrowPopup#show()");
|
|
}
|
|
|
|
if (onVisibilityChangeListener != null) {
|
|
onVisibilityChangeListener.onDoorHangerShow();
|
|
}
|
|
|
|
final int[] anchorLocation = new int[2];
|
|
if (mAnchor != null) {
|
|
mAnchor.getLocationInWindow(anchorLocation);
|
|
}
|
|
|
|
// The doorhanger should overlap the bottom of the urlbar.
|
|
int offsetY = mContext.getResources().getDimensionPixelOffset(R.dimen.doorhanger_offsetY);
|
|
final View decorView = ((Activity) mContext).getWindow().getDecorView();
|
|
|
|
// Hack for Gingerbread: showAtLocation ignores window layout parameters so we have to use
|
|
// showAsDropDown() instead.
|
|
// Height and width are always set to 0 dp.
|
|
if (Versions.preHC) {
|
|
setWidth(decorView.getWidth());
|
|
offsetY = mContext.getResources().getDimensionPixelOffset(R.dimen.doorhanger_GB_offsetY);
|
|
if (mAnchor == null) {
|
|
mAnchor = decorView;
|
|
}
|
|
showAsDropDown(mAnchor, 0, -offsetY);
|
|
return;
|
|
}
|
|
|
|
final boolean validAnchor = (mAnchor != null) && (anchorLocation[1] > 0);
|
|
if (HardwareUtils.isTablet()) {
|
|
if (validAnchor) {
|
|
showAsDropDown(mAnchor, 0, 0);
|
|
} else {
|
|
// The anchor will be offscreen if the dynamic toolbar is hidden, so anticipate the re-shown position
|
|
// of the toolbar.
|
|
final int offsetX = mContext.getResources().getDimensionPixelOffset(R.dimen.doorhanger_offsetX);
|
|
showAtLocation(decorView, Gravity.TOP | Gravity.LEFT, offsetX, offsetY);
|
|
}
|
|
} else {
|
|
// If the anchor is null or out of the window bounds, just show the popup at the top of the
|
|
// root view.
|
|
final View anchor = validAnchor ? mAnchor : decorView;
|
|
|
|
showAtLocation(anchor, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, offsetY);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dismiss() {
|
|
super.dismiss();
|
|
if (onVisibilityChangeListener != null) {
|
|
onVisibilityChangeListener.onDoorHangerHide();
|
|
}
|
|
}
|
|
}
|