如何为Android应用创建透明演示屏幕?

106
我将尝试创建一个半透明的演示屏幕,只有在用户首次安装我的应用程序时才会启动。以下是Pulse News应用程序的示例:
Galaxy Nexus

Example screenshot from Pulse News on Galaxy Nexus

Nexus One

enter image description here

我希望用户能够通过滑动几个透明的演示页面,而不是使用“点击即消失”功能。

在我的第一次尝试中,我修改了ViewPagerIndicator库中的一个示例。我在每个视图分页器的片段中使用了半透明的PNG图像视图。然后,在“主要活动”的onCreate方法中启动了这个作为“演示活动”。

问题:无法看到“主要活动”背景 - 只有黑色。我尝试了here的解决方案,但没有解决问题。

是否有更好的方法来创建这样的东西,或者我正在正确的轨道上?

我还有另一个相关的问题,它取决于如何实现。我正在尝试覆盖文本和箭头,使它们指向背景中的特定UI组件。通过使用具有文本和箭头的PNG,很可能在不同设备上无法正确缩放。也就是说,箭头可能不会指向背景中的正确UI组件。是否有方法来解决这个问题?

谢谢!以下是我的第一次尝试的代码:

这是我第一次尝试的代码:

DemoActivity.java

public class DemoActivity extends FragmentActivity {
    DemoFragmentAdapter mAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.demo_activity);

        mAdapter = new DemoFragmentAdapter(getSupportFragmentManager());

        mPager = (ViewPager)findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);
        //mPager.setAlpha(0);

        UnderlinePageIndicator indicator = (UnderlinePageIndicator)findViewById(R.id.indicator);
        indicator.setViewPager(mPager);
        indicator.setFades(false);
        mIndicator = indicator;
    }

}

DemoFragmentAdapter.java

class DemoFragmentAdapter extends FragmentPagerAdapter {
    protected static final int[] CONTENT = new int[] { R.drawable.demo1, R.drawable.demo2, R.drawable.demo3, R.drawable.demo4};

    private int mCount = CONTENT.length;

    public DemoFragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return DemoFragment.newInstance(CONTENT[position % CONTENT.length]);
    }

    @Override
    public int getCount() {
        return mCount;
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    } }

DemoFragment.java

public final class DemoFragment extends Fragment {
    private static final String KEY_CONTENT = "TestFragment:Content";

    public static DemoFragment newInstance(int content) {
        DemoFragment fragment = new DemoFragment();
        fragment.mContent = content;
        return fragment;
    }

    private int mContent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if ((savedInstanceState != null) && savedInstanceState.containsKey(KEY_CONTENT)) {
            mContent = savedInstanceState.getInt(KEY_CONTENT);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        ImageView image = new ImageView(getActivity());
        image.setBackgroundResource(mContent);

        LinearLayout layout = new LinearLayout(getActivity());
        layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        layout.setGravity(Gravity.CENTER);
        layout.addView(image);

        return layout;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_CONTENT, mContent);
    }
}

没有看到你的代码,很难给出建议。如果你能提供你的活动代码,那可能会有所帮助。 - Sayyam
11
这是个好问题。 - con_9
8个回答

80

将您的演示信息放在另一个活动中,并给它以下主题。

<style name="Transparent" parent="@android:style/Theme.NoTitleBar">
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>      
    <item name="android:backgroundDimEnabled">false</item>
</style>

如果您正在使用ActionBarSherlock,请将parent更改为@style/Theme.Sherlock

这将为您提供一个透明的活动,因此您将能够看到其下面的活动。

现在我猜想您也想要一个半透明的背景。

在xml布局中(透明活动的布局)添加:

android:background="#aa000000" 

最后6个数字定义了颜色:000000代表黑色。

前两个数字定义了不透明度:00表示100%透明,ff表示100%不透明。因此,请选择介于两者之间的数值。


1
谢谢你的回答!这基本上就是我最终做出来的,经过了很多试错。我仍然很好奇Pulse演示屏是如何能够在不同的屏幕尺寸上“重新定位”覆盖内容到正确的位置的 - 请参见更新后的截图。有什么想法吗? - Gautam
2
在你的第一个活动中找到你希望指向的视图(findViewById)。然后使用这个方法获取它相对于根布局的位置。将位置通过意图发送到叠加活动中。进行适当的对齐。 - Benito Bertoli
2
或者使用 View.getLocationOnScreen(int[] location)View.getLocationInWindow(int[] location)。我不确定哪一个更好。 - Benito Bertoli
这是不添加库或使现有活动过于复杂的最佳解决方案。+1。 - rupps
1
这对我有用,但我在扩展Activity时遇到了问题。为了使用AppCompatActivity,我定义了以下样式:<style name="Transparent" parent="Theme.AppCompat"> <item name="android:windowContentOverlay">@null</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowNoTitle">true</item> <item name="android:backgroundDimEnabled">false</item> </style> - Jose Q
显示剩余4条评论

65

你看过 ShowcaseView 吗?https://github.com/Espiandev/ShowcaseView.

使用这个:

