/** * Copyright 2010-present Facebook. * * 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.facebook.widget; import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewTreeObserver; import android.view.Window; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.PopupWindow; import android.widget.TextView; import com.facebook.android.R; import java.lang.ref.WeakReference; public class ToolTipPopup { public static enum Style { /** * The tool tip will be shown with a blue style; including a blue background and blue * arrows. */ BLUE, /** * The tool tip will be shown with a black style; including a black background and black * arrows. */ BLACK } /** * The default time that the tool tip will be displayed */ public static final long DEFAULT_POPUP_DISPLAY_TIME = 6000; private final String mText; private final WeakReference<View> mAnchorViewRef; private final Context mContext; private PopupContentView mPopupContent; private PopupWindow mPopupWindow; private Style mStyle = Style.BLUE; private long mNuxDisplayTime = DEFAULT_POPUP_DISPLAY_TIME; private final ViewTreeObserver.OnScrollChangedListener mScrollListener = new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { if (mAnchorViewRef.get() != null && mPopupWindow != null && mPopupWindow.isShowing()) { if (mPopupWindow.isAboveAnchor()) { mPopupContent.showBottomArrow(); } else { mPopupContent.showTopArrow(); } } } }; /** * Create a new ToolTipPopup * @param text The text to be displayed in the tool tip * @param anchor The view to anchor this tool tip to. */ public ToolTipPopup(String text, View anchor) { mText = text; mAnchorViewRef = new WeakReference<View>(anchor); mContext = anchor.getContext(); } /** * Sets the {@link Style} of this tool tip. * @param mStyle */ public void setStyle(Style mStyle) { this.mStyle = mStyle; } /** * Display this tool tip to the user */ public void show() { if (mAnchorViewRef.get() != null) { mPopupContent = new PopupContentView(mContext); TextView body = (TextView) mPopupContent.findViewById( R.id.com_facebook_tooltip_bubble_view_text_body); body.setText(mText); if (mStyle == Style.BLUE) { mPopupContent.bodyFrame.setBackgroundResource( R.drawable.com_facebook_tooltip_blue_background); mPopupContent.bottomArrow.setImageResource( R.drawable.com_facebook_tooltip_blue_bottomnub); mPopupContent.topArrow.setImageResource( R.drawable.com_facebook_tooltip_blue_topnub); mPopupContent.xOut.setImageResource(R.drawable.com_facebook_tooltip_blue_xout); } else { mPopupContent.bodyFrame.setBackgroundResource( R.drawable.com_facebook_tooltip_black_background); mPopupContent.bottomArrow.setImageResource( R.drawable.com_facebook_tooltip_black_bottomnub); mPopupContent.topArrow.setImageResource( R.drawable.com_facebook_tooltip_black_topnub); mPopupContent.xOut.setImageResource(R.drawable.com_facebook_tooltip_black_xout); } final Window window = ((Activity) mContext).getWindow(); final View decorView = window.getDecorView(); final int decorWidth = decorView.getWidth(); final int decorHeight = decorView.getHeight(); registerObserver(); mPopupContent.onMeasure( View.MeasureSpec.makeMeasureSpec(decorWidth, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(decorHeight, View.MeasureSpec.AT_MOST)); mPopupWindow = new PopupWindow( mPopupContent, mPopupContent.getMeasuredWidth(), mPopupContent.getMeasuredHeight()); mPopupWindow.showAsDropDown(mAnchorViewRef.get()); updateArrows(); if (mNuxDisplayTime > 0) { mPopupContent.postDelayed(new Runnable() { @Override public void run() { dismiss(); } }, mNuxDisplayTime); } mPopupWindow.setTouchable(true); mPopupContent.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); } } /** * Set the time (in milliseconds) the tool tip will be displayed. Any number less than or equal * to 0 will cause the tool tip to be displayed indefinitely * @param displayTime The amount of time (in milliseconds) to display the tool tip */ public void setNuxDisplayTime(long displayTime) { this.mNuxDisplayTime = displayTime; } private void updateArrows() { if (mPopupWindow != null && mPopupWindow.isShowing()) { if (mPopupWindow.isAboveAnchor()) { mPopupContent.showBottomArrow(); } else { mPopupContent.showTopArrow(); } } } /** * Dismiss the tool tip */ public void dismiss() { unregisterObserver(); if (mPopupWindow != null) { mPopupWindow.dismiss(); } } private void registerObserver() { unregisterObserver(); if (mAnchorViewRef.get() != null) { mAnchorViewRef.get().getViewTreeObserver().addOnScrollChangedListener(mScrollListener); } } private void unregisterObserver() { if (mAnchorViewRef.get() != null) { mAnchorViewRef.get().getViewTreeObserver().removeOnScrollChangedListener(mScrollListener); } } private class PopupContentView extends FrameLayout { private ImageView topArrow; private ImageView bottomArrow; private View bodyFrame; private ImageView xOut; public PopupContentView(Context context) { super(context); init(); } private void init() { LayoutInflater inflater = LayoutInflater.from(getContext()); inflater.inflate(R.layout.com_facebook_tooltip_bubble, this); topArrow = (ImageView) findViewById(R.id.com_facebook_tooltip_bubble_view_top_pointer); bottomArrow = (ImageView) findViewById( R.id.com_facebook_tooltip_bubble_view_bottom_pointer); bodyFrame = findViewById(R.id.com_facebook_body_frame); xOut = (ImageView) findViewById(R.id.com_facebook_button_xout); } public void showTopArrow() { topArrow.setVisibility(View.VISIBLE); bottomArrow.setVisibility(View.INVISIBLE); } public void showBottomArrow() { topArrow.setVisibility(View.INVISIBLE); bottomArrow.setVisibility(View.VISIBLE); } // Expose so popup content can be sized @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }