12

ich eine benutzerdefinierte Animation für meine Splash Screen-Aktivität entwickelt:Wie können wir diese android benutzerdefinierte Splash-Animation (cpu & RAM) optimieren?

=> Hier ist eine Animation, die zeigt, was passiert:

enter image description here

Natürlich meine echte App:

  • ist mit verschiedenen Bildern (fullhd)
  • ist ein bisschen langsamer im Vergleich zum GIF: 3s für 60 Zwischen Bildschirme.

Mein Designer stellte mir 60 Png-Dateien.

=> Ein Beispiel zur Veranschaulichung:

enter image description here

Mein Ziel ist:

  1. Start von einem zentralen Logo (hier mit SO) mit einem unteren Bild (Apple)
  2. führen Sie eine Morphing-Animation
  3. Ende auf dem Bildschirm wie die Homepage der App

dies ausführen zu können, habe ich ein Multilayer-Layout für die SpashScreenActivity mit:

  • BackGround (unsichtbar): Das Layout der Homepage (MainActivity)
  • Mittelgrund: mit dem Image des Apfels, wird durch die Droid und die bottomBar ersetzt, die
  • frontground wachsen: das logo in einem Image mit dem Slogan in einem Textview

Hier wird der xml-Code für das SpashScreen Layout:

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

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:visibility="invisible" 
     android:orientation="vertical"> 

     <FrameLayout 
      android:id="@+id/fl_logo_top_marge_hidden" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:layout_weight="1" 
      android:visibility="invisible" 
      android:background="@color/colorPrimary" /> 

     <include 
      android:visibility="invisible" 
      android:id="@+id/l_logo_activate_hidden" 
      layout="@layout/part_logo_activate" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" /> 

     <FrameLayout 
      android:visibility="invisible" 
      android:id="@+id/fl_logo_bottom_marge_hidden" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:layout_weight="1" 
      android:background="@color/colorPrimary" /> 

     <fr.millezimsolutions.app.splashanimation.SquareAspectWidthBasedImageView 
      android:visibility="invisible" 
      android:id="@+id/iv_home_hidden" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:scaleType="fitXY" 
      android:src="@drawable/p_log_android" /> 

     <FrameLayout 
      android:visibility="invisible" 
      android:id="@+id/fl_bar_hidden" 
      android:layout_width="match_parent" 
      android:layout_height="@dimen/start_degustation_bar_height" 
      android:background="@color/colorAccent" 
      android:gravity="bottom" /> 
    </LinearLayout> 


    <LinearLayout 
     android:id="@+id/fl_middle" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_alignParentBottom="true" 
     android:background="@color/colorPrimary" 
     android:gravity="bottom" 
     android:orientation="vertical"> 

     <fr.millezimsolutions.app.splashanimation.FitXCropTopImageView 
      android:id="@+id/iv_slogan" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="@color/colorTransparent" 
      android:scaleType="fitStart" 
      android:src="@drawable/p_log_apple" /> 

     <FrameLayout 
      android:id="@+id/fl_logo_bottom_bar" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:background="@color/colorAccent" 
      android:gravity="bottom" /> 

    </LinearLayout> 

    <LinearLayout 
     android:id="@+id/fl_front" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical"> 

     <FrameLayout 
      android:id="@+id/fl_logo_top_layout" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:layout_weight="40" 
      android:background="@color/colorPrimary" /> 

     <FrameLayout 
      android:id="@+id/fl_logo_top_marge" 
      android:layout_width="match_parent" 
      android:layout_height="5dp" 
      android:background="@color/colorTransparent" /> 

     <include 
      android:id="@+id/l_logo_activate" 
      layout="@layout/part_logo_activate" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" /> 

     <FrameLayout 
      android:id="@+id/fl_logo_bottom_marge" 
      android:layout_width="match_parent" 
      android:layout_height="5dp" 
      android:background="@color/colorTransparent" /> 

     <FrameLayout 
      android:id="@+id/fl_logo_bottom_layout" 
      android:layout_width="match_parent" 
      android:layout_height="0dp" 
      android:layout_weight="40" 
      android:background="@color/colorTransparent" /> 
    </LinearLayout> 
</RelativeLayout> 

2 der XML-Code für die oben im Layout (via umfasst)

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@color/colorTransparent" 
    android:gravity="bottom" 
    android:orientation="vertical"> 

    <FrameLayout 
     android:id="@+id/fl_home_marginTop" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" /> 

    <ImageView 
     android:id="@+id/iv_millezimuLogo" 
     android:layout_width="wrap_content" 
     android:layout_height="64dp" 
     android:layout_gravity="center_horizontal" 
     android:layout_marginLeft="@dimen/marge" 
     android:layout_marginRight="@dimen/marge" 
     android:src="@drawable/p_log_so" /> 

    <TextView 
     android:id="@+id/tv_slogan" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_horizontal" 
     android:layout_marginBottom="@dimen/marge_small" 
     android:layout_marginTop="@dimen/marge_small_border" 
     android:gravity="center" 
     android:hint="" 
     android:text="Bonjour" 
     android:textColor="@color/colorAccent" 
     android:textSize="20sp" /> 

    <ImageView 
     android:id="@+id/iv_sponsorLogo" 
     android:layout_width="wrap_content" 
     android:layout_height="50dp" 
     android:layout_gravity="center_horizontal" 
     android:layout_marginLeft="@dimen/marge" 
     android:layout_marginRight="@dimen/marge" 
     android:src="@drawable/p_log_so" 
     android:visibility="gone" /> 

    <TextView 
     android:id="@+id/tv_sponsorLogo" 
     android:layout_width="match_parent" 
     android:layout_height="50dp" 
     android:layout_gravity="center_horizontal" 
     android:layout_marginLeft="@dimen/marge" 
     android:layout_marginRight="@dimen/marge" 
     android:gravity="center" 
     android:textColor="@color/colorAccent" 
     android:textSize="20sp" 
     android:visibility="gone" /> 

    <FrameLayout 
     android:id="@+id/fl_home_marginBottom" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" /> 

</LinearLayout> 

3 Hier ist der Code der Aktivität.

import android.content.Intent; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.PorterDuff; 
import android.graphics.PorterDuffXfermode; 
import android.graphics.Rect; 
import android.os.Bundle; 
import android.os.Handler; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.ViewGroup; 
import android.view.WindowManager; 
import android.widget.FrameLayout; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 

public class SplashScreenActivity extends AppCompatActivity { 

    // Splash screen timer 
    private static int SPLASH_TIME_OUT = 3000; 
    private int finalTopMarge, finalBottomMarge, topMargeDec, bottomMargeInc; 
    long currentTimeStamp; 

    private int[] mSplashAnimFrames = {R.drawable.p_wave_spashscreen_00, R.drawable.p_wave_spashscreen_01, R.drawable.p_wave_spashscreen_02, R.drawable.p_wave_spashscreen_03, R.drawable.p_wave_spashscreen_04, R.drawable.p_wave_spashscreen_05, R.drawable.p_wave_spashscreen_06, R.drawable.p_wave_spashscreen_07, R.drawable.p_wave_spashscreen_08, R.drawable.p_wave_spashscreen_09, 
      R.drawable.p_wave_spashscreen_10, R.drawable.p_wave_spashscreen_11, R.drawable.p_wave_spashscreen_12, R.drawable.p_wave_spashscreen_13, R.drawable.p_wave_spashscreen_14, R.drawable.p_wave_spashscreen_15, R.drawable.p_wave_spashscreen_16, R.drawable.p_wave_spashscreen_17, R.drawable.p_wave_spashscreen_18, R.drawable.p_wave_spashscreen_19, 
      R.drawable.p_wave_spashscreen_20, R.drawable.p_wave_spashscreen_21, R.drawable.p_wave_spashscreen_22, R.drawable.p_wave_spashscreen_23, R.drawable.p_wave_spashscreen_24, R.drawable.p_wave_spashscreen_25, R.drawable.p_wave_spashscreen_26, R.drawable.p_wave_spashscreen_27, R.drawable.p_wave_spashscreen_28, R.drawable.p_wave_spashscreen_29, 
      R.drawable.p_wave_spashscreen_30, R.drawable.p_wave_spashscreen_31, R.drawable.p_wave_spashscreen_32, R.drawable.p_wave_spashscreen_33, R.drawable.p_wave_spashscreen_34, R.drawable.p_wave_spashscreen_35, R.drawable.p_wave_spashscreen_36, R.drawable.p_wave_spashscreen_37, R.drawable.p_wave_spashscreen_38, R.drawable.p_wave_spashscreen_39, 
      R.drawable.p_wave_spashscreen_40, R.drawable.p_wave_spashscreen_41, R.drawable.p_wave_spashscreen_42, R.drawable.p_wave_spashscreen_43, R.drawable.p_wave_spashscreen_44, R.drawable.p_wave_spashscreen_45, R.drawable.p_wave_spashscreen_46, R.drawable.p_wave_spashscreen_47, R.drawable.p_wave_spashscreen_48, R.drawable.p_wave_spashscreen_49, 
      R.drawable.p_wave_spashscreen_50, R.drawable.p_wave_spashscreen_51, R.drawable.p_wave_spashscreen_52, R.drawable.p_wave_spashscreen_53, R.drawable.p_wave_spashscreen_54, R.drawable.p_wave_spashscreen_55, R.drawable.p_wave_spashscreen_56, R.drawable.p_wave_spashscreen_57, R.drawable.p_wave_spashscreen_58, R.drawable.p_wave_spashscreen_59}; 


