English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Cet article présente la création d'une vue personnalisée en配合属性动画来实现以下效果
L'idée de mise en œuvre est assez simple :
Regardons d'abord la partie de dessin de cercle semi-transparent
public class ClickCircleView extends View { private Bitmap bitmap; private Paint paint; private Canvas canvas; private boolean isSpreadFlag = false;//Marquer si l'émission est terminée 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); // Set the width and height of the 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); } }
As can be seen, the relevant properties are all set on the pen, then directly call the canvas's drawCircle() method to draw a semi-transparent circle, and finally call the invalidate() method to refresh the View
It is necessary to override the parent class's onDraw() method, otherwise the custom View cannot take effect
We set a flag isSpreadFlag, which is used to mark whether the expansion animation is completed
Then we will implement two animation effects
animation of expansion when clicked
<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>
It's very simple, just change the scale value to increase to1.8times
animation of expansion and recovery when not clicked
<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>
Similaire à l'animation précédente, le paramètre startOffset peut être utilisé pour contrôler l'ordre d'exécution de l'Animation, par exemple Android:startOffset=""10"00" signifie configurer le délai d'animation de cette propriété1Seconde d'exécution
Ensuite, c'est la partie où l'animation et la logique sont exécutées par un thread
Partie animée au moment du clic non détecté
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(); // Charger l'animation 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();//Exécution en boucle de l'animation } } }); anim.setTarget(clickCircleView); anim.start(); } });
Après avoir initialisé clickCircleView, ajoutez ce view au layout parent, puis chargez l'animation et configurez l'exécution en boucle, enfin utilisez postInvalidate() pour actualiser le view en mode sous-thread
Partie animée au moment du clic
mXiuyixiuButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickCircleView.setVisibility(View.GONE);//Dessiner un cercle, cacher le View d'animation en boucle 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);//Marquer que l'animation est terminée } }); spreadAnim.setTarget(item); spreadAnim.start(); clickCircleViewList.add(item); mXiuyixiuLayout.addView(item); mXiuyixiuLayout.invalidate(); handler.post(circleViewRunnable); } });
Masquer l'animation non cliquable, initialise bien ClickCircleView puis ajoute ce view à la liste et à la mise en page parente, puis charge l'animation et ajoute le marqueur isSpreadFlag à la fin de l'animation, puis appelle la méthode invalidate() pour actualiser le view et démarrer le thread
Partie thread
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); } };
Parcourir la liste, supprimer les vues marquées par isSpreadFlag de la liste et du layout parent, puis actualiser la vue, enfin, si la liste est vide, afficher l'animation lors du clic
N'oubliez pas de supprimer le thread dans onDestroy()
@Override protected void onDestroy() { super.onDestroy(); handler.removeCallbacks(circleViewRunnable); }
L'utilisation de View personnalisé avec l'animation des propriétés pour réaliser cet effet a une forte cohérence, mais par rapport à l'utilisation complète de View personnalisé, cette méthode est plus fluide, la plupart des codes de cette méthode sont tirés des blogs d'autres personnes, mais si vous ne résumez pas simplement pour utiliser, cela ne deviendra pas votre propre connaissance, donc j'ai écrit ce blog.
Référence : plusieurs idées et méthodes pour réaliser le fonctionnalité 'Xiu Xiu' d'Alipay en Android
C'est tout le contenu de cet article, j'espère que cela aidera à votre apprentissage, et j'espère que vous soutiendrez également le tutoriel d'alarme.
Déclaration : le contenu de cet article est extrait du réseau, la propriété intellectuelle appartient à l'auteur original, le contenu est apporté par les utilisateurs d'Internet et téléchargé spontanément, ce site Web ne détient pas de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de copyright, veuillez envoyer un e-mail à : notice#w3Déclaration : le contenu de cet article est extrait du réseau, la propriété intellectuelle appartient à l'auteur original, le contenu est apporté par les utilisateurs d'Internet et téléchargé spontanément, ce site Web ne détient pas de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de copyright, veuillez envoyer un e-mail à : notice#w