最近.一個朋友跟我說想,我給她弄個鬧鐘APP軟件...功能其實很簡單...只需要弄個簡單的鬧鐘.自己設計設計時間.然后時間到了的時候,鬧鈴放的聲音是男朋友錄制好的聲音...于是就開始整了....
第一次做這種的時候.我想把首頁界面做成一個GIF動畫特效的.這樣看起來可愛點...適合妹子用,于是就有了下面這個效果圖
上代碼
ndroid中的Android.graphics.Movie 這個類,這是android提供給我們的一個非常方便的工具。
首先,重寫控件View,自定義一個展示gif圖的GifView
Movie其實管理著GIF動畫中的多個幀,只需要通過 setTime() 一下就可以讓它在draw()的時候繪出相應的那幀圖像。通過當前時間與duration之間的換算關系,是很容易實現GIF動起來的效果。
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
|
public class GifView extends View { /** * 默認為1秒 */ private static final int DEFAULT_MOVIE_DURATION = 1000 ; private int mMovieResourceId; private Movie mMovie; private long mMovieStart; private int mCurrentAnimationTime = 0 ; private float mLeft; private float mTop; private float mScale; private int mMeasuredMovieWidth; private int mMeasuredMovieHeight; private boolean mVisible = true ; private volatile boolean mPaused = false ; public GifView(Context context) { this (context, null ); } public GifView(Context context, AttributeSet attrs) { this (context, attrs, R.styleable.CustomTheme_gifViewStyle); } public GifView(Context context, AttributeSet attrs, int defStyle) { super (context, attrs, defStyle); setViewAttributes(context, attrs, defStyle); } @SuppressLint ( "NewApi" ) private void setViewAttributes(Context context, AttributeSet attrs, int defStyle) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { setLayerType(View.LAYER_TYPE_SOFTWARE, null ); } // 從描述文件中讀出gif的值,創建出Movie實例 final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GifView, defStyle, R.style.Widget_GifView); mMovieResourceId = array.getResourceId(R.styleable.GifView_gif, - 1 ); mPaused = array.getBoolean(R.styleable.GifView_paused, false ); array.recycle(); if (mMovieResourceId != - 1 ) { mMovie = Movie.decodeStream(getResources().openRawResource( mMovieResourceId)); } } /** * 設置gif圖資源 * * @param movieResId */ public void setMovieResource( int movieResId) { this .mMovieResourceId = movieResId; mMovie = Movie.decodeStream(getResources().openRawResource( mMovieResourceId)); requestLayout(); } public void setMovie(Movie movie) { this .mMovie = movie; requestLayout(); } public Movie getMovie() { return mMovie; } public void setMovieTime( int time) { mCurrentAnimationTime = time; invalidate(); } /** * 設置暫停 * * @param paused */ public void setPaused( boolean paused) { this .mPaused = paused; if (!paused) { mMovieStart = android.os.SystemClock.uptimeMillis() - mCurrentAnimationTime; } invalidate(); } /** * 判斷gif圖是否停止了 * * @return */ public boolean isPaused() { return this .mPaused; } @Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { if (mMovie != null ) { int movieWidth = mMovie.width(); int movieHeight = mMovie.height(); int maximumWidth = MeasureSpec.getSize(widthMeasureSpec); float scaleW = ( float ) movieWidth / ( float ) maximumWidth; mScale = 1f / scaleW; mMeasuredMovieWidth = maximumWidth; mMeasuredMovieHeight = ( int ) (movieHeight * mScale); setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight); } else { setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight()); } } @Override protected void onLayout( boolean changed, int l, int t, int r, int b) { super .onLayout(changed, l, t, r, b); mLeft = (getWidth() - mMeasuredMovieWidth) / 2f; mTop = (getHeight() - mMeasuredMovieHeight) / 2f; mVisible = getVisibility() == View.VISIBLE; } @Override protected void onDraw(Canvas canvas) { if (mMovie != null ) { if (!mPaused) { updateAnimationTime(); drawMovieFrame(canvas); invalidateView(); } else { drawMovieFrame(canvas); } } } @SuppressLint ( "NewApi" ) private void invalidateView() { if (mVisible) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { postInvalidateOnAnimation(); } else { invalidate(); } } } private void updateAnimationTime() { long now = android.os.SystemClock.uptimeMillis(); // 如果第一幀,記錄起始時間 if (mMovieStart == 0 ) { mMovieStart = now; } // 取出動畫的時長 int dur = mMovie.duration(); if (dur == 0 ) { dur = DEFAULT_MOVIE_DURATION; } // 算出需要顯示第幾幀 mCurrentAnimationTime = ( int ) ((now - mMovieStart) % dur); } private void drawMovieFrame(Canvas canvas) { // 設置要顯示的幀,繪制即可 mMovie.setTime(mCurrentAnimationTime); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.scale(mScale, mScale); mMovie.draw(canvas, mLeft / mScale, mTop / mScale); canvas.restore(); } @SuppressLint ( "NewApi" ) @Override public void onScreenStateChanged( int screenState) { super .onScreenStateChanged(screenState); mVisible = screenState == SCREEN_STATE_ON; invalidateView(); } @SuppressLint ( "NewApi" ) @Override protected void onVisibilityChanged(View changedView, int visibility) { super .onVisibilityChanged(changedView, visibility); mVisible = visibility == View.VISIBLE; invalidateView(); } @Override protected void onWindowVisibilityChanged( int visibility) { super .onWindowVisibilityChanged(visibility); mVisible = visibility == View.VISIBLE; invalidateView(); } } |
其次,在xml布局文件中,把這個view定義進去,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "fill_parent" android:layout_height = "fill_parent" android:background = "#ffffff" android:gravity = "center" android:orientation = "vertical" > < com.example.alarmtest.GifView android:id = "@+id/gif1" android:layout_width = "300dp" android:layout_height = "300dp" android:layout_gravity = "center_horizontal" android:enabled = "false" /> < Button android:id = "@+id/bu" android:text = "進入" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_gravity = "center_horizontal" /> </ LinearLayout > |
最后,在MainActivity中的使用,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
|
public class FirstActivity extends Activity { private GifView gif; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_first); gif = (GifView) findViewById(R.id.gif1); // 設置背景gif圖片資源 gif.setMovieResource(R.raw.a123); } } |
Styles.xml
1
2
3
4
5
6
7
8
|
< declare-styleable name = "GifView" > < attr name = "gif" format = "reference" /> < attr name = "paused" format = "boolean" /> </ declare-styleable > < declare-styleable name = "CustomTheme" > < attr name = "gifViewStyle" format = "reference" /> </ declare-styleable > < style name = "Widget_GifView" ></ style > |
raw是res下面的一個文件放的是GIF動畫圖噢
我這里放了一個動畫圖 跟一個 音樂文件,因為我要做的是一個有聲音的鬧鈴
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:https://blog.csdn.net/bfboys/article/details/53183171