    private final int C_STOP = 120, C_MOVE = 40, C_BAR = 80; 
    private int bottomBarRatio; 
    private ImageView finalImageView; 
    private int targetWidth, targetHeight; 
    private Rect mImageViewRect; 
    private Paint paint; 
    private Bitmap original; 
    private Bitmap result; 
    private boolean setupOk = false; 
    private ImageView mImageView; 
    private Bitmap mask; 
    private FrameLayout ltm; 
    private FrameLayout lbm; 
    private FrameLayout lbb; 


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

     // Indique que l'ecran est full Screen 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

     ImageManager.create(this); 

    } 


    @Override 
    protected void onResume() { 
     super.onResume(); 
     int delay = SPLASH_TIME_OUT/C_STOP; 
     bottomBarRatio = getResources().getDimensionPixelSize(R.dimen.bar_nav_height)/(C_STOP - C_BAR); 
     runCycle(0, delay); 
    } 


    private void logStamp() { 
     long oldTimeStamp = currentTimeStamp; 
     currentTimeStamp = System.currentTimeMillis(); 
     long delay = currentTimeStamp - oldTimeStamp; 
     Log.v("TIMESTAMP", String.valueOf(delay)); 
    } 

    public void runCycle(final int cycle, final int delay) { 
     if (BuildConfig.DEBUG) 
      logStamp(); 

     Handler cyclic = new Handler(); 
     cyclic.postDelayed(new Runnable() { 

      @Override 
      public void run() { 

       if (cycle >= C_STOP) { 
        closeActivity(); 
       } else { 
        runCycle(cycle + 1, delay); 

        if (cycle >= C_MOVE) { 
         // Copy des hauteurs pour les marges 
         initFinalLogoMargeHeight(); 

         // Decroissance du poid de layout superieur 
         MoveUpLogo(); 

         // bouger la bar 
         if (cycle >= C_BAR) { 
          updateBottomBar(cycle - C_BAR); 
         } 
         findViewById(R.id.fl_front).requestLayout(); 
        } 

        if (setupFinalView()) { 
         if ((cycle % 2) == 0) 
          updateImageViewLight(cycle/2); 
        } 
       } 
      } 

     }, delay); 
    } 


    private boolean setupFinalView() { 
     if (!setupOk) { 
      finalImageView = (ImageView) findViewById(R.id.iv_home_hidden); 
      targetWidth = finalImageView.getWidth(); 
      targetHeight = finalImageView.getHeight(); 
      mImageViewRect = new Rect(0, 0, finalImageView.getWidth(), finalImageView.getHeight()); 
      mImageView = (ImageView) findViewById(R.id.iv_slogan); 
      mImageView.setBackgroundResource(R.drawable.p_log_apple); 

      paint = new Paint(Paint.ANTI_ALIAS_FLAG); 

      ltm = (FrameLayout) findViewById(R.id.fl_logo_top_marge); 
      lbm = (FrameLayout) findViewById(R.id.fl_logo_bottom_marge); 
      lbb = ((FrameLayout) findViewById(R.id.fl_logo_bottom_bar)); 


      if (targetWidth > 0 && targetHeight > 0) { 
       original = ImageManager.decodeSampledBitmapFromResource(getResources(), R.drawable.p_log_android, targetWidth, targetHeight); 
       result = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_4444); 
       setupOk = true; 
      } 
     } 
     return setupOk; 
    } 

    private void MoveUpLogo() { 
     ViewGroup.LayoutParams ltmp = ltm.getLayoutParams(); 
     ltmp.height -= topMargeDec; 

     ViewGroup.LayoutParams lbmp = lbm.getLayoutParams(); 
     lbmp.height += bottomMargeInc; 
    } 


    private void initFinalLogoMargeHeight() { 
     if (finalBottomMarge == 0) { 
      finalTopMarge = findViewById(R.id.fl_logo_top_marge_hidden).getHeight(); 
      topMargeDec = (findViewById(R.id.fl_logo_top_marge).getHeight() - finalTopMarge)/C_BAR; 
      finalBottomMarge = findViewById(R.id.fl_logo_bottom_marge_hidden).getHeight() + findViewById(R.id.fl_bar_hidden).getHeight() + findViewById(R.id.iv_home_hidden).getHeight(); 
      bottomMargeInc = (finalBottomMarge - findViewById(R.id.fl_logo_bottom_marge).getHeight())/C_BAR; 
     } 
    } 

    private void updateBottomBar(int cycle) { 
     LinearLayout.LayoutParams lbbp = (LinearLayout.LayoutParams) lbb.getLayoutParams(); 
     lbbp.height = cycle * bottomBarRatio; 
     lbb.setLayoutParams(lbbp); 
    } 


    private void closeActivity() { 
     overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 
     Intent i = new Intent(SplashScreenActivity.this, MainActivity.class); 
     startActivity(i); 
     finish(); 
     overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 
    } 

    private int getNext(int index) { 
     if (index < (mSplashAnimFrames.length - 1)) 
      index++; 
     else 
      index = mSplashAnimFrames.length - 1; 
     return mSplashAnimFrames[index]; 
    } 


    public void updateImageViewLight(int index) { 

     mask = ImageManager.decodeSampledBitmapFromResource(getResources(), getNext(index), targetWidth, targetHeight); 
     Canvas mCanvas = new Canvas(result); 
     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); 
     mCanvas.drawBitmap(original, null, mImageViewRect, null); 
     mCanvas.drawBitmap(mask, null, mImageViewRect, paint); 
     paint.setXfermode(null); 
     mImageView.setImageBitmap(result); 
    } 

} 

