如何使用LayoutInflater / ViewStub来制作覆盖层

3
作为一个不太自信于通过编程改变视图的人,我有以下问题:
在我的应用程序第一次启动时,我想要一个覆盖在主屏幕上的叠加层,告诉用户查看设置,因为有两个关键选项需要用户配置。
我不想使用AlertDialog,也不想使用向导。因此,我决定采取类似Go SMS的方法,在第一次启动时创建一个叠加层。我创建的模型如下所示:
普通菜单: Normal 第一次启动: enter image description here 这些是我遇到的问题:
  1. 就像我说的,我不想在第一次启动时使用屏幕截图覆盖,因为这会占用太多空间,并且不会与语言和屏幕无关。
  2. 我想把圆形作为png,但我不知道如何将其放在图片上方
  3. 文字也有同样的问题
  4. 最后,我想在应用程序上放置一个半透明的白色。它并不一定需要图标的洞口,虽然有这个会很好。

如果您需要布局源代码,可以在pastebin获取。

所以,我只需要在这里开始,如果使用LayoutInflater或ViewStub更好,以及如何实现它,因为我完全没有经验...

谢谢!

/编辑:我上传了一个新的、更加整齐的布局。

2个回答

1

我曾经遇到过类似的问题,一个客户想要一个应用程序的演示,整个屏幕都要变得更白(他们称之为“透明”),除了通过一个覆盖在按钮上的对话框来解释按钮。

幸运的是,你的布局不像我处理的那个那么复杂 :)

现在,你可以用两种方法实现透明效果,一种是设置白色背景并调用所有视图的setAlpha()方法,另一种是创建半透明的白色覆盖层。

如果你选择使用覆盖层,你将需要找到一种方法通过覆盖层显示不透明的按钮。这可能会有点复杂。

如果你选择第一种选项,你只需要在不透明的视图上调用setAlpha(1)来显示它。

setAlpha()方法仅在api版本11以上可用,所以如果你的目标版本较早,你可能需要以稍微复杂的方式实现。

在Honeycomb之前的版本中设置视图透明度的示例:

为你的按钮创建布局(任何样式都可以,只要让它们相似,这样你就可以循环遍历它们):

<LinearLayout 
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <ImageView 
        android:tag="image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/tile"/>
    <TextView 
        android:tag="text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FF000000"
        android:text="button1"/>
</LinearLayout>

在您的程序中,当您想要使按钮透明时:
LinearLayout l = (LinearLayout) findViewById(R.id.button1);
((ImageView)l.findViewWithTag("image")).setAlpha(0x7F);
((TextView)l.findViewWithTag("text")).setTextColor(0x7F000000);



当您决定如何创建透明效果时,您将不得不决定如何显示覆盖文本/气泡。您很可能希望将其放在整个布局的顶部的单独图层中,以确保它不受新视图的影响。
实现此目的的一种方法是将根布局元素更改为FrameLayout,然后在其中创建/显示。例如:

<FrameLayout background="#FFFF"> <!-- white background, just in case -->
    <LinearLayout>
        <!-- the rest of your layout -->
    </LinearLayout>
    <LinearLayout visibility="gone"> <!-- this will be your overlay view -->
        <ImageView /> <!-- the arrow/ring -->
        <TextView /> <!-- the description -->
    </LinearLayout>
</FrameLayout>

当显示介绍时,您将隐藏的覆盖视图的位置设置为要解释的表项的位置,将文本更改为适当的字符串/资源并显示该视图。
当介绍结束时,您将所有按钮的alpha值重置,并将覆盖的可见性再次设置为gone。

非常感谢您的回答!不过,我不知道为什么代码无法运行。您能否提供一些示例代码?(您不必为我编写整个代码) - Force
我添加了一些代码来改变按钮的透明度,因为我意识到setAlpha()只存在于蜂窝版本之后。我会在有时间的时候更新更多示例代码。 - Jave

0

由于我对ViewStub没有太多经验,所以我会使用LayoutInflater。

首先,您需要在当前布局的顶部加载第二个布局。最简单的方法是使用FrameLayout,它有一个子视图是您当前的视图,然后您可以在第一次启动时动态地加载第二个子视图。当您在Activity中加载内容视图时,它将附加到一些已创建的视图(某些DecorView、FrameLayout等)。因此,您可以重用现有的FrameLayout,也可以创建一个新的FrameLayout。我会选择第二种解决方案,因为它更稳定(我只是提到了另一种可能性,以防您想要最小化层数)。

因此,作为第一步,将您当前的布局包装在FrameLayout中,并给它一个id,比如"@id/root"。

然后,在onCreate方法中,您可以像这样编写:

setContentView(R.layout.main);
if (isFirstRun()) {
    ViewGroup parent = (ViewGroup)findViewById(R.id.root); // locate the FrameLayout
    LayoutInflater li = LayoutInflater.from(this); // get an instance of LayoutInflater
    li.inflate(R.layout.overlay, parent);
}

到目前为止,您已经加载了覆盖层。现在轮到您定义覆盖层了。 要创建白化效果,只需在 overlay.xml 布局中的根视图上设置以下属性即可:
android:background="#40ffffff"

为了定位圆形,首先需要找到它的位置。您可以使用View.getLocationOnScreen来获取屏幕上图标(在圆形下方)的绝对坐标。然后您有两个选项:

  • 要么创建自定义视图(用于覆盖),并手动在给定位置绘制圆形
  • 要么使用ImageView添加圆形,并根据坐标调整左侧和顶部边距

谢谢您的回答,但是我无法让LayoutInflater部分工作。无论我做什么或使用什么布局,它都不会显示任何内容... - Force
你可以尝试使用另一个答案的解决方案(即将重叠布局包含在默认布局中,但默认情况下隐藏),或者使用HierarchyViewer来仔细检查层次结构(也许已添加,但由于某些原因不可见)。 - Pal Szasz
我也会继续处理另一个答案 - 但是我真的很想让这个答案起作用。因为LayoutInflater肯定有问题,我也尝试过 LayoutInflater li = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);,但那也不起作用... - Force
这是我如何使用layout.xml和LayoutInflater来创建动态叠加布局的方法。http://stackoverflow.com/questions/3983632/how-to-overlay-a-button-programmatically/14248874#14248874 - Whome

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