Come si crea una schermata demo trasparente per un'app Android?


105

Sto cercando di creare una schermata demo semitrasparente che viene avviata solo quando un utente installa per la prima volta la mia applicazione. Ecco un esempio dall'app Pulse News:

Galaxy Nexus

Schermata di esempio da Pulse News su Galaxy Nexus

Nexus One

inserisci qui la descrizione dell'immagine

Invece di una funzione "tocca per chiudere", voglio che l'utente sia in grado di scorrere un paio di pagine demo così trasparenti.

Per il mio primo tentativo, ho modificato un campione dalla libreria ViewPagerIndicator . Ho usato PNG semitrasparenti in ImageViews all'interno di ciascuno dei frammenti del cercapersone della vista. L'ho quindi lanciato come "attività demo" nel metodo onCreate della mia "attività principale".

Problema: "l'attività principale" non era visibile sullo sfondo, ma era solo nera. Ho provato le soluzioni qui , ma questo non ha risolto il problema.

C'è un approccio migliore per creare qualcosa di simile o sono sulla strada giusta?

Avevo anche un'altra domanda correlata che dipende da come viene implementata. Sto cercando di sovrapporre testo e frecce in modo che puntino a particolari componenti dell'interfaccia utente in background. Utilizzando un PNG che ha il testo e le frecce, è probabile che non venga ridimensionato correttamente su dispositivi diversi. Ad esempio, le frecce potrebbero non puntare necessariamente al componente dell'interfaccia utente corretto in background. C'è un modo per affrontare anche questo problema?

Grazie!

Ecco il mio codice per il primo tentativo:

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);
    }
}

Senza guardare il tuo codice è difficile suggerire qualcosa. Se potessi inserire il tuo codice attività, potrebbe essere d'aiuto.
Sayyam

11
questa è una buona domanda.
con_9

Risposte:


79

Metti le tue informazioni sulla demo in un'attività diversa e assegnale il seguente tema.

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

Se stai usando ActionBarSherlock cambia parentin @style/Theme.Sherlock.

Questo ti darà un'attività trasparente, così sarai in grado di vedere l'attività sottostante.

Ora immagino che tu voglia anche uno sfondo traslucido.

Nel layout xml (della tua attività trasparente) aggiungi:

android:background="#aa000000" 

Le ultime 6 cifre definiscono il colore: 000000 è il nero.

I primi 2 definiscono l'opacità: 00 è trasparente al 100%, ff è opaco al 100%. Quindi scegli una via di mezzo.


1
Grazie per la risposta! Questo è più o meno quello che ho finito per fare, dopo molti tentativi ed errori . Sono ancora curioso di sapere come la schermata demo di Pulse sia in grado di "riposizionare" il contenuto sovrapposto nei posti giusti, anche su schermi di dimensioni diverse - guarda gli screenshot aggiornati. Qualche idea?
Gautam

2
Nella tua prima attività trova la vista che desideri puntare ( findViewById). Quindi ottieni la sua posizione rispetto al layout principale usando questo metodo . Invia la posizione all'attività di sovrapposizione nell'intento. Eseguire il corretto allineamento.
Benito Bertoli

2
Oppure usa View.getLocationOnScreen(int[] location)o View.getLocationInWindow(int[] location). Non sono sicuro di quale sia il migliore.
Benito Bertoli

@Gautam: "Qualche idea?" - per Pulse, si tratta di mettere un'immagine nell'angolo in alto a sinistra, un'altra immagine al centro e una terza immagine nell'angolo in basso a destra. Una dozzina di righe di XML, basate su a RelativeLayout, sarebbero sufficienti.
CommonsWare

1
Questo ha funzionato per me, ma ho avuto problemi nelle mie attività nel prolungare l'attività. Quindi, per utilizzare AppCompatActivity, ho definito lo stile in questo modo: <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

Hai guardato ShowcaseView? https://github.com/Espiandev/ShowcaseView .

Usando questo:

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

1
Grazie, è esattamente quello che stavo cercando.
Snicolas

Eccezionale! Conosci qualcosa di simile per iOS?
KVISH

Deprecato ancora ... Lo sviluppatore intendeva che il design dell'API di base non era abbastanza buono (il che era parzialmente vero).
Laurent Meyer

Ho provato questo e ho scoperto che non ci sono tag per cambiare le immagini.
Anshul Tyagi

11

Pulse utilizza un RelativeLayout con quattro ImageView e quattro TextView. Il testo nella schermata è tutto TextView con il proprio carattere personalizzato.

Nel tuo manifest aggiungi quanto segue alla tua attività:

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

Nel tuo RelativeLayout esterno aggiungi:

Android: background = "# aa000000"

Al tuo file 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 esempio su come programmare il carattere personalizzato che puoi trovare su:

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

Il layout dal visualizzatore della gerarchia ha questo aspetto (la casella rossa è il contenitore RelativeLayout):

inserisci qui la descrizione dell'immagine


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();

}

esattamente quello che cerco semplice e diretto e facilmente chiamare il metodo senza controllare o impilare le attività. grazie
Abhishek Garg

5

Per questo è necessario creare il layout della guida nella parte inferiore del layout principale, ad esempio: (struttura)

<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

Avvolgi il tuo layout principale in un RelativeLayout, quindi aggiungi un secondo layout a quello, qualcosa come:

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

Credo che il layout overlay vada sotto il layout principale nel file XML (se la memoria serve). È quindi possibile creare il proprio layout ViewFlipper, qualunque cosa si desideri all'interno di questo secondo layout.


1
Grazie per la risposta! Ho provato questo e sembra funzionare. Tuttavia, c'è un problema: il contenuto nel layout overlay non copre le schede ActionBar o ActionBar che ho nella mia attività.
Gautam

Hai aggiunto il RelativeLayoutal demo_activity.xmlfile? Ed è il DemoActivitytuo principale (primo) Activity?
Eric

Bene "DemoActivity" è stato il mio tentativo di creare un'attività trasparente che avrebbe fatto la stessa cosa. "MainActivity" è l'attività che voglio sotto in background. Quindi ho inserito il layout per "MainActivity", cioè "main_activity.xml" con "RelativeLayout" come hai menzionato e ho anche inserito il trasparente "LinearLayout". Il problema è che tutto il contenuto in "main_activity.xml" è mostrato sotto "ActionBar" e una delle sue schede di navigazione.
Gautam

1

Crea una nuova attività (ad esempio Tutorial).

Vai al file xml del layout della tua attività (activity_tutorial). Sotto il layout principale, aggiungi "android: background = # 000" e "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>

Ora vai al file manifest dell'applicazione e sotto l'attività del tutorial aggiungi l'attributo 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>

Ecco fatto, ora esegui questa attività in cima a qualsiasi altra attività e puoi ottenere i risultati desiderati. Personalizza, aggiungi testo, visualizzazioni di immagini e altro per ottenere la schermata del tutorial desiderata. Abbastanza sicuro che puoi far funzionare un viewpager con questa tecnica.


0

Potresti semplicemente controllare il codice di avvio di Android, mentre lo fanno. Non so là implementazione.

Se fossi stato io, lo farei (se fosse solo un semplice overlay) in modo da non rovinare il layout per la tua applicazione, basta creare il tuo layout overlay e collegarlo al layout dell'applicazione aggiungendolo direttamente con le tue attività WindowManager. Potrebbe essere semplice come aggiungere un ImageViewa WindowManager, ascoltare i tocchi ImageViewo avere un timeout per rimuoverlo ImageViewdal tuo Window.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.