Comment créer un écran de démonstration transparent pour une application Android?

105

J'essaie de créer un écran de démonstration semi-transparent qui ne se lance que lorsqu'un utilisateur installe mon application pour la première fois. Voici un exemple de l'application Pulse News:

Galaxy Nexus

Exemple de capture d'écran de Pulse News sur Galaxy Nexus

Nexus One

entrez la description de l'image ici

Au lieu d'une fonction «appuyer pour ignorer», je souhaite que l'utilisateur puisse parcourir quelques pages de démonstration transparentes.

Pour ma première tentative, j'ai modifié un échantillon de la bibliothèque ViewPagerIndicator . J'ai utilisé des PNG semi-transparents dans ImageViews à l'intérieur de chacun des fragments du pager de vue. J'ai ensuite lancé cela comme une «activité de démonstration» dans la méthode onCreate de mon «activité principale».

Problème: «L'activité principale» ne pouvait pas être vue en arrière-plan - à la place, elle était juste noire. J'ai essayé les solutions ici , mais cela n'a pas résolu le problème.

Existe-t-il une meilleure approche pour créer quelque chose comme ça, ou suis-je sur la bonne voie?

J'ai également eu une autre question connexe qui dépend de la façon dont cela est mis en œuvre. J'essaie de superposer du texte et des flèches de manière à ce qu'ils pointent vers des composants d'interface utilisateur particuliers en arrière-plan. En utilisant un PNG contenant le texte et les flèches, il est probable qu'il ne sera pas mis à l'échelle correctement sur différents appareils. Par exemple, les flèches ne pointent pas nécessairement vers le composant d'interface utilisateur correct en arrière-plan. Existe-t-il également un moyen de s'attaquer à ce problème?

Merci!

Voici mon code pour la première tentative:

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);
    }
}
Gautam
la source
Sans regarder votre code, il est difficile de suggérer quoi que ce soit. Si vous pouviez mettre votre code d'activité, cela pourrait vous aider.
Sayyam
11
C'est une bonne question.
con_9

Réponses:

79

Mettez vos informations de démonstration dans une activité différente et donnez-lui le thème suivant.

<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>

Si vous utilisez ActionBarSherlock, passez parentà @style/Theme.Sherlock.

Cela vous donnera une activité transparente, vous pourrez donc voir l'activité en dessous.

Maintenant, je suppose que vous voulez aussi un fond translucide.

Dans la mise en page xml (de votre activité transparente), ajoutez:

android:background="#aa000000" 

Les 6 derniers chiffres définissent la couleur: 000000 est le noir.

Les 2 premiers définissent l'opacité: 00 est 100% transparent, ff est 100% opaque. Alors choisissez quelque chose entre les deux.

Benito Bertoli
la source
1
Merci d'avoir répondu! C'est à peu près ce que j'ai fini par faire, après de nombreux essais et erreurs . Je suis toujours curieux de savoir comment l'écran de démonstration Pulse est capable de `` repositionner '' le contenu superposé aux bons endroits, même sur différentes tailles d'écran - voir les captures d'écran mises à jour. Des idées?
Gautam
2
Dans votre première activité, trouvez la vue sur laquelle vous souhaitez pointer ( findViewById). Obtenez ensuite sa position par rapport à la disposition racine en utilisant cette méthode . Envoyer la position à l'activité de superposition dans l'intention. Faites un alignement correct.
Benito Bertoli
2
Ou utilisez View.getLocationOnScreen(int[] location)ou View.getLocationInWindow(int[] location). Je ne sais pas lequel est le meilleur.
Benito Bertoli
@Gautam: "Des idées?" - pour Pulse, il s'agit de mettre une image dans le coin supérieur gauche, une autre image centrée et une troisième image dans le coin inférieur droit. Une douzaine de lignes XML, basées sur a RelativeLayout, suffiraient.
CommonsWare
1
Cela a fonctionné pour moi, mais j'ai eu des problèmes dans mes activités en prolongeant l'activité. Donc, pour utiliser AppCompatActivity, j'ai défini le style comme ceci: <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
65

Avez-vous regardé ShowcaseView? https://github.com/Espiandev/ShowcaseView .

