2013-08-13 19 views
7

Sappiamo tutti che ci sono un sacco di tutorial su come fare una schermata iniziale su Android. Ma sappiamo anche che sono pseudo-splashscreens. Ho cercato per molti e ho sempre visto Thread.sleep(x). Questo non è ben codificato, questo è solo per rendere la bellezza dell'app e sembrare un'app professionale, non è quello che voglio!
Un altro problema con quegli splash screen è che non risolvono il mio problema perché lo mostrano solo dopo l' l'attività inizia e mostra la visualizzazione del contenuto.Come fare uno splash screen ben codificato

Ho un'app che fa un sacco di cose durante l'inizializzazione e quando l'app si avvia l'utente vede uno schermo nero per alcuni secondi, abbastanza tempo per infastidire. Ecco perché voglio mostrare uno splash screen ben codificato che rimuove quella schermata nera che appare prima che la visualizzazione del contenuto sia stata impostata.

Ho provato qualcosa. Ho incluso lo splash screen (uno RelativeLayout) nel layout impostato nello MainActivity, ma per quanto ne so Android mostra solo il contenuto dopo che tutto è stato caricato, quindi se sto cercando di mostrare qualche vista dalla vista del contenuto Devo aspettare che tutto abbia finito. Eppure, io mando il mio codice, può aiutare in qualche modo ...

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    new SplashTask().execute(); 
} 

private class SplashTask extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected void onPreExecute() { 
     initializeViews(); 
     mSplashScreen.setVisibility(View.VISIBLE); 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void params) { 
     Standard.Initiate(MainActivity.this); 
     verifyListStats(); 
     loadListAdapters(); 
     setOnClickListeners(); 
     mSplashScreen.setVisibility(View.GONE); 
    } 

} 

ho provato a caricare alcune risorse in doInBackground(...) ma perché lo faccio alcune operazioni in onResume() che hanno bisogno di tali risorse non posso farlo (o almeno penso di non poterlo fare).

Qualche idea? Ho sentito parlare di un meccanismo integrato simile alle immagini di lancio di iOS, forse questo può essere un modo.

+5

[Do not] (http://cyrilmottier.com/2012/05/03/splash-screens-are-evil-dont-use-them/) – Jonas

+2

Sì @ Jonas mi è piaciuto quell'articolo quando l'ho letto un po 'di tempo fa. È molto meglio mostrare la tua GUI pre-popolata mentre stai aspettando piuttosto che bloccare un utente con una schermata iniziale. –

+0

Se la tua app usa internet puoi verificare la connessione anche sullo schermo di Splas. Questo è utile – NightSkyCode

risposta

5

Quando viene avviata un'attività, Android avvia uno Zigote, un'attività vuota che non fa nulla e imposta il tema dell'attività su di esso, quindi lo avvia. Una volta che l'attività è pronta per la visualizzazione, scambia l'attività visualizzata con la tua. Per maggiori informazioni sulla zigote, si può leggere this article da Cyril Motier

Quindi, per rispondere alla tua domanda, si può fare questo:

  1. creare un piccolo tema che uno sfondo della finestra personalizzato che visualizza le tue informazioni schizzi (si può utilizzare 9 patch per centrare il contenuto non graduato);
  2. Nel file manifest, utilizzare questo tema splash per la propria attività;
  3. nel metodo onCreate() della tua attività, chiama setTheme (R.id.yourActivityTheme) (chiamalo prima di setContentView());
  4. godere ...

In questo modo, il vostro "splash screen" (vale a dire: lo zigote con il tema iniziale) sarà visibile fino a quando la vostra attività è pronto per essere visualizzato.

+0

Semplice ed efficace. Questo è il tipo di cosa che volevo. Funziona perfettamente. Grazie! –

0

ho fatto questo con la creazione di una finestra di chiuderlo quando mi è stato fatto il caricamento iniziale schermo intero

splashDialog = new Dialog(getActivity(), android.R.style.Theme_Black_NoTitleBar_Fullscreen); 
     splashDialog.setContentView(R.layout.yourSplashLayout); 
2

Creare un'attività SplashScreen e dichiarare come predefinita nella vostra applicazione, vale a dire aggiungere questo alla tua AndroidManifest.xml

<activity 
     android:name="package.SplashScreen" 
     android:icon="@drawable/icon" 
     android:label="@string/app_name" 
     android:noHistory="true"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
      <category android:name="android.intent.category.DEFAULT" /> 
     </intent-filter> 
    </activity> 

Nella tua SplashActivity onCreate lanciare un nuovo AsyncTask:

public class SplashScreen extends Activity { 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.splash_image); 

     new InitAsyncTask().execute(); 
    } 

    private class InitAsyncTask extends AsyncTask<?, ?, ?> { 

     protected ? doInBackground(?... params) { 
     // PERFORM YOUR INITIALIZATION HERE 
     } 

     protected void onPostExecute(? result) { 
      // Initialization is completed, close SplashScreen 
      // and launch your MainActivity: 
      SplashScreen.this.finish(); 
      startActivity(new Intent(MainActivity.class, SplashScreen.this); 

    } 
    } 
} 
+1

'AsyncTasks' come le classi interne sono cattive. – Luksprog

+0

@Luksprogless Niente ti impedisce di dichiararlo come statico – Anton

0

Il modo migliore per aprire una schermata iniziale è che è possibile creare una nuova attività per tale attività e quindi in tale attività è possibile impostare un timer per op. it una nuova attività che sarebbe la tua attività principale.Penso che usando questo puoi liberarti dallo schermo nero all'avvio.In manifest fai attività splash come attività di avvio predefinita.Qui è l'esempio: -

SplashActivity. java

public class SplashActivity extends Activity { 

private Timer timer; 

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

@Override 
protected void onResume() { 

    timer = new Timer(); 
      timer.schedule(new TimerTask() { 
       @Override 
       public void run() { 
        Intent intialScreenIntent = new Intent(SplashActivity.this, MainActivity.class); 
        startActivity(intialScreenIntent); 
       } 
      }, 2000l); 
      super.onResume();  
} 


@Override 
public void onBackPressed() { 
    try { 
     timer.cancel(); 
     timer = null; 
    } catch (Exception e) { 
    } 
    super.onBackPressed(); 
}} 
0

Anche io cercavo lo stesso. Alla fine imparo ciò che soddisfa le mie esigenze.

Nota:

  • Fa 'tutto pesante lavoro nel creare sul della vostra seconda attività. Pertanto, quando tutto il lavoro verrà eseguito, l'attività verrà avviata automaticamente dopo la chiamata al numero onStart().
  • È possibile inserire alcuni controlli nello onCreate() se si desidera che il codice venga eseguito solo una volta nella vita dell'applicazione.
  • Non eseguire lavori pesanti nel metodo ApplicationClass onCreate() perché viene eseguito all'avvio dell'applicazione. Quindi durante questa esecuzione c'è uno schermo nero.

Questo è Splash Screen xml:

<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:background="@drawable/splash_screen" 
    tools:context=".SplashScreenActivity"> 
</RelativeLayout> 

Si tratta di attività di classe

public class SplashScreenActivity estende Activity {

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_splash_screen); 
    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      Intent mainIntent = new Intent(SplashScreenActivity.this, 
        MyLauncherActivity.class); 
      SplashScreenActivity.this.startActivity(mainIntent); 
         // SplashScreenActivity.this.finish(); No need to finish it as "noHistory" tag is true in the manifest 
     } 
    }, 1500); 

} 

@Override 
public void onBackPressed() { 
} 
} 

Voci nel manifesto:

<activity 
     android:name="com.wokomoco.test.activities.SplashScreenActivity" 
     android:label="@string/app_name" 
     android:noHistory="true" 
     android:screenOrientation="portrait" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
</activity> 

Spero che questo ti possa aiutare. Goditi la programmazione !!

0

Uno dei miei progetti senza licenza richiedeva una schermata iniziale anche se non era necessaria. Forse può essere utile per il tuo progetto in quanto è basato su un dialogo piuttosto che un'attività. Se la schermata iniziale viene toccata o gestita, verrà ignorata e una volta completata l'animazione (dissolvenza programmata). Potrebbero essere apportate modifiche alla classe in modo da controllare qualche tipo di "stato pronto booleano" prima di consentire il tocco o i gesti per eliminare l'immagine.

file di classe: AppIntro.java

import android.app.Dialog; 
import android.content.Context; 
import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.Window; 
import android.view.animation.Animation; 
import android.view.animation.Animation.AnimationListener; 
import android.view.animation.AnimationUtils; 

public class AppIntro extends Dialog { 
    protected int mLayoutRes = 0; 
    protected int mAnimRes = 0; 
    protected Animation mIntroAnim = null; 
    protected View mLayout = null; 

    public AppIntro(Context aContext, int aLayoutRes, int aAnimRes) { 
     super(aContext); 
     mLayoutRes = aLayoutRes; 
     mAnimRes = aAnimRes; 
    } 

    @Override 
    protected void onCreate(Bundle aSavedState) { 
     super.onCreate(aSavedState); 
     mLayout = LayoutInflater.from(getContext()).inflate(mLayoutRes,null); 
     mLayout.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       AppIntro.this.dismiss(); 
      } 
     }); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(mLayout); 
     mIntroAnim = AnimationUtils.loadAnimation(getContext(),mAnimRes); 
     mIntroAnim.setAnimationListener(new AnimationListener() { 

      @Override 
      public void onAnimationStart(Animation animation) { 
       //nothing to do 
      } 

      @Override 
      public void onAnimationRepeat(Animation animation) { 
       //nothing to do 
      } 

      @Override 
      public void onAnimationEnd(Animation animation) { 
       AppIntro.this.dismiss(); 
      } 
     }); 
    } 

    @Override 
    public boolean onGenericMotionEvent(MotionEvent event) { 
     dismiss(); 
     return true; 
    } 

    @Override 
    public void show() { 
     super.show(); 
     mLayout.startAnimation(mIntroAnim); 
    } 

} 

successivo, definiamo la nostra animazione fade out (modificare la durata di essere ciò che è necessario caricare l'app) nel file "res/anim/intro_anim.xml ". 4200 = 4,2 secondi.

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    > 
    <alpha 
     android:fromAlpha="1.0" android:toAlpha="0.0" 
     android:interpolator="@android:anim/accelerate_interpolator" 
     android:duration="4200" 
     android:repeatCount="0" > 
    </alpha> 
</set> 

Infine, definiamo il nostro layout schermata iniziale (utilizzando qualsiasi immagine (s) che si desidera) in "Layout/intro.xml". La mia particolare schermata iniziale mostrava un titolo app con immagine insieme a 3 loghi di varie fonti di finanziamento.

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/layout_intro" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <TextView 
     android:id="@+id/intro_Text_title" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentTop="true" 
     android:layout_centerHorizontal="true" 
     android:gravity="center" 
     android:text="@string/title_intro" 
     android:textAppearance="?android:attr/textAppearanceLarge" /> 

    <ImageView 
     android:id="@+id/intro_Image_myproject" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_below="@+id/intro_Text_title" 
     android:layout_centerHorizontal="true" 
     android:src="@drawable/intro_image" /> 

    <FrameLayout 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_below="@id/intro_Image_myproject" 
     android:layout_alignRight="@id/intro_Image_myproject" 
     android:layout_alignLeft="@id/intro_Image_myproject"> 

     <ImageView 
      android:id="@+id/intro_Image_logo1" 
      android:layout_width="80dp" 
      android:layout_height="50dp" 
      android:scaleType="fitXY" 
      android:src="@drawable/logo1" 
      android:layout_gravity="left|center_vertical"/> 

     <ImageView 
      android:id="@+id/intro_Image_logo2" 
      android:layout_width="150dp" 
      android:layout_height="wrap_content" 
      android:src="@drawable/logo2" 
      android:layout_gravity="center" 
      android:scaleType="centerInside"/> 

     <ImageView 
      android:id="@+id/intro_Image_logo3" 
      android:layout_width="70dp" 
      android:layout_height="70dp" 
      android:scaleType="fitXY" 
      android:src="@drawable/logo3" 
      android:layout_gravity="right|center_vertical"/> 

    </FrameLayout> 

</RelativeLayout> 

Il codice utilizzato per popup la finestra di dialogo:

@Override 
protected void onCreate(Bundle aSavedState) { 
    super.onCreate(aSavedState); 
    if (aSavedState==null) { 
     //only show splash screen at app start, not on rotate screen 
     new AppIntro(this,R.layout.intro,R.anim.intro_anim).show(); 
    } 
    setContentView(R.layout.main); 
    //...rest of onCreate() 
} 

mia app visualizzata mio punto di vista principale, allo stesso tempo, come la schermata di avvio, quindi nessuna garanzia questa finestra di dialogo verrà visualizzato non appena si chiama .mostrare().

0

Di seguito è riportata l'attività di schermata iniziale che sto utilizzando in tutto il progetto. Si prega di verificare se è utile a voi.

public class SplashActivity extends Activity { 

    private SharedPreferences myPrefs; 
    private SharedPreferences.Editor prefsEditor; 
    private boolean login; 
    private boolean connectivityState; 
    private String connectedNetworkType; 
    private ConnectivityManager connectivityManager; 
    private CheckInternet checkInternet; 
    private File file = new File(API.file_dir); 
    public static Location loc; 
    Configuration newConfig; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.splash_layout); 



     //---------------------- 
     myPrefs = getSharedPreferences("myPrefs", MODE_WORLD_READABLE); 
     boolean login = myPrefs.getBoolean("login", false); 

      checkForInternetAndNextFlow(); 
    } 


    // Check for the Internet Connection 
    private void checkForInternetAndNextFlow() { 

     connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); 
     checkInternet = new CheckInternet(getApplicationContext()); 
     connectivityState = checkInternet.isConnected(connectivityManager); 

     if (connectivityState) { 
      connectedNetworkType = checkInternet.getNetworkType(); 
      // Toast.makeText(getApplicationContext(), "Connected via : " + 
      // connectedNetworkType, Toast.LENGTH_LONG).show(); 

      // check for the login or not from preference 
      myPrefs = this.getSharedPreferences("myPrefs", MODE_WORLD_READABLE); 
      login = myPrefs.getBoolean("login", false); 

      System.out.println("Loging value is:" + login); 
      Thread t = new Thread() { 
       public void run() { 
        try { 
         Thread.sleep(1500); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } finally { 
         if (login) { 
          Intent i = new Intent(SplashActivity.this,MainTabActivity.class); 
          startActivity(i); 
         } else { 
          Intent i = new Intent(SplashActivity.this,LoginActivity.class); 
          startActivity(i); 
         } 
        } 
       } 
      }; 
      t.start(); 

     } else { 
      // Toast.makeText(getApplicationContext(), "NOT connected", 
      // Toast.LENGTH_LONG).show(); 
      final Dialog dialog = new Dialog(SplashActivity.this,R.style.CustomDialogTheme); 
      dialog.getWindow(); 
      dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 
      dialog.setContentView(R.layout.internet_dialog); 
      dialog.setCancelable(false); 

      Button retryBtn = (Button) dialog.findViewById(R.id.retryBtn); 
      Button cancel = (Button) dialog.findViewById(R.id.cancelBtn); 

      retryBtn.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View arg0) { 
        dialog.dismiss(); 
        checkForInternetAndNextFlow(); 
       } 
      }); 

      cancel.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View arg0) { 
        dialog.dismiss(); 
        finish(); 
       } 
      }); 
      dialog.show(); 
     } 

    } 


} 

Spero che ti possa aiutare. Goditi la codifica ...:)

Problemi correlati