<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Android特效專輯(五)——自定義圓形頭像和仿MIUI卸載動畫—粒子爆炸 > 好的,各位親愛的朋友,今天講的特效還是比較炫的,首先,我們會講一個自定義圓形的imageView,接著,我們會來實現粒子爆炸的特效,按照國際慣例,無圖無真相的沒這個效果也是模仿大神的,現在應用在了我的《Only》上 ### 截圖 ![這里寫圖片描述](https://box.kancloud.cn/2016-02-24_56cd2c174d678.jpg "") ~~~ 好的,我們新建一個工程——AnimView,我們要用到的圖片 ~~~ ![這里寫圖片描述](https://box.kancloud.cn/2016-02-24_56cd2c1792fd5.jpg "") ### 一.自定義圓形頭像—— ~~~ 直接開寫了,要實現的東西都在注釋上了 ~~~ ### 1.編寫自定義屬性attr.xml ~~~ <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="roundedimageview"> <attr name="border_thickness" format="dimension" /> <attr name="border_inside_color" format="color" /> <attr name="border_outside_color" format="color"></attr> </declare-styleable> </resources> ~~~ ### 2.自定義View ~~~ 緊接著我們就可以編寫這個類了 ~~~ ~~~ package com.lgl.animview; /** * 圓形頭像 * Created by LGL on 2016/1/12. */ import android.content.Context; import android.content.res.TypedArray; 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.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.util.AttributeSet; import android.widget.ImageView; /** * 圓形ImageView,可設置最多兩個寬度不同且顏色不同的圓形邊框。 設置顏色在xml布局文件中由自定義屬性配置參數指定 */ public class RoundImageView extends ImageView { private int mBorderThickness = 0; private Context mContext; private int defaultColor = 0xFFFFFFFF; // 如果只有其中一個有值,則只畫一個圓形邊框 private int mBorderOutsideColor = 0; private int mBorderInsideColor = 0; // 控件默認長、寬 private int defaultWidth = 0; private int defaultHeight = 0; public RoundImageView(Context context) { super(context); mContext = context; } public RoundImageView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setCustomAttributes(attrs); } public RoundImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; setCustomAttributes(attrs); } private void setCustomAttributes(AttributeSet attrs) { // 獲取自定義的屬性 TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview); mBorderThickness = a.getDimensionPixelSize( R.styleable.roundedimageview_border_thickness, 0); mBorderOutsideColor = a .getColor(R.styleable.roundedimageview_border_outside_color, defaultColor); mBorderInsideColor = a.getColor( R.styleable.roundedimageview_border_inside_color, defaultColor); } @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable == null) { return; } if (getWidth() == 0 || getHeight() == 0) { return; } this.measure(0, 0); if (drawable.getClass() == NinePatchDrawable.class) return; Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); if (defaultWidth == 0) { defaultWidth = getWidth(); } if (defaultHeight == 0) { defaultHeight = getHeight(); } int radius = 0; if (mBorderInsideColor != defaultColor && mBorderOutsideColor != defaultColor) {// 定義畫兩個邊框,分別為外圓邊框和內圓邊框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - 2 * mBorderThickness; // 畫內圓 drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); // 畫外圓 drawCircleBorder(canvas, radius + mBorderThickness + mBorderThickness / 2, mBorderOutsideColor); } else if (mBorderInsideColor != defaultColor && mBorderOutsideColor == defaultColor) {// 定義畫一個邊框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderInsideColor); } else if (mBorderInsideColor == defaultColor && mBorderOutsideColor != defaultColor) {// 定義畫一個邊框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2 - mBorderThickness; drawCircleBorder(canvas, radius + mBorderThickness / 2, mBorderOutsideColor); } else {// 沒有邊框 radius = (defaultWidth < defaultHeight ? defaultWidth : defaultHeight) / 2; } Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius); canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight / 2 - radius, null); } /** * 獲取裁剪后的圓形圖片 */ public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) { Bitmap scaledSrcBmp; int diameter = radius * 2; // 為了防止寬高不相等,造成圓形圖片變形,因此截取長方形中處于中間位置最大的正方形圖片 int bmpWidth = bmp.getWidth(); int bmpHeight = bmp.getHeight(); int squareWidth = 0, squareHeight = 0; int x = 0, y = 0; Bitmap squareBitmap; if (bmpHeight > bmpWidth) {// 高大于寬 squareWidth = squareHeight = bmpWidth; x = 0; y = (bmpHeight - bmpWidth) / 2; // 截取正方形圖片 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else if (bmpHeight < bmpWidth) {// 寬大于高 squareWidth = squareHeight = bmpHeight; x = (bmpWidth - bmpHeight) / 2; y = 0; squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, squareHeight); } else { squareBitmap = bmp; } if (squareBitmap.getWidth() != diameter || squareBitmap.getHeight() != diameter) { scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, diameter, true); } else { scaledSrcBmp = squareBitmap; } Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); Paint paint = new Paint(); Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), scaledSrcBmp.getHeight()); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); canvas.drawARGB(0, 0, 0, 0); canvas.drawCircle(scaledSrcBmp.getWidth() / 2, scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(scaledSrcBmp, rect, rect, paint); bmp = null; squareBitmap = null; scaledSrcBmp = null; return output; } /** * 邊緣畫圓 */ private void drawCircleBorder(Canvas canvas, int radius, int color) { Paint paint = new Paint(); /* 去鋸齒 */ paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint.setColor(color); /* 設置paint的 style 為STROKE:空心 */ paint.setStyle(Paint.Style.STROKE); /* 設置paint的外框寬度 */ paint.setStrokeWidth(mBorderThickness); canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint); } } ~~~ ### 3.引用 ~~~ 引用起來就比較簡單了,我們首先來引入他的命名空間 ~~~ ~~~ xmlns:imagecontrol="http://schemas.android.com/apk/res-auto" ~~~ ~~~ 然后我們直接寫xml ~~~ ~~~ <com.lgl.animview.RoundImageView android:id="@+id/iv_round" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/photo" imagecontrol:border_inside_color="#bc0978" imagecontrol:border_outside_color="#ba3456" imagecontrol:border_thickness="1dp" /> ~~~ ~~~ 好的,讓我們運行下吧 ~~~ ![這里寫圖片描述](https://box.kancloud.cn/2016-02-24_56cd2c17af7f9.jpg "") ### 二.MUI卸載動畫——粒子爆炸 ~~~ 關于這個粒子特效,在開篇的時候已經展示了效果,那么我們接下來,要怎么做尼? ~~~ ### 1.ParticleUtils ~~~ 用于粒子動畫的單位轉換 ~~~ ~~~ package com.lgl.animview; import android.content.res.Resources; /** * 粒子動畫 */ public class ParticleUtils { /** * 密度 */ public static final float DENSITY = Resources.getSystem().getDisplayMetrics().density; public static int dp2px(int dp) { return Math.round(dp * DENSITY); } } ~~~ ### 2.Particle ~~~ 用于爆破效果的分子計算 ~~~ ~~~ package com.lgl.animview; import java.util.Random; import android.graphics.Point; import android.graphics.Rect; /** * Created by lgl on 16/01/14. 爆破粒子 */ public class Particle { public static final int PART_WH = 8; // 默認小球寬高 // 原本的值(不可變) // float originCX; // float originCY; // float originRadius; // 實際的值(可變) float cx; // center x of circle float cy; // center y of circle float radius; int color; float alpha; static Random random = new Random(); Rect mBound; public static Particle generateParticle(int color, Rect bound, Point point) { int row = point.y; // 行是高 int column = point.x; // 列是寬 Particle particle = new Particle(); particle.mBound = bound; particle.color = color; particle.alpha = 1f; particle.radius = PART_WH; particle.cx = bound.left + PART_WH * column; particle.cy = bound.top + PART_WH * row; return particle; } public void advance(float factor) { cx = cx + factor * random.nextInt(mBound.width()) * (random.nextFloat() - 0.5f); cy = cy + factor * random.nextInt(mBound.height() / 2); radius = radius - factor * random.nextInt(2); alpha = (1f - factor) * (1 + random.nextFloat()); } } ~~~ ### 3.ExplosionAnimator ~~~ 屬性動畫,用于動畫展示 ~~~ ~~~ package com.lgl.animview; import android.animation.ValueAnimator; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.view.View; /** * Created by lgl on 16/01/14. */ public class ExplosionAnimator extends ValueAnimator { public static final int DEFAULT_DURATION = 1500; private Particle[][] mParticles; private Paint mPaint; private View mContainer; public ExplosionAnimator(View view, Bitmap bitmap, Rect bound) { mPaint = new Paint(); mContainer = view; setFloatValues(0.0f, 1.0f); setDuration(DEFAULT_DURATION); mParticles = generateParticles(bitmap, bound); } private Particle[][] generateParticles(Bitmap bitmap, Rect bound) { int w = bound.width(); int h = bound.height(); int partW_Count = w / Particle.PART_WH; // 橫向個數 int partH_Count = h / Particle.PART_WH; // 豎向個數 int bitmap_part_w = bitmap.getWidth() / partW_Count; int bitmap_part_h = bitmap.getHeight() / partH_Count; Particle[][] particles = new Particle[partH_Count][partW_Count]; Point point = null; for (int row = 0; row < partH_Count; row++) { // 行 for (int column = 0; column < partW_Count; column++) { // 列 // 取得當前粒子所在位置的顏色 int color = bitmap.getPixel(column * bitmap_part_w, row * bitmap_part_h); point = new Point(column, row); // x是列,y是行 particles[row][column] = Particle.generateParticle(color, bound, point); } } return particles; } public void draw(Canvas canvas) { if (!isStarted()) { // 動畫結束時停止 return; } for (Particle[] particle : mParticles) { for (Particle p : particle) { p.advance((Float) getAnimatedValue()); mPaint.setColor(p.color); // mPaint.setAlpha((int) (255 * p.alpha)); //只是這樣設置,透明色會顯示為黑色 mPaint.setAlpha((int) (Color.alpha(p.color) * p.alpha)); // 這樣透明顏色就不是黑色了 canvas.drawCircle(p.cx, p.cy, p.radius, mPaint); } } mContainer.invalidate(); } @Override public void start() { super.start(); mContainer.invalidate(); } } ~~~ ### 4.ExplosionField ~~~ 開始執行這個實例的動畫了 ~~~ ~~~ package com.lgl.animview; import java.util.ArrayList; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.Window; /** * Created by lgl on 16/01/14. */ public class ExplosionField extends View { private static final String TAG = "ExplosionField"; private static final Canvas mCanvas = new Canvas(); private ArrayList<ExplosionAnimator> explosionAnimators; private OnClickListener onClickListener; public ExplosionField(Context context) { super(context); init(); } public ExplosionField(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { explosionAnimators = new ArrayList<ExplosionAnimator>(); attach2Activity((Activity) getContext()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (ExplosionAnimator animator : explosionAnimators) { animator.draw(canvas); } } /** * 爆破 * * @param view * 使得該view爆破 */ public void explode(final View view) { Rect rect = new Rect(); view.getGlobalVisibleRect(rect); // 得到view相對于整個屏幕的坐標 rect.offset(0, -ParticleUtils.dp2px(25)); // 去掉狀態欄高度 final ExplosionAnimator animator = new ExplosionAnimator(this, createBitmapFromView(view), rect); explosionAnimators.add(animator); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { view.animate().alpha(0f).setDuration(150).start(); } @Override public void onAnimationEnd(Animator animation) { view.animate().alpha(1f).setDuration(150).start(); // 動畫結束時從動畫集中移除 explosionAnimators.remove(animation); animation = null; } }); animator.start(); } private Bitmap createBitmapFromView(View view) { /* * 為什么屏蔽以下代碼段? 如果ImageView直接得到位圖,那么當它設置背景(backgroud)時,不會讀取到背景顏色 */ // if (view instanceof ImageView) { // Drawable drawable = ((ImageView)view).getDrawable(); // if (drawable != null && drawable instanceof BitmapDrawable) { // return ((BitmapDrawable) drawable).getBitmap(); // } // } // view.clearFocus(); //不同焦點狀態顯示的可能不同——(azz:不同就不同有什么關系?) Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); if (bitmap != null) { synchronized (mCanvas) { mCanvas.setBitmap(bitmap); view.draw(mCanvas); mCanvas.setBitmap(null); // 清除引用 } } return bitmap; } /** * 給Activity加上全屏覆蓋的ExplosionField */ private void attach2Activity(Activity activity) { ViewGroup rootView = (ViewGroup) activity .findViewById(Window.ID_ANDROID_CONTENT); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); rootView.addView(this, lp); } /** * 希望誰有破碎效果,就給誰加Listener * * @param view * 可以是ViewGroup */ public void addListener(View view) { if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; int count = viewGroup.getChildCount(); for (int i = 0; i < count; i++) { addListener(viewGroup.getChildAt(i)); } } else { view.setClickable(true); view.setOnClickListener(getOnClickListener()); } } private OnClickListener getOnClickListener() { if (null == onClickListener) { onClickListener = new OnClickListener() { @Override public void onClick(View v) { ExplosionField.this.explode(v); // view.setOnClickListener(null); // 用過一次就不需要了 } }; } return onClickListener; } } ~~~ ### 5.MainActivity ~~~ 好的,一切準備好了之后我們就可以使用了 ~~~ ~~~ package com.lgl.animview; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { // 實例化粒子動畫 private ExplosionField explosionField; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); explosionField = new ExplosionField(this); // 綁定哪個控件哪個控件就有效果,如果需要整個layout,只要綁定根布局的id即可 explosionField.addListener(findViewById(R.id.iv_round)); } } ~~~ ~~~ 在xml中我們什么也不用做,好的,讓我們來運行一下 ~~~ ![這里寫圖片描述](https://box.kancloud.cn/2016-02-24_56cd2c17de8ca.jpg "") ~~~ 好的,本篇博客也到此結束了,喜歡的點個贊 ~~~ ### Demo下載:[http://download.csdn.net/detail/qq_26787115/9409139](http://download.csdn.net/detail/qq_26787115/9409139)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看