En utilisant ceci:

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);
Nik
la source
1
Merci, c'est exactement ce que je cherchais.
Snicolas le
Impressionnant! Connaissez-vous quelque chose de similaire pour iOS?
KVISH
Encore obsolète ... Le développeur voulait dire que la conception de l'API de base n'était pas assez bonne (ce qui était partiellement vrai).
Laurent Meyer
J'ai essayé cela et j'ai trouvé qu'il n'y avait pas de balise pour changer les images.
Anshul Tyagi
11

Pulse utilise un RelativeLayout avec quatre ImageView et quatre TextView. Le texte de la capture d'écran est tous TextView avec leur propre police personnalisée.

Dans votre manifeste, ajoutez les éléments suivants à votre activité:

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

Dans votre RelativeLayout externe, ajoutez:

android: background = "# aa000000"

Dans votre fichier 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>    

Un exemple de programmation de la police personnalisée que vous pouvez trouver sur:

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

La disposition de la visionneuse de hiérarchie ressemble à ceci (la boîte rouge est le conteneur RelativeLayout):

entrez la description de l'image ici

poudre366
la source
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();

}
Ravikiran
la source
exactement ce que je recherche pour un appel de méthode simple et direct, et facilement sans contrôler ni empiler les activités. merci
Abhishek Garg
5

Pour cela, vous devez créer une mise en page d'aide en bas de votre mise en page principale ex: (structure)

<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>
Surendar D
la source
2

Enveloppez votre mise en page principale dans un RelativeLayout, puis ajoutez-y une deuxième mise en page, quelque chose comme:

<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>

Je crois que la mise en page de superposition va en dessous de la mise en page principale dans le fichier XML (si la mémoire est bonne). Vous pouvez ensuite créer votre propre mise en page ViewFlipper, tout ce que vous voulez dans cette deuxième mise en page.

Eric
la source
1
Merci pour votre réponse! J'ai essayé cela et cela semble fonctionner. Cependant, il y a un problème - le contenu de la disposition de superposition ne couvre pas l'ActionBar ou les onglets ActionBar que j'ai dans mon activité.
Gautam
Vous avez ajouté le RelativeLayoutau demo_activity.xmlfichier? Et est DemoActivityvotre principal (premier) Activity?
Eric
Eh bien, «DemoActivity» était ma tentative de créer une activité transparente qui ferait la même chose. «MainActivity» est l'activité que je veux en arrière-plan. J'ai donc encapsulé la mise en page pour 'MainActivity', c'est-à-dire 'main_activity.xml' avec le 'RelativeLayout' comme vous l'avez mentionné et j'ai également inséré le 'LinearLayout' transparent. Le problème est que tout le contenu de «main_activity.xml» est affiché sous «ActionBar» et l'un de ses onglets de navigation.
Gautam
1

Créez une nouvelle activité (dites Tutoriel).

Accédez au fichier xml de mise en page de votre activité (activity_tutorial). Sous la mise en page parent, ajoutez "android: background = # 000" et "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>

Maintenant, accédez au fichier manifeste de l'application et sous votre activité de didacticiel, ajoutez l'attribut 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>

C'est tout, maintenant exécutez cette activité en plus de toute autre activité et vous pouvez obtenir les résultats souhaités. Personnalisez, ajoutez du texte, des vues d'images et d'autres éléments pour obtenir l'écran de didacticiel souhaité. À peu près sûr que vous pouvez faire fonctionner un visualiseur avec cette technique.

Ankush Wadhwa
la source
0

Vous pouvez simplement vérifier le code du lanceur Android, car ils le font. Je ne connais pas la mise en œuvre.

Si c'était moi, je le ferais (ne serait-ce qu'une simple superposition) pour que vous ne vissiez pas avec votre mise en page pour votre application, créez simplement votre mise en page de superposition et attachez-la sur la mise en page de votre application en l'ajoutant directement à vos activités WindowManager. Cela peut être aussi simple que d'ajouter un ImageViewau WindowManager, d'écouter les touches sur le ImageView, ou d'avoir un délai d'attente pour supprimer le ImageViewde votre Window.

Jug6ernaut
la source