4 Und der Code des Imagemanager für das Verständnis (ich benutze UIL)

public class ImageManager { 


    private static Context context; 

    public static ImageLoader getImageLoader() { 
     return ImageLoader.getInstance(); 
    } 

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                 int reqWidth, int reqHeight) { 

     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.outWidth = reqWidth; 
     options.outHeight = reqHeight; 
     options.inJustDecodeBounds = true; 
     options.inPreferredConfig = Bitmap.Config.RGB_565; 
     BitmapFactory.decodeResource(res, resId, options); 

     // Calculate inSampleSize 
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     // Decode bitmap with inSampleSize set 
     options.inJustDecodeBounds = false; 
     return getResourceImageForCanvas(resId, new ImageSize(reqWidth, reqHeight)); 
    } 

    public static int calculateInSampleSize(
      BitmapFactory.Options options, int reqWidth, int reqHeight) { 
     // Raw height and width of image 
     final int height = options.outHeight; 
     final int width = options.outWidth; 
     int inSampleSize = 1; 

     if (height > reqHeight || width > reqWidth) { 

      final int halfHeight = height/2; 
      final int halfWidth = width/2; 

      // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
      // height and width larger than the requested height and width. 
      while ((halfHeight/inSampleSize) > reqHeight 
        && (halfWidth/inSampleSize) > reqWidth) { 
       inSampleSize *= 2; 
      } 
     } 

     return inSampleSize; 
    } 



    public static Bitmap getResourceImageForCanvas(int bitmapResourceId, ImageSize targetImageSize) { 
     DisplayImageOptions options = new DisplayImageOptions.Builder().bitmapConfig(Bitmap.Config.RGB_565).build(); 
     return getImageLoader().loadImageSync("drawable://" + bitmapResourceId, targetImageSize, options); 
// 
    } 

    public static void create(Context context) { 
     try { 
      ImageManager.context = context; 
      initImageLoader(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    private static void initImageLoader() throws IOException { 
     // Create global configuration and initialize ImageLoader with this 
     // configuration 

     BitmapFactory.Options opt = new BitmapFactory.Options(); 
     // opt.inScaled = false; 
     opt.inSampleSize = 1; 
     opt.inDither = true; 
     opt.inPreferredConfig = Bitmap.Config.RGB_565; 
     opt.inPreferQualityOverSpeed = false; 

     DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()./* cacheInMemory(true). */cacheOnDisk(true).decodingOptions(opt).imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) 
       .bitmapConfig(Bitmap.Config.RGB_565).build(); 

     ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context).defaultDisplayImageOptions(defaultOptions).memoryCacheSizePercentage(13).writeDebugLogs().build(); 
     ImageLoader.getInstance().init(config); 
    } 

} 

