在首次运行时显示覆盖层提示框

6
第一次运行某些谷歌应用程序或核心Android系统(或进行重大更新后),有时会显示一个透明的叠加层,其中包含有关如何使用新功能的简短提示信息。下面是一个示例。
在Android框架中是否有API用于创建它们,或者是否都是定制的?如果是后一种情况,应该如何实现?最后,这些提示信息是否有某种官方/技术名称可以参考(在搜索相关信息时可能会有用)?谢谢。
编辑
我获取了一张截图,更准确地说明了我的意思。除了“指向手”图形外,此工具提示还在Clock应用程序的图标周围显示了一个高亮圆圈。这不仅仅是一个透明叠加层,单击后就消失:此时可以单击甚至长按时钟图标,但其他图标(圆圈外)在工具提示消失之前是不可访问的。所有这些行为是否都是专门为此目的而定制的,还是存在某些内置设施?

1
我正想问这个问题,尽管我想要的是“气球提示”效果。你找到实现它的方法了吗?我不想为一个只用一次的功能增加布局复杂度... - Basic
3个回答

3

这只是一个半透明的对话框。

将下面的代码插入res文件夹中的themes.xml中。

 <style name="Theme.TranparentDialog" parent="@android:style/Theme.NoTitleBar">
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:colorForeground">@color/transparent</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowBackground">@color/transparent</item>
    </style>

创建覆盖整个屏幕的对话框以实现半透明效果。

Dialog dialog= new Dialog(context,  R.style.Theme_TutorialDialog);

dialog.show();


谢谢您的回答。不过,我提供了一张更精确的截图并稍微更新了我的问题。请看一下。 - Natix

2

0

如果将此视图用作上述对话框的背景,则可以使用此视图来在屏幕上绘制一个透明的矩形。

public class WindowView extends View {
private static final int LOW_DPI_STATUS_BAR_HEIGHT = 19;

private static final int MEDIUM_DPI_STATUS_BAR_HEIGHT = 25;

private static final int HIGH_DPI_STATUS_BAR_HEIGHT = 38;
Context mContext;

int mHeight, mWidth, mTop, mRight, mLeft, mBottom;
Rect mLeftRect, mRightRect, mTopRect, mBottomRect;

Rect mRect;
Paint mPaint;
View mAnchorView;
Paint mTempPaint1;

public WindowView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public WindowView(Context context) {
    this(context, null);
}

public WindowView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mContext = context;
    initVariables();
}

boolean mReset = false;

GestureDetector mGestureDetector;
GestureDetector.SimpleOnGestureListener mSimpleOnGestureListener;

private View getView() {
    return this;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (mSimpleOnGestureListener == null) {
        mSimpleOnGestureListener = new SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                if (mListener != null && e.getX() >= mRect.left
                        && e.getX() <= mRect.right && e.getY() >= mRect.top
                        && e.getY() <= mRect.bottom)
                    mListener.onClick(getView());
                return true;
            }
        };
    }
    if (mGestureDetector == null) {
        mGestureDetector = new GestureDetector(mContext,
                mSimpleOnGestureListener);
    }
    mGestureDetector.onTouchEvent(event);
    return true;
}

private void initVariables() {
    mPaint = new Paint();
    mPaint.setStyle(Style.FILL);
    mPaint.setColor(mContext.getResources().getColor(
            R.color.tut_transcluscent_bg));
    mRect = new Rect();

    mTempPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
    mTempPaint1.setAlpha(64);
    mTempPaint1.setColorFilter(new PorterDuffColorFilter(Color.WHITE,
            Mode.SRC_IN));
}

OnClickListener mListener;

public void setTransparentBackGroundColor(int color) {
    mPaint.setColor(color);
    invalidate();
}

@Override
public void setOnClickListener(OnClickListener l) {
    mListener = l;
}

public View getAnchorView() {
    return mAnchorView;
}

float[] mPaddings;
Rect mAnchorRect;;

public void setAnchorView(View mView, Rect rect, float[] paddings) {
    mAnchorRect = rect;
    if (mAnchorRect == null)
        mAnchorView = mView;
    else
        mAnchorView = null;
    mPaddings = paddings;
    requestLayout();
    invalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (mAnchorView != null || mAnchorRect != null)
        initView();
    mReset = true;
}