View showcasedView = findViewById(R.id.view_to_showcase);
ViewTarget target = new ViewTarget(showcasedView);
ShowcaseView.insertShowcaseView(target, this, R.string.showcase_title, R.string.showcase_details);

太棒了!你知道有没有类似的iOS应用吗? - KVISH
虽然已经被弃用,但开发人员的意思是基本API的设计不够好(这在某种程度上是正确的)。 - Laurent Meyer
我尝试了这个,发现没有标签可以更改图片。 - Anshul Tyagi

11

Pulse使用一个RelativeLayout布局,其中包含四个ImageView和四个TextView。 屏幕截图中的文本都是带有自定义字体的TextView。

在您的Manifest文件中添加以下Activity元素:

android:theme="@style/Theme.Transparent"

在外部RelativeLayout中添加以下元素:

android:background="#aa000000"

将以下代码添加到您的styles.xml文件中:

<style name="Theme.Transparent" parent="android:Theme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">false</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>    

这里有一个编写自定义字体的示例:

https://github.com/commonsguy/cw-android/tree/master/Fonts/FontSampler/

从Hierarchy Viewer中查看的布局如下所示(红框是RelativeLayout容器):

enter image description here


6
setContentView(R.layout.sample_main);
showOverLay();

private void showOverLay(){

    final Dialog dialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar);

    dialog.setContentView(R.layout.transparent);

    RelativeLayout layout = (RelativeLayout) dialog.findViewById(R.id.transparent);

    layout.setOnClickListener(new View.OnClickListener() {

        @Override

        public void onClick(View arg0) {

            dialog.dismiss();

        }

    });

    dialog.show();

}

我正在寻找的是简单直接、易于调用且无需控制或堆叠活动的方法。谢谢。 - Abhishek Garg

5
为此,您需要在主布局底部创建帮助布局。 例如:(结构)
<Parent layout>

<Layout 1>(Linear,Relative,....)
  Main layout
  your view...
</Layout 1>

<Layout help>
  set #70000000 as background of this layout 
  #70(transparent range can change) 000000(black)
  and height and width as fillparent
</Layout help>

</Parent layout>

2

将您的主要布局包装在 RelativeLayout 中,然后在其中添加第二个布局,类似于以下内容:

<RelativeLayout
    .... >

    <LinearLayout
        .... >

        <!-- Contents of your main layout -->

    </LinearLayout>

    <LinearLayout
        ....
        android:background="#44000000" > <!-- This is alpha 68/255, black -->

        <!-- Contents of your overlay layout -->

    </LinearLayout>

</RelativeLayout>

我相信叠加布局在XML文件中位于主要布局下方(如果我的记忆没有出错的话)。然后,您可以在这个第二个布局中创建自己的布局、ViewFlipper或其他任何您想要的内容。


1
谢谢您的回复!我尝试了这个方法,似乎可以解决问题。但是,有一个问题 - 在覆盖布局中的内容并没有覆盖我的活动中的ActionBar或ActionBar选项卡。 - Gautam
你将RelativeLayout添加到了demo_activity.xml文件中吗?而且DemoActivity是你的主(第一个)Activity吗? - Cat
“DemoActivity”是我尝试创建一个透明活动来执行相同操作的尝试。 “MainActivity”是我想要在后台的活动。因此,我使用您提到的“RelativeLayout”包装了“MainActivity”的布局,即“main_activity.xml”,并插入了透明的“LinearLayout”。问题是,“main_activity.xml”中的所有内容都显示在“ActionBar”及其任何导航选项卡下方。 - Gautam

1

创建一个新的活动(比如说教程)。

进入你的活动布局xml文件(activity_tutorial)。 在父布局下添加 "android:background= #000" 和 "android:alpha= "0.5"。

<RelativeLayout 
    
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
                
                
    tools:context=".Tutorial_Activity" 
    android:background="#000"
    android:alpha="0.5">
  ..................................................
  ....................................................
  .............................................
  ...............................................
  
  </RelativeLayout>

现在,打开应用程序清单文件,在您的教程活动下添加属性 android:theme="@android:style/Theme.Translucent.NoTitleBar">。

<application>
 .........................................
..........................................
....................................
..........................................

<activity
            android:name="com.aird.airdictionary.Tutorial_Activity"
            android:label="@string/title_activity_tutorial"
            
          android:theme="@android:style/Theme.Translucent.NoTitleBar">
  
        </activity>
    </application>

</manifest>

就这样,现在在任何其他活动的顶部运行此活动,即可获得所需结果。 自定义、添加文本、图像视图和其他内容,以获得所需的教程屏幕。 相信您可以通过此技术使视图翻页器正常工作。


0

你可以查看Android启动器代码,因为他们这样做。我不知道他们的实现方式。

如果是我的话,我会(如果只是一个简单的覆盖层)这样做,以便您不会干扰应用程序的布局,只需创建覆盖层布局,并通过直接添加到您的活动 WindowManager 将其附加在应用程序布局上。可能只需要向 WindowManager 添加一个 ImageView ,监听 ImageView 上的触摸事件,或者设置超时时间来从您的 Window 中删除 ImageView


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