STATUS:

Die updateImageViewLight Methode beweisbar anderen helfen kann mit dieser Art von Verhalten umgehen (PortedDuff ...) das war nicht leicht zu finden.

Die Animation funktioniert gut auf einem leistungsfähigen Gerät, aber oft verzögert, wenn das Gerät oder die App etwas anderes tut.

Ich habe versucht, diese Berechnung in Async Aufgabe zu laufen, aber es war weniger stark als in dem Mainthread

FRAGEN:

Ich bin für jede gebildete Beratung über meine Implementierung suchen, die helfen können zu verbessern:

  • Speicherverbrauch
  • CPU-Auslastung

Aber auch:

  • potenzieller Leck
  • Lesbarkeit des Codes
+0

@Rod_Algonquin, in dem Sinn, Zeit beim ersten Zyklus nehmen es ist besser in der Leistung? – Anthony

+0

Wäre es nicht ein Video-Stream macht CPU-Ressourcen am meisten frei, weil es auf GPU beschleunigt werden kann? –

+0

Die Antwort ist wahrscheinlich ja, aber der Inhalt kann sich ändern (zB "bonjour"), so dass es auf Programmebene gehandhabt werden muss. Und ich bin mir nicht sicher, ob das Layout immer zu einem Pre-Recorder-Video passt. – Anthony

Antwort

2

noch nicht vollständig beantworten, aber es ist ein Versuch, das muss fortgesetzt und kommentiert werden.

Erste Optimierung:

  • Erstellen Sie eine benutzerdefinierte Ansicht (hier ImageView Erweiterung) für die Welle, die auf onDraw Methode
  • definieren const Mitglied als static final Klasse Mitglieder
  • wie die meisten neu geladen zu möglich, Vermeidung der Objektinstanzenerstellung in onDraw (Canvas und Paint) sowie unnötiges Objektupdate
  • Hier

ist der Code des Custom des Image erstreckt

public class WaveFillingImageView extends ImageView { 

    private final static int[] mSplashAnimFrames = {R.drawable.p_wave_spashscreen_00, R.drawable.p_wave_spashscreen_01, R.drawable.p_wave_spashscreen_02, R.drawable.p_wave_spashscreen_03, R.drawable.p_wave_spashscreen_04, R.drawable.p_wave_spashscreen_05, R.drawable.p_wave_spashscreen_06, R.drawable.p_wave_spashscreen_07, R.drawable.p_wave_spashscreen_08, R.drawable.p_wave_spashscreen_09, 
      R.drawable.p_wave_spashscreen_10, R.drawable.p_wave_spashscreen_11, R.drawable.p_wave_spashscreen_12, R.drawable.p_wave_spashscreen_13, R.drawable.p_wave_spashscreen_14, R.drawable.p_wave_spashscreen_15, R.drawable.p_wave_spashscreen_16, R.drawable.p_wave_spashscreen_17, R.drawable.p_wave_spashscreen_18, R.drawable.p_wave_spashscreen_19, 
      R.drawable.p_wave_spashscreen_20, R.drawable.p_wave_spashscreen_21, R.drawable.p_wave_spashscreen_22, R.drawable.p_wave_spashscreen_23, R.drawable.p_wave_spashscreen_24, R.drawable.p_wave_spashscreen_25, R.drawable.p_wave_spashscreen_26, R.drawable.p_wave_spashscreen_27, R.drawable.p_wave_spashscreen_28, R.drawable.p_wave_spashscreen_29, 
      R.drawable.p_wave_spashscreen_30, R.drawable.p_wave_spashscreen_31, R.drawable.p_wave_spashscreen_32, R.drawable.p_wave_spashscreen_33, R.drawable.p_wave_spashscreen_34, R.drawable.p_wave_spashscreen_35, R.drawable.p_wave_spashscreen_36, R.drawable.p_wave_spashscreen_37, R.drawable.p_wave_spashscreen_38, R.drawable.p_wave_spashscreen_39, 
      R.drawable.p_wave_spashscreen_40, R.drawable.p_wave_spashscreen_41, R.drawable.p_wave_spashscreen_42, R.drawable.p_wave_spashscreen_43, R.drawable.p_wave_spashscreen_44, R.drawable.p_wave_spashscreen_45, R.drawable.p_wave_spashscreen_46, R.drawable.p_wave_spashscreen_47, R.drawable.p_wave_spashscreen_48, R.drawable.p_wave_spashscreen_49, 
      R.drawable.p_wave_spashscreen_50, R.drawable.p_wave_spashscreen_51, R.drawable.p_wave_spashscreen_52, R.drawable.p_wave_spashscreen_53, R.drawable.p_wave_spashscreen_54, R.drawable.p_wave_spashscreen_55, R.drawable.p_wave_spashscreen_56, R.drawable.p_wave_spashscreen_57, R.drawable.p_wave_spashscreen_58, R.drawable.p_wave_spashscreen_59}; 
    private Paint paint; 
    private long nextDrawTimeStamp; 
    private boolean init = false, isStarted = false; 
    private Bitmap original, result; 
    private Rect mImageViewRect; 
    private int index = 0; 
    private LogAndStat las; 
    private Canvas mCanvas; 
    private final int timeTick = 50; 