boolean mFlagInvalid = false;
Handler mAnrHandler;

public void setHandler(Handler handler) {
    mAnrHandler = handler;
}

private int getStatusBarHeight() {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
            .getDefaultDisplay().getMetrics(displayMetrics);

    int statusBarHeight;

    switch (displayMetrics.densityDpi) {
    case DisplayMetrics.DENSITY_HIGH:
        statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT;
        break;
    case DisplayMetrics.DENSITY_MEDIUM:
        statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
        break;
    case DisplayMetrics.DENSITY_LOW:
        statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT;
        break;
    default:
        statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
    }
    return statusBarHeight;
}

public void initView() {

    mFlagInvalid = false;
    int top = 0, left = 0;
    if (mAnchorView != null) {
        top = mAnchorView.getTop();
        left = mAnchorView.getLeft();
        View temp = mAnchorView;
        int cnt = 0;
        try {
            while (((View) temp.getParent()).getId() != android.R.id.content) {
                temp = (View) temp.getParent();
                int scrolledHeight = 0;
                if (temp instanceof ScrollView) {
                    scrolledHeight = ((ScrollView) temp).getScrollY();
                }
                top = top + temp.getTop() - scrolledHeight;
                left = left + temp.getLeft();
                cnt++;
                if (cnt > 100) {
                    if (mAnrHandler != null)
                        mAnrHandler.sendEmptyMessage(9);
                    mFlagInvalid = true;
                    break;
                }
            }
        } catch (Exception e) {
            mFlagInvalid = true;
            if (mAnrHandler != null)
                mAnrHandler.sendEmptyMessage(8);
            e.printStackTrace();
        }
        TypedValue tv = new TypedValue();
        if (getContext()
                .getTheme()
                .resolveAttribute(
                        VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB ? android.R.attr.actionBarSize
                                : R.attr.actionBarSize, tv, true)) {
            int actionBarHeight = TypedValue.complexToDimensionPixelSize(
                    tv.data, getResources().getDisplayMetrics());
            top = top + actionBarHeight;
        }

    } else if (mAnchorRect != null) {
    }

    if (mFlagInvalid)
        init(20, 20, 50, 50);
    else {
        if (mAnchorRect != null) {
            init(mAnchorRect.bottom, mAnchorRect.right, mAnchorRect.left,
                    mAnchorRect.top);
        } else
            init(mAnchorView.getHeight(), mAnchorView.getWidth(), left, top);
    }
}

public void init(int height, int width, int left, int top) {
    mWidth = width;
    mHeight = height;
    mTop = top;
    mBottom = top + height;
    mLeft = left;
    mRight = left + width;

    mLeft = (int) (mLeft + mPaddings[0] * mWidth);
    mTop = (int) (mTop + mPaddings[1] * mHeight);
    mRight = (int) (mRight - mPaddings[2] * mWidth);
    mBottom = (int) (mBottom - mPaddings[3] * mHeight);
    mRect = new Rect(mLeft, mTop, mRight, mBottom);

    invalidate();
}

public Rect getAnchorRect() {
    return mRect;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    initOnceOnDraw();
    canvas.drawRect(mLeftRect, mPaint);
    canvas.drawRect(mTopRect, mPaint);
    canvas.drawRect(mRightRect, mPaint);
    canvas.drawRect(mBottomRect, mPaint);
    canvas.drawRect(mRect, mTempPaint1);
}

private void initOnceOnDraw() {
    if (mReset) {
        mReset = false;
        mTopRect = new Rect(0, 0, getWidth(), mRect.top);
        mLeftRect = new Rect(0, mRect.top, mRect.left, mRect.bottom);
        mRightRect = new Rect(mRect.right, mRect.top, getWidth(),
                mRect.bottom);
        mBottomRect = new Rect(0, mRect.bottom, getWidth(), getHeight());
    }
}}

方法setAnchorView()提供了要在其上绘制覆盖层的视图。

    mWindowView = (WindowView) mTutorialView
                            .findViewById(R.id.windowview_tutorial);
                        mWindowView.setTransparentBackGroundColor(backgroundColor);

                    mWindowView.setAnchorView(view, null, padding);

希望这能有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接