English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Realizzazione dell'effetto 'Shui You You' di Alipay con View personalizzata di Android

Questo articolo introduce la creazione di una View personalizzata con animazioni di proprietà per ottenere l'effetto seguente

L'idea di implementazione è piuttosto semplice:

  • Disegna un cerchio semi-trasparente
  • Realizza due effetti animazione, espansione al click e rimpicciolimento quando non si clicca
  • Combina i due passaggi precedenti utilizzando un thread

Prima di tutto, guardiamo la parte di disegno del cerchio semi-trasparente

public class ClickCircleView extends View {
 private Bitmap bitmap;
 private Paint paint;
 private Canvas canvas;
 private boolean isSpreadFlag = false;// Segnala se l'emissione è completata
 public boolean isSpreadFlag() {
  return isSpreadFlag;
 }
 public void setIsSpreadFlag(boolean isSpreadFlag) {
  this.isSpreadFlag = isSpreadFlag;
 }
 public ClickCircleView(Context context, int width, int height, int screenWidth, int screenHeight) {
  super(context);
  bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888); // Imposta le dimensioni del bitmap
  canvas = new Canvas();
  canvas.setBitmap(bitmap);
  paint = new Paint(Paint.DITHER_FLAG);
  paint.setAntiAlias(true);
  paint.setColor(Color.WHITE);
  paint.setStyle(Paint.Style.FILL);
  paint.setAlpha(50);
  canvas.drawCircle(screenWidth / 2, screenHeight / 2, width / 2 + 10, paint);
  invalidate();
 }
 @Override
 protected void onDraw(Canvas canvas) {
  canvas.drawBitmap(bitmap, 0, 0, null);
 }
}

puoi vedere che le proprietà pertinenti sono impostate sulla penna, quindi si chiama direttamente il metodo drawCircle() del canvas per disegnare un cerchio trasparente, infine si chiama invalidate() per aggiornare la View
è assolutamente necessario sovrascrivere il metodo onDraw() della superclasse, altrimenti la View personalizzata non funzionerà
abbiamo impostato un flag isSpreadFlag, il cui scopo è quello di indicare se l'animazione di espansione è stata completata

quindi implementiamo due effetti di animazione

quando cliccato, l'animazione di espansione

<set xmlns:android="http://schemas.android.com/apk/res/android">
 <objectAnimator
  android:duration="1000"
  android:propertyName="scaleY"
  android:valueFrom="1.0"
  android:valueTo="1.8"
  android:valueType="floatType" />
 <objectAnimator
  android:duration="1000"
  android:propertyName="scaleX"
  android:valueFrom="1.0"
  android:valueTo="1.8"
  android:valueType="floatType" />
</set>

è molto semplice, si tratta solo di modificare il valore di scale, aumentandolo di 1.8 volte

quando non cliccato, l'animazione di espansione e recupero

<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:ordering="together">
 <objectAnimator
  android:duration="1000"
  android:propertyName="scaleX"
  android:valueFrom="1.0"
  android:valueTo="1.2"
  android:valueType="floatType" />
 <objectAnimator
  android:duration="1000"
  android:propertyName="scaleY"
  android:valueFrom="1.0"
  android:valueTo="1.2"
  android:valueType="floatType" />
 <objectAnimator
  android:duration="1000"
  android:propertyName="scaleX"
  android:startOffset="1000"
  android:valueFrom="1.2"
  android:valueTo="1.0"
  android:valueType="floatType" />
 <objectAnimator
  android:duration="1000"
  android:propertyName="scaleY"
  android:startOffset="1000"
  android:valueFrom="1.2"
  android:valueTo="1.0"
  android:valueType="floatType" />
</set>

Simile all'animazione precedente, il parametro startOffset può essere utilizzato per controllare l'ordine di esecuzione dell'animazione, ad esempio in Android:startOffset=”1000” significa che l'animazione viene eseguita con un ritardo di 1 secondo

Poi è la parte in cui si eseguono animazioni e logica tramite thread

parte dell'animazione quando non si clicca

mXiuyixiuButton.post(new Runnable() {
   @Override
   public void run() {
    clickCircleView = new ClickCircleView(CustomView1.this, mXiuyixiuButton.getWidth())
      , mXiuyixiuButton.getHeight(), mXiuyixiuLayout.getMeasuredWidth(),
      mXiuyixiuLayout.getMeasuredHeight());
    clickCircleView.setVisibility(View.VISIBLE);
    mXiuyixiuLayout.addView(clickCircleView);
    mXiuyixiuLayout.postInvalidate();
    // Carica l'animazione
    final Animator anim = AnimatorInflater.loadAnimator(CustomView1.this,
      R.animator.circle_scale_animator);
    anim.addListener(new AnimatorListenerAdapter() {
     @Override
     public void onAnimationEnd(Animator animation) {
      if (anim != null) {
       anim.start(); // Esegui l'animazione in modo ciclico
      }
     }
    });
    anim.setTarget(clickCircleView);
    anim.start();
   }
  });

Dopo aver inizializzato clickCircleView, aggiungi questo view alla layout padre, carica l'animazione e impostala per essere eseguita in modo ciclico, infine utilizza postInvalidate() per aggiornare il view nella thread figlia

parte dell'animazione quando si clicca

mXiuyixiuButton.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    clickCircleView.setVisibility(View.GONE); // Nasconde il View del cerchio di click,View dell'animazione di ciclo
    final ClickCircleView item = new ClickCircleView(CustomView1.this, mXiuyixiuButton.getWidth())
      , mXiuyixiuButton.getHeight(), mXiuyixiuLayout.getWidth(),
      mXiuyixiuLayout.getHeight());
    Animator spreadAnim = AnimatorInflater.loadAnimator(CustomView1.this,
      R.animator.circle_spread_animator);
    spreadAnim.addListener(new AnimatorListenerAdapter() {
     @Override
     public void onAnimationEnd(Animator animation) {
      item.setIsSpreadFlag(true);//动画执行完成,标记一下
     }
    });
    spreadAnim.setTarget(item);
    spreadAnim.start();
    clickCircleViewList.add(item);
    mXiuyixiuLayout.addView(item);
    mXiuyixiuLayout.invalidate();
    handler.post(circleViewRunnable);
   }
  });


隐藏不点击动画,初始化好ClickCircleView后将该view加入List中并添加到父布局中,然后加载动画并在动画结束时添加isSpreadFlag标记,最后调用invalidate()方法刷新view并开启线程

线程部分

private Runnable circleViewRunnable = new Runnable() {
  public void run() {
   for (int i = 0; i < clickCircleViewList.size(); i++) {
    if (clickCircleViewList.get(i).isSpreadFlag()) {
     mXiuyixiuLayout.removeView(clickCircleViewList.get(i));
     clickCircleViewList.remove(i);
     mXiuyixiuLayout.postInvalidate();
    }
   }
   if (clickCircleViewList.size() <= 0) {
    clickCircleView.setVisibility(View.VISIBLE);
   }
   handler.postDelayed(this, 100);
  }
 };

Esegui l'iterazione sulla lista, rimuovi i view con il flag isSpreadFlag dalla lista e dal layout genitore, aggiornare la view, infine, se la lista è vuota, visualizza l'animazione non cliccata

Infine, ricorda di rimuovere il thread in onDestroy()

@Override
 protected void onDestroy() {
  super.onDestroy();
  handler.removeCallbacks(circleViewRunnable);
 }

L'uso di View personalizzati con animazioni di proprietà ha una alta coerenza, ma rispetto all'uso completo di View personalizzati, questo metodo è più fluido, la maggior parte del codice è basato su blog di altri, ma se si utilizza semplicemente senza sintetizzare non diventerà la tua conoscenza, quindi è nato questo blog.

Riferimento: alcuni metodi e idee per implementare支付宝咻一咻 in Android

Questo è tutto il contenuto dell'articolo, speriamo che sia utile per la tua apprendimento, e speriamo che tutti sosteniate il tutorial di urla.

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il diritto d'autore è dell'autore originale, il contenuto è stato contribuito autonomamente dagli utenti di Internet e caricato autonomamente, il sito web non detiene i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare e fornire prove pertinenti. Una volta verificata, il sito web eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare