編輯:關於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 SparseArraymDrawables = 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
實現功能:實現網絡音樂歌詞下載功能(下載音樂的同時,下載對應歌詞)下載好的歌詞目前不在播放器內,可以通過文件浏覽器查看。後續將博文,將實現本地音樂歌詞下載和已下載音樂掃描
在安卓開發中,會碰到選開始日期和結束日期的問題。特別是在使用Pad時,如果彈出一個Dialog,能夠同時選擇開始日期和結束日期,那將是極好的。我在開發中在DatePick
最近在做項目,小組幾個回了家。界面暫時沒人做,用到自定義對話框只能臨時去學。現在把對話框的相關整理。 +
當應用安裝到Android後,系統會根據每個應用的包名創建一個/data/data/包名/的文件夾,訪問自己包名下的目錄是不需要權限的,並且Android已經提供了非常簡