Android特效专辑(六)——仿QQ聊天撒花特效,无形装逼,最为致命

来源:互联网 发布:java violate关键字 编辑:程序博客网 时间:2024/05/17 23:03

标签: android聊天特效-撒花
 4017人阅读 评论(12) 收藏 举报
 分类:

目录(?)[+]

Android特效专辑(六)——仿QQ聊天撒花特效,无形装逼,最为致命


我的关于特效的专辑已经在CSDN上申请了一个专栏——http://blog.csdn.net/column/details/liuguilin.html 
日后我所写的特效专辑也会以一添加在这个专栏上,今天写的这个特效,是关于聊天的,你肯定遇到过,就是你跟人家聊天的时候,比如发送应(么么哒),然后屏幕上全部就是表情了,今天我们就是做这个,撒花的特效,国际惯例,上图

截图

这里写图片描述

实现这样的效果,你要知道贝塞尔曲线,何谓贝塞尔曲线?其实就是曲线,嘿嘿,关于曲线的概念大家可以去

Android绘图机制(二)——自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解 
中看下,我们这里就直接写了

1.activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    //撒花的区域    <RelativeLayout        android:id="@+id/rlt_animation_layout"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </RelativeLayout>    <Button        android:id="@+id/btn_start"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="23dp"        android:text="开始撒花" /></RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2.Fllower

传参类
package com.lgl.test;import android.graphics.Bitmap;import android.graphics.Path;import java.io.Serializable;public class Fllower implements Serializable {    private static final long serialVersionUID = 1L;    private Bitmap image;    private float x;    private float y;    private Path path;    private float value;    public Bitmap getResId() {        return image;    }    public void setResId(Bitmap img) {        this.image = img;    }    public float getX() {        return x;    }    public void setX(float x) {        this.x = x;    }    public float getY() {        return y;    }    public void setY(float y) {        this.y = y;    }    public Path getPath() {        return path;    }    public void setPath(Path path) {        this.path = path;    }    public float getValue() {        return value;    }    public void setValue(float value) {        this.value = value;    }    @Override    public String toString() {        return "Fllower [ x=" + x + ", y=" + y + ", path=" + path + ", value="                + value + "]";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

3.FllowerAnimation

动画类
package com.lgl.test;import java.util.ArrayList;import java.util.List;import java.util.Random;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.animation.ValueAnimator.AnimatorUpdateListener;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PathMeasure;import android.util.Log;import android.util.TypedValue;import android.view.View;import android.view.WindowManager;import android.view.animation.AccelerateInterpolator;/** * 撒花 用到的知识点: 1、android属性动画 2、Path路径绘制 3、贝塞尔曲线 */public class FllowerAnimation extends View implements AnimatorUpdateListener {    /**     * 动画改变的属性值     */    private float phase1 = 0f;    private float phase2 = 0f;    private float phase3 = 0f;    /**     * 小球集合     */    private List<Fllower> fllowers1 = new ArrayList<Fllower>();    private List<Fllower> fllowers2 = new ArrayList<Fllower>();    private List<Fllower> fllowers3 = new ArrayList<Fllower>();    /**     * 动画播放的时间     */    private int time = 4000;    /**     * 动画间隔     */    private int delay = 400;    int[] ylocations = { -100, -50, -25, 0 };    /**     * 资源ID     */    // private int resId = R.drawable.fllower_love;    public FllowerAnimation(Context context) {        super(context);        init(context);        // this.resId = resId;    }    @SuppressWarnings("deprecation")    private void init(Context context) {        WindowManager wm = (WindowManager) context                .getSystemService(Context.WINDOW_SERVICE);        width = wm.getDefaultDisplay().getWidth();        height = (int) (wm.getDefaultDisplay().getHeight() * 3 / 2f);        mPaint = new Paint();        mPaint.setAntiAlias(true);        // mPaint.setStrokeWidth(2);        // mPaint.setColor(Color.BLUE);        // mPaint.setStyle(Style.STROKE);        pathMeasure = new PathMeasure();        builderFollower(fllowerCount, fllowers1);        builderFollower(fllowerCount, fllowers2);        builderFollower(fllowerCount, fllowers3);    }    /**     * 宽度     */    private int width = 0;    /**     * 高度     */    private int height = 0;    /**     * 曲线高度个数分割     */    private int quadCount = 10;    /**     * 曲度     */    private float intensity = 0.2f;    /**     * 第一批个数     */    private int fllowerCount = 4;    /**     * 创建花     */    private void builderFollower(int count, List<Fllower> fllowers) {        int max = (int) (width * 3 / 4f);        int min = (int) (width / 4f);        Random random = new Random();        for (int i = 0; i < count; i++) {            int s = random.nextInt(max) % (max - min + 1) + min;            Path path = new Path();            CPoint CPoint = new CPoint(s, ylocations[random.nextInt(3)]);            List<CPoint> points = builderPath(CPoint);            drawFllowerPath(path, points);            Fllower fllower = new Fllower();            fllower.setPath(path);            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),                    R.drawable.lift_flower);            fllower.setResId(bitmap);            fllowers.add(fllower);        }    }    /**     * 画曲线     *     * @param path     * @param points     */    private void drawFllowerPath(Path path, List<CPoint> points) {        if (points.size() > 1) {            for (int j = 0; j < points.size(); j++) {                CPoint point = points.get(j);                if (j == 0) {                    CPoint next = points.get(j + 1);                    point.dx = ((next.x - point.x) * intensity);                    point.dy = ((next.y - point.y) * intensity);                } else if (j == points.size() - 1) {                    CPoint prev = points.get(j - 1);                    point.dx = ((point.x - prev.x) * intensity);                    point.dy = ((point.y - prev.y) * intensity);                } else {                    CPoint next = points.get(j + 1);                    CPoint prev = points.get(j - 1);                    point.dx = ((next.x - prev.x) * intensity);                    point.dy = ((next.y - prev.y) * intensity);                }                // create the cubic-spline path                if (j == 0) {                    path.moveTo(point.x, point.y);                } else {                    CPoint prev = points.get(j - 1);                    path.cubicTo(prev.x + prev.dx, (prev.y + prev.dy), point.x                            - point.dx, (point.y - point.dy), point.x, point.y);                }            }        }    }    /**     * 曲线摇摆的幅度     */    private int range = (int) TypedValue            .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, getResources()                    .getDisplayMetrics());    /**     * 画路径     *     * @param point     * @return     */    private List<CPoint> builderPath(CPoint point) {        List<CPoint> points = new ArrayList<CPoint>();        Random random = new Random();        for (int i = 0; i < quadCount; i++) {            if (i == 0) {                points.add(point);            } else {                CPoint tmp = new CPoint(0, 0);                if (random.nextInt(100) % 2 == 0) {                    tmp.x = point.x + random.nextInt(range);                } else {                    tmp.x = point.x - random.nextInt(range);                }                tmp.y = (int) (height / (float) quadCount * i);                points.add(tmp);            }        }        return points;    }    /**     * 画笔     */    private Paint mPaint;    /**     * 测量路径的坐标位置     */    private PathMeasure pathMeasure = null;    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        drawFllower(canvas, fllowers1);        drawFllower(canvas, fllowers2);        drawFllower(canvas, fllowers3);    }    /**     * 高度往上偏移量,把开始点移出屏幕顶部     */    private float dy = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,            40, getResources().getDisplayMetrics());    /**     * @param canvas     * @param fllowers     */    private void drawFllower(Canvas canvas, List<Fllower> fllowers) {        for (Fllower fllower : fllowers) {            float[] pos = new float[2];            // canvas.drawPath(fllower.getPath(),mPaint);            pathMeasure.setPath(fllower.getPath(), false);            pathMeasure.getPosTan(height * fllower.getValue(), pos, null);            // canvas.drawCircle(pos[0], pos[1], 10, mPaint);            canvas.drawBitmap(fllower.getResId(), pos[0], pos[1] - dy, null);        }    }    ObjectAnimator mAnimator1;    ObjectAnimator mAnimator2;    ObjectAnimator mAnimator3;    public void startAnimation() {        if (mAnimator1 != null && mAnimator1.isRunning()) {            mAnimator1.cancel();        }        mAnimator1 = ObjectAnimator.ofFloat(this, "phase1", 0f, 1f);        mAnimator1.setDuration(time);        mAnimator1.addUpdateListener(this);        mAnimator1.start();        mAnimator1.setInterpolator(new AccelerateInterpolator(1f));        if (mAnimator2 != null && mAnimator2.isRunning()) {            mAnimator2.cancel();        }        mAnimator2 = ObjectAnimator.ofFloat(this, "phase2", 0f, 1f);        mAnimator2.setDuration(time);        mAnimator2.addUpdateListener(this);        mAnimator2.start();        mAnimator2.setInterpolator(new AccelerateInterpolator(1f));        mAnimator2.setStartDelay(delay);        if (mAnimator3 != null && mAnimator3.isRunning()) {            mAnimator3.cancel();        }        mAnimator3 = ObjectAnimator.ofFloat(this, "phase3", 0f, 1f);        mAnimator3.setDuration(time);        mAnimator3.addUpdateListener(this);        mAnimator3.start();        mAnimator3.setInterpolator(new AccelerateInterpolator(1f));        mAnimator3.setStartDelay(delay * 2);    }    /**     * 跟新小球的位置     *     * @param value     * @param fllowers     */    private void updateValue(float value, List<Fllower> fllowers) {        for (Fllower fllower : fllowers) {            fllower.setValue(value);        }    }    /**     * 动画改变回调     */    @Override    public void onAnimationUpdate(ValueAnimator arg0) {        updateValue(getPhase1(), fllowers1);        updateValue(getPhase2(), fllowers2);        updateValue(getPhase3(), fllowers3);        Log.i(tag, getPhase1() + "");        invalidate();    }    public float getPhase1() {        return phase1;    }    public void setPhase1(float phase1) {        this.phase1 = phase1;    }    public float getPhase2() {        return phase2;    }    public void setPhase2(float phase2) {        this.phase2 = phase2;    }    public float getPhase3() {        return phase3;    }    public void setPhase3(float phase3) {        this.phase3 = phase3;    }    private String tag = this.getClass().getSimpleName();    private class CPoint {        public float x = 0f;        public float y = 0f;        /**         * x-axis distance         */        public float dx = 0f;        /**         * y-axis distance         */        public float dy = 0f;        public CPoint(float x, float y) {            this.x = x;            this.y = y;        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353

4.MainActivity

接着就看我们使用
package com.lgl.test;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.RelativeLayout;public class MainActivity extends Activity {    private Button btn_start;    // 撒花特效    private RelativeLayout rlt_animation_layout;    private FllowerAnimation fllowerAnimation;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 撒花初始化        rlt_animation_layout = (RelativeLayout) findViewById(R.id.rlt_animation_layout);        rlt_animation_layout.setVisibility(View.VISIBLE);        fllowerAnimation = new FllowerAnimation(this);        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(                RelativeLayout.LayoutParams.MATCH_PARENT,                RelativeLayout.LayoutParams.MATCH_PARENT);        fllowerAnimation.setLayoutParams(params);        rlt_animation_layout.addView(fllowerAnimation);        btn_start = (Button) findViewById(R.id.btn_start);        btn_start.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // 开始撒花                fllowerAnimation.startAnimation();            }        });    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
好,我们现在来看看效果

这里写图片描述

好的,你也赶快去试一下吧!

Demo下载:http://download.csdn.net/detail/qq_26787115/9410578

0 0
原创粉丝点击