    public WaveFillingImageView(Context context) { 
     super(context); 
     init(context); 
    } 

    public WaveFillingImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context); 
    } 

    public WaveFillingImageView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(context); 
    } 

    @DebugLog 
    private void init(Context context) { 
     paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); 
     las = new LogAndStat("View", mSplashAnimFrames.length); 
    } 

    public void start() { 
     isStarted = true; 
     nextDrawTimeStamp = System.currentTimeMillis(); 
     invalidate(); 
    } 

    @DebugLog 
    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     // Before Layout 
     if (getWidth() == 0 || getHeight() == 0) 
      return; 
     // Init variables 
     if (!init) { 
      las.logStamp("init onDraw"); 
      original = ImageManager.decodeSampledBitmapFromResourcewithUIL(getResources(), R.drawable.p_log_android, getWidth(), getHeight()); 
      result = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444); 
      mCanvas = new Canvas(result); 
      mImageViewRect = new Rect(0, 0, getWidth(), getHeight()); 
      init = true; 
      las.logStamp("init onDraw"); 

     } 
     // If tick reached for refresh 
     if (System.currentTimeMillis() >= nextDrawTimeStamp) { 
      nextDrawTimeStamp += timeTick; 
      las.logStamp(index); 
      Bitmap mask = ImageManager.decodeSampledBitmapFromResourcewithUIL(getResources(), getResourceForNextCycle(index), mImageViewRect.width(), mImageViewRect.height()); 
      mCanvas.drawBitmap(original, null, mImageViewRect, null); 
      mCanvas.drawBitmap(mask, null, mImageViewRect, paint); 
      canvas.drawBitmap(result, 0, 0, null); 

      index++; 
     } 
     if (isStarted) 
      // Invalidate during animation to call again on Draw 
      if (index < mSplashAnimFrames.length) { 
       las.logStamp("invalidate"); 
       invalidate(); 
      } else { 
       las.logStats(); 
      } 
    } 

    @DebugLog 
    private int getResourceForNextCycle(int index) { 
     if (index < (mSplashAnimFrames.length - 1)) 
      index++; 
     else 
      index = mSplashAnimFrames.length - 1; 
     return mSplashAnimFrames[index]; 
    } 

    @DebugLog 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, widthMeasureSpec); 
    } 
    } 

Ergebnisse:

  • Animation, erstickt, und scheint weniger Ressourcen nehmen. Es ist jedoch völlig nicht synchron mit der Layoutanimation. Müssen Sie das tun. Irgendwelche Best Practices?
  • Dies ist eindeutig der init Schritt des onDraw Methode, die
  • Arbeiten auf temporäre Leinwand, um schließlich die Leinwand zu ziehen auf der Hauptansicht Leinwand verbessert wird viel