English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Este artigo introduz a implementação de View personalizada com animação de atributos para alcançar os seguintes efeitos
A ideia é bem simples:
Primeiro, vamos olhar para a parte de desenhar o círculo semi-transparente
public class ClickCircleView extends View { private Bitmap bitmap; private Paint paint; private Canvas canvas; private boolean isSpreadFlag = false;//marcar se foi concluído o disparo 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); // Definir as dimensões do 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); } }
Pode ver que as propriedades relacionadas são configuradas no pincel, então chamamos diretamente o método drawCircle() do canvas para desenhar um círculo semi-transparente, e por fim chamamos o método invalidate() para atualizar o View
É obrigatório sobrescrever o método onDraw() da superclasse, senão o View personalizado não funcionará
Definimos um sinalizador de flag isSpreadFlag, cujo propósito é marcar se a animação de expansão foi concluída
Então vamos implementar os dois efeitos de animação
A animação de expansão ao clicar
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="10"00" android:propertyName="scaleY" android:valueFrom="1.0" android:valueTo="1.8" android:valueType="floatType" /> <objectAnimator android:duration="10"00" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="1.8" android:valueType="floatType" /> </set>
É muito simples, é alterar o valor de scale, aumentando até1.8vezes
A animação de expansão e recolhimento ao não clicar
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:duration="10"00" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="1.2" android:valueType="floatType" /> <objectAnimator android:duration="10"00" android:propertyName="scaleY" android:valueFrom="1.0" android:valueTo="1.2" android:valueType="floatType" /> <objectAnimator android:duration="10"00" android:propertyName="scaleX" android:startOffset="10"00" android:valueFrom="1.2" android:valueTo="1.0" android:valueType="floatType" /> <objectAnimator android:duration="10"00" android:propertyName="scaleY" android:startOffset="10"00" android:valueFrom="1.2" android:valueTo="1.0" android:valueType="floatType" /> </set>
e a animação anterior, o parâmetro startOffset pode ser usado para controlar a ordem de execução da Animation, por exemplo, Android:startOffset=""10"00" indica a configuração do atraso da animação dessa propriedade1segundo
Depois disso, é a vez de usar a thread para executar a animação e a lógica
parte da animação ao não clicar
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(); // carregar a animação 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();//execução de loop da animação } } }); anim.setTarget(clickCircleView); anim.start(); } });
Depois de inicializar o clickCircleView, adicione este view ao layout pai, carregue a animação e configure para executar em loop, finalmente, use postInvalidate() para atualizar o view na thread secundária
parte da animação ao clicar
mXiuyixiuButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickCircleView.setVisibility(View.GONE);//Disparar o círculo, ocultar a animação de loop do View 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); } };
Percorrer a lista, remover o view com o marcador isSpreadFlag da lista e do layout pai e atualizar o view, por fim, se a lista estiver vazia, exibir o efeito de clique
Lembre-se de remover a thread no onDestroy() no final
@Override protected void onDestroy() { super.onDestroy(); handler.removeCallbacks(circleViewRunnable); }
Usar View personalizado com animação de atributo para alcançar uma alta耦合ação, mas este método é mais fluído do que usar View personalizado completamente, a maioria do código é referenciado de blogs de outras pessoas, mas se você simplesmente usar sem resumir, não se tornará seu conhecimento, portanto, surgiu este blog.
Referência: Várias abordagens para implementar o efeito de 'Xiu Xiu' no Android
Isso é tudo o que há no artigo, esperamos que ajude no seu aprendizado e que você apoie o tutorial Gargalhadas.
Declaração: O conteúdo deste artigo é extraído da Internet, pertence ao respectivo proprietário, foi contribuído e carregado voluntariamente pelos usuários da Internet, o site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie e-mail para: notice#oldtoolbag.com (ao enviar e-mail, substitua # por @ para denunciar e forneça provas relevantes. Caso seja confirmado, o site deletará imediatamente o conteúdo suspeito de violação de direitos autorais.)