編輯:關於Android編程
在SystemUI中有一個Activity可以顯示所有的Logo

這個Activity涉及到的圖標存放在SystemUI/res/drawable-nodpi目錄下

在這裡我自己寫了個小的測試程序,把相關的文件拿出來

DessertCase.java、DessertCaseDream.java、DessertCaseView.java,只要是在DessertCaseView這個View中動態改變圖標的位置
只要在測試程序中啟動DessertCase.java就可以了
Intent intent = new Intent(getApplicationContext(), DessertCase.class); startActivity(intent);
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dzt.testapp.dessert;
import android.app.Activity;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.util.Slog;
public class DessertCase extends Activity {
DessertCaseView mView;
@Override
public void onStart() {
super.onStart();
PackageManager pm = getPackageManager();
final ComponentName cn = new ComponentName(this, DessertCaseDream.class);
if (pm.getComponentEnabledSetting(cn) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
Slog.v("DessertCase", "ACHIEVEMENT UNLOCKED");
pm.setComponentEnabledSetting(cn,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
mView = new DessertCaseView(this);
DessertCaseView.RescalingContainer container = new DessertCaseView.RescalingContainer(
this);
container.setView(mView);
setContentView(container);
}
@Override
public void onResume() {
super.onResume();
mView.postDelayed(new Runnable() {
public void run() {
mView.start();
}
}, 1000);
}
@Override
public void onPause() {
super.onPause();
mView.stop();
}
}
自定義的View,實現一些動畫
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.dzt.testapp.dessert;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.util.HashSet;
import java.util.Set;
import com.dzt.testapp.R;
public class DessertCaseView extends FrameLayout {
private static final String TAG = DessertCaseView.class.getSimpleName();
private static final boolean DEBUG = false;
static final int START_DELAY = 5000;
static final int DELAY = 2000;
static final int DURATION = 500;
private static final int TAG_POS = 0x2000001;
private static final int TAG_SPAN = 0x2000002;
private static final int[] PASTRIES = {
R.drawable.dessert_kitkat, // used with permission
R.drawable.dessert_android, // thx irina
};
private static final int[] RARE_PASTRIES = {
R.drawable.dessert_cupcake, // 2009
R.drawable.dessert_donut, // 2009
R.drawable.dessert_eclair, // 2009
R.drawable.dessert_froyo, // 2010
R.drawable.dessert_gingerbread, // 2010
R.drawable.dessert_honeycomb, // 2011
R.drawable.dessert_ics, // 2011
R.drawable.dessert_jellybean, // 2012
};
private static final int[] XRARE_PASTRIES = {
R.drawable.dessert_petitfour, // the original and still delicious
R.drawable.dessert_donutburger, // remember kids, this was long before cronuts
R.drawable.dessert_flan, // sholes final approach
// landing gear punted to flan
// runway foam glistens
// -- mcleron
R.drawable.dessert_keylimepie, // from an alternative timeline
};
private static final int[] XXRARE_PASTRIES = {
R.drawable.dessert_zombiegingerbread, // thx hackbod
R.drawable.dessert_dandroid, // thx morrildl
R.drawable.dessert_jandycane, // thx nes
};
private static final int NUM_PASTRIES = PASTRIES.length + RARE_PASTRIES.length
+ XRARE_PASTRIES.length + XXRARE_PASTRIES.length;
private SparseArray mDrawables = new SparseArray(NUM_PASTRIES);
private static final float[] MASK = {
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 0f, 255f,
1f, 0f, 0f, 0f, 0f
};
private static final float[] ALPHA_MASK = {
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 1f, 0f
};
private static final float[] WHITE_MASK = {
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 0f, 255f,
0f, 0f, 0f, 0f, 255f,
-1f, 0f, 0f, 0f, 255f
};
public static final float SCALE = 0.25f; // natural display size will be SCALE*mCellSize
private static final float PROB_2X = 0.33f;
private static final float PROB_3X = 0.1f;
private static final float PROB_4X = 0.01f;
private boolean mStarted;
private int mCellSize;
private int mWidth, mHeight;
private int mRows, mColumns;
private View[] mCells;
private final Set mFreeList = new HashSet();
private final Handler mHandler = new Handler();
private final Runnable mJuggle = new Runnable() {
@Override
public void run() {
final int N = getChildCount();
final int K = 1; //irand(1,3);
for (int i=0; i T pick(T[] a) {
return a[(int)(Math.random()*a.length)];
}
T pick(SparseArray sa) {
return sa.valueAt((int)(Math.random()*sa.size()));
}
float[] hsv = new float[] { 0, 1f, .85f };
int random_color() {
// return 0xFF000000 | (int) (Math.random() * (float) 0xFFFFFF); // totally random
final int COLORS = 12;
hsv[0] = irand(0,COLORS) * (360f/COLORS);
return Color.HSVToColor(hsv);
}
@Override
protected synchronized void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mWidth == w && mHeight == h) return;
final boolean wasStarted = mStarted;
if (wasStarted) {
stop();
}
mWidth = w;
mHeight = h;
mCells = null;
removeAllViewsInLayout();
mFreeList.clear();
mRows = mHeight / mCellSize;
mColumns = mWidth / mCellSize;
mCells = new View[mRows * mColumns];
if (DEBUG) Log.v(TAG, String.format("New dimensions: %dx%d", mColumns, mRows));
setScaleX(SCALE);
setScaleY(SCALE);
setTranslationX(0.5f * (mWidth - mCellSize * mColumns) * SCALE);
setTranslationY(0.5f * (mHeight - mCellSize * mRows) * SCALE);
for (int j=0; j 0) {
final float s = (Integer) v.getTag(TAG_SPAN);
v.setScaleX(0.5f * s);
v.setScaleY(0.5f * s);
v.setAlpha(0f);
v.animate().withLayer().scaleX(s).scaleY(s).alpha(1f).setDuration(animationLen);
}
}
}
public void place(View v, boolean animate) {
place(v, new Point(irand(0, mColumns), irand(0, mRows)), animate);
}
// we don't have .withLayer() on general Animators
private final Animator.AnimatorListener makeHardwareLayerListener(final View v) {
return new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
/// M: [ALPS01271500] Check if this view is currently attached to a window.
if (!v.isAttachedToWindow()) return;
v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
v.buildLayer();
}
@Override
public void onAnimationEnd(Animator animator) {
/// M: [ALPS01271500] Check if this view is currently attached to a window.
if (!v.isAttachedToWindow()) return;
v.setLayerType(View.LAYER_TYPE_NONE, null);
}
};
}
private final HashSet tmpSet = new HashSet();
public synchronized void place(View v, Point pt, boolean animate) {
final int i = pt.x;
final int j = pt.y;
final float rnd = frand();
if (v.getTag(TAG_POS) != null) {
for (final Point oc : getOccupied(v)) {
mFreeList.add(oc);
mCells[oc.y*mColumns + oc.x] = null;
}
}
int scale = 1;
if (rnd < PROB_4X) {
if (!(i >= mColumns-3 || j >= mRows-3)) {
scale = 4;
}
} else if (rnd < PROB_3X) {
if (!(i >= mColumns-2 || j >= mRows-2)) {
scale = 3;
}
} else if (rnd < PROB_2X) {
if (!(i == mColumns-1 || j == mRows-1)) {
scale = 2;
}
}
v.setTag(TAG_POS, pt);
v.setTag(TAG_SPAN, scale);
tmpSet.clear();
final Point[] occupied = getOccupied(v);
for (final Point oc : occupied) {
final View squatter = mCells[oc.y*mColumns + oc.x];
if (squatter != null) {
tmpSet.add(squatter);
}
}
for (final View squatter : tmpSet) {
for (final Point sq : getOccupied(squatter)) {
mFreeList.add(sq);
mCells[sq.y*mColumns + sq.x] = null;
}
if (squatter != v) {
squatter.setTag(TAG_POS, null);
if (animate) {
squatter.animate().withLayer()
.scaleX(0.5f).scaleY(0.5f).alpha(0)
.setDuration(DURATION)
.setInterpolator(new AccelerateInterpolator())
.setListener(new Animator.AnimatorListener() {
public void onAnimationStart(Animator animator) { }
public void onAnimationEnd(Animator animator) {
removeView(squatter);
}
public void onAnimationCancel(Animator animator) { }
public void onAnimationRepeat(Animator animator) { }
})
.start();
} else {
removeView(squatter);
}
}
}
for (final Point oc : occupied) {
mCells[oc.y*mColumns + oc.x] = v;
mFreeList.remove(oc);
}
final float rot = (float)irand(0, 4) * 90f;
if (animate) {
v.bringToFront();
AnimatorSet set1 = new AnimatorSet();
set1.playTogether(
ObjectAnimator.ofFloat(v, View.SCALE_X, (float) scale),
ObjectAnimator.ofFloat(v, View.SCALE_Y, (float) scale)
);
set1.setInterpolator(new AnticipateOvershootInterpolator());
set1.setDuration(DURATION);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(
ObjectAnimator.ofFloat(v, View.ROTATION, rot),
ObjectAnimator.ofFloat(v, View.X, i* mCellSize + (scale-1) * mCellSize /2),
ObjectAnimator.ofFloat(v, View.Y, j* mCellSize + (scale-1) * mCellSize /2)
);
set2.setInterpolator(new DecelerateInterpolator());
set2.setDuration(DURATION);
set1.addListener(makeHardwareLayerListener(v));
set1.start();
set2.start();
} else {
v.setX(i * mCellSize + (scale-1) * mCellSize /2);
v.setY(j * mCellSize + (scale-1) * mCellSize /2);
v.setScaleX((float) scale);
v.setScaleY((float) scale);
v.setRotation(rot);
}
}
private Point[] getOccupied(View v) {
final int scale = (Integer) v.getTag(TAG_SPAN);
final Point pt = (Point)v.getTag(TAG_POS);
if (pt == null || scale == 0) return new Point[0];
final Point[] result = new Point[scale * scale];
int p=0;
for (int i=0; i在Activity onResume時會創建線程調用
public void start() {
if (!mStarted) {
mStarted = true;
fillFreeList(DURATION * 4);
}
mHandler.postDelayed(mJuggle, START_DELAY);
}
同時也會創建一個線程循環調用動畫播放
private final Runnable mJuggle = new Runnable() {
@Override
public void run() {
final int N = getChildCount();
final int K = 1; //irand(1,3);
for (int i=0; i
Android開發本地及網絡Mp3音樂播放器(十五)網絡音樂及歌詞下載功能實現
實現功能:實現網絡音樂歌詞下載功能(下載音樂的同時,下載對應歌詞)下載好的歌詞目前不在播放器內,可以通過文件浏覽器查看。後續將博文,將實現本地音樂歌詞下載和已下載音樂掃描
android實現雙日期選擇控件(可隱藏日,只顯示年月)
在安卓開發中,會碰到選開始日期和結束日期的問題。特別是在使用Pad時,如果彈出一個Dialog,能夠同時選擇開始日期和結束日期,那將是極好的。我在開發中在DatePick
Android對話框(一)AlertDialog
最近在做項目,小組幾個回了家。界面暫時沒人做,用到自定義對話框只能臨時去學。現在把對話框的相關整理。 +
2.3.1 存儲數據到data目錄中
當應用安裝到Android後,系統會根據每個應用的包名創建一個/data/data/包名/的文件夾,訪問自己包名下的目錄是不需要權限的,並且Android已經提供了非常簡