关于android4.0.4中彩蛋的实现

情况:

在android4.0.4的系统设置-关于手机-Android版本,连续快速点击几下,就会出现一个机器人,长按住机器人不放,机器人会一直变大,然后出现一堆机器从屏幕上飞过


觉得有点意思,于是想看看是怎么实现的,电脑上有android4.0的代码。

系统设置-关于手机的代码:

packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java

其中,点击选项的处理如下:

long [] mHits =  new   long [ 3 ];  

  1. @Override  
  2. public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {  
  3.     if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) {  
  4.         System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);  
  5.         mHits[mHits.length-1] = SystemClock.uptimeMillis();  
  6.         if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {  
  7.             Intent intent = new Intent(Intent.ACTION_MAIN);  
  8.             intent.setClassName("android",  
  9.                     com.android.internal.app.PlatLogoActivity.class.getName());  
  10.             try {  
  11.                 startActivity(intent);  
  12.             } catch (Exception e) {  
  13.                 Log.e(LOG_TAG, "Unable to start activity " + intent.toString());  
  14.             }  
  15.         }  
  16.     }  
  17.     return super.onPreferenceTreeClick(preferenceScreen, preference);  
  18. }  
这里可以看到对固件版本选项有特殊处理:

if (preference.getKey().equals(KEY_FIRMWARE_VERSION)) {

    //如果点击的是固件版本,则记录下最近三次点击的时间;

    //如果三次点击的总时间少于500ms,则启动com.android.internal.app.PlatLogoActivity

}


再看PlatLogoActivity的实现:

  1. public class PlatLogoActivity extends Activity {  
  2.     Toast mToast;  
  3.     ImageView mContent;  
  4.     Vibrator mZzz = new Vibrator();  
  5.     int mCount;  
  6.     final Handler mHandler = new Handler();  
  7.   
  8.     Runnable mSuperLongPress = new Runnable() {  
  9.         public void run() {  
  10.             mCount++;  
  11.             mZzz.vibrate(50 * mCount);  
  12.             final float scale = 1f + 0.25f * mCount * mCount;  
  13.             mContent.setScaleX(scale);  
  14.             mContent.setScaleY(scale);  
  15.   
  16.             if (mCount <= 3) {  
  17.                 mHandler.postDelayed(mSuperLongPress, ViewConfiguration.getLongPressTimeout());  
  18.             } else {  
  19.                 try {  
  20.                     startActivity(new Intent(Intent.ACTION_MAIN)  
  21.                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK  
  22.                             | Intent.FLAG_ACTIVITY_CLEAR_TASK  
  23.                             | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)  
  24.                         .setClassName("com.android.systemui","com.android.systemui.Nyandroid"));  
  25.                 } catch (ActivityNotFoundException ex) {  
  26.                     android.util.Log.e("PlatLogoActivity""Couldn't find platlogo screensaver.");  
  27.                 }  
  28.                 finish();  
  29.             }  
  30.         }  
  31.     };  
  32.   
  33.     @Override  
  34.     protected void onCreate(Bundle savedInstanceState) {  
  35.         super.onCreate(savedInstanceState);  
  36.           
  37.         mToast = Toast.makeText(this"Android 4.0: Ice Cream Sandwich", Toast.LENGTH_SHORT);  
  38.   
  39.         mContent = new ImageView(this);  
  40.         mContent.setImageResource(com.android.internal.R.drawable.platlogo);  
  41.         mContent.setScaleType(ImageView.ScaleType.CENTER_INSIDE);  
  42.   
  43.         mContent.setOnTouchListener(new View.OnTouchListener() {  
  44.             @Override  
  45.             public boolean onTouch(View v, MotionEvent event) {  
  46.                 final int action = event.getAction();  
  47.                 if (action == MotionEvent.ACTION_DOWN) {  
  48.                     mContent.setPressed(true);  
  49.                     mHandler.removeCallbacks(mSuperLongPress);  
  50.                     mCount = 0;  
  51.                     mHandler.postDelayed(mSuperLongPress, 2*ViewConfiguration.getLongPressTimeout());  
  52.                 } else if (action == MotionEvent.ACTION_UP) {  
  53.                     if (mContent.isPressed()) {  
  54.                         mContent.setPressed(false);  
  55.                         mHandler.removeCallbacks(mSuperLongPress);  
  56.                         mToast.show();  
  57.                     }  
  58.                 }  
  59.                 return true;  
  60.             }  
  61.         });  
  62.           
  63.         setContentView(mContent);  
  64.     }  
  65. }
这里对图片的触摸事件进行了处理,

mHandler.postDelayed(mSuperLongPress, 2*ViewConfiguration.getLongPressTimeout());

在图片按下开始,2倍长按超时时间后,执行mSuperLongPress,而在mSuperLongPress中会设置图片缩放比例,逐渐放大。图片连续放大超过三次后,启动com.android.systemui.Nyandroid,显示一堆机器人。


frameworks/base/packages/SystemUI/src/com/android/systemui/Nyandroid.java

  1. public class Nyandroid extends Activity {  
  2.     final static boolean DEBUG = false;  
  3.   
  4.     public static class Board extends FrameLayout  
  5.     {  
  6.         public static final boolean FIXED_STARS = true;  
  7.         public static final int NUM_CATS = 20;  
  8.   
  9.         static Random sRNG = new Random();  
  10.   
  11.         static float lerp(float a, float b, float f) {  
  12.             return (b-a)*f + a;  
  13.         }  
  14.   
  15.         static float randfrange(float a, float b) {  
  16.             return lerp(a, b, sRNG.nextFloat());  
  17.         }  
  18.   
  19.         static int randsign() {  
  20.             return sRNG.nextBoolean() ? 1 : -1;  
  21.         }  
  22.   
  23.         static  E pick(E[] array) {  
  24.             if (array.length == 0return null;  
  25.             return array[sRNG.nextInt(array.length)];  
  26.         }  
  27.   
  28.         public class FlyingCat extends ImageView {  
  29.             public static final float VMAX = 1000.0f;  
  30.             public static final float VMIN = 100.0f;  
  31.   
  32.             public float v, vr;  
  33.   
  34.             public float dist;  
  35.             public float z;  
  36.   
  37.             public ComponentName component;  
  38.   
  39.             public FlyingCat(Context context, AttributeSet as) {  
  40.                 super(context, as);  
  41.                 setImageResource(R.drawable.nyandroid_anim); // @@@  
  42.   
  43.                 if (DEBUG) setBackgroundColor(0x80FF0000);  
  44.             }  
  45.   
  46.             public String toString() {  
  47.                 return String.format("",  
  48.                     getX(), getY(), getWidth(), getHeight());  
  49.             }  
  50.   
  51.             public void reset() {  
  52.                 final float scale = lerp(0.1f,2f,z);  
  53.                 setScaleX(scale); setScaleY(scale);  
  54.   
  55.                 setX(-scale*getWidth()+1);  
  56.                 setY(randfrange(0, Board.this.getHeight()-scale*getHeight()));  
  57.                 v = lerp(VMIN, VMAX, z);  
  58.   
  59.                 dist = 0;  
  60.   
  61. //                android.util.Log.d("Nyandroid", "reset cat: " + this);  
  62.             }  
  63.   
  64.             public void update(float dt) {  
  65.                 dist += v * dt;  
  66.                 setX(getX() + v * dt);  
  67.             }  
  68.         }  
  69.   
  70.         TimeAnimator mAnim;  
  71.   
  72.         public Board(Context context, AttributeSet as) {  
  73.             super(context, as);  
  74.   
  75.             setLayerType(View.LAYER_TYPE_HARDWARE, null);  
  76.             setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);  
  77.             setBackgroundColor(0xFF003366);  
  78.         }  
  79.   
  80.         private void reset() {  
  81. //            android.util.Log.d("Nyandroid", "board reset");  
  82.             removeAllViews();  
  83.   
  84.             final ViewGroup.LayoutParams wrap = new ViewGroup.LayoutParams(  
  85.                         ViewGroup.LayoutParams.WRAP_CONTENT,  
  86.                         ViewGroup.LayoutParams.WRAP_CONTENT);  
  87.   
  88.             if (FIXED_STARS) {  
  89.                 for(int i=0; i<20; i++) {  
  90.                     ImageView fixedStar = new ImageView(getContext(), null);  
  91.                     if (DEBUG) fixedStar.setBackgroundColor(0x8000FF80);  
  92.                     fixedStar.setImageResource(R.drawable.star_anim); // @@@  
  93.                     addView(fixedStar, wrap);  
  94.                     final float scale = randfrange(0.1f, 1f);  
  95.                     fixedStar.setScaleX(scale); fixedStar.setScaleY(scale);  
  96.                     fixedStar.setX(randfrange(0, getWidth()));  
  97.                     fixedStar.setY(randfrange(0, getHeight()));  
  98.                     final AnimationDrawable anim = (AnimationDrawable) fixedStar.getDrawable();  
  99.                     postDelayed(new Runnable() {   
  100.                         public void run() {  
  101.                             anim.start();  
  102.                         }}, (int) randfrange(01000));  
  103.                 }  
  104.             }  
  105.   
  106.             for(int i=0; i
  107.                 FlyingCat nv = new FlyingCat(getContext(), null);  
  108.                 addView(nv, wrap);  
  109.                 nv.z = ((float)i/NUM_CATS);  
  110.                 nv.z *= nv.z;  
  111.                 nv.reset();  
  112.                 nv.setX(randfrange(0,Board.this.getWidth()));  
  113.                 final AnimationDrawable anim = (AnimationDrawable) nv.getDrawable();  
  114.                 postDelayed(new Runnable() {   
  115.                     public void run() {  
  116.                         anim.start();  
  117.                     }}, (int) randfrange(01000));  
  118.             }  
  119.   
  120.             if (mAnim != null) {  
  121.                 mAnim.cancel();  
  122.             }  
  123.             mAnim = new TimeAnimator();  
  124.             mAnim.setTimeListener(new TimeAnimator.TimeListener() {  
  125.                 public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {  
  126.                     // setRotation(totalTime * 0.01f); // not as cool as you would think  
  127. //                    android.util.Log.d("Nyandroid", "t=" + totalTime);  
  128.   
  129.                     for (int i=0; i
  130.                         View v = getChildAt(i);  
  131.                         if (!(v instanceof FlyingCat)) continue;  
  132.                         FlyingCat nv = (FlyingCat) v;  
  133.                         nv.update(deltaTime / 1000f);  
  134.                         final float catWidth = nv.getWidth() * nv.getScaleX();  
  135.                         final float catHeight = nv.getHeight() * nv.getScaleY();  
  136.                         if (   nv.getX() + catWidth < -2  
  137.                             || nv.getX() > getWidth() + 2  
  138.                             || nv.getY() + catHeight < -2  
  139.                             || nv.getY() > getHeight() + 2)  
  140.                         {  
  141.                             nv.reset();  
  142.                         }  
  143.                     }  
  144.                 }  
  145.             });  
  146.         }  
  147.   
  148.         @Override  
  149.         protected void onSizeChanged (int w, int h, int oldw, int oldh) {  
  150.             super.onSizeChanged(w,h,oldw,oldh);  
  151. //            android.util.Log.d("Nyandroid", "resized: " + w + "x" + h);  
  152.             post(new Runnable() { public void run() {   
  153.                 reset();  
  154.                 mAnim.start();   
  155.             } });  
  156.         }  
  157.   
  158.   
  159.         @Override  
  160.         protected void onDetachedFromWindow() {  
  161.             super.onDetachedFromWindow();  
  162.             mAnim.cancel();  
  163.         }  
  164.   
  165.         @Override  
  166.         public boolean isOpaque() {  
  167.             return true;  
  168.         }  
  169.     }  
  170.   
  171.     private Board mBoard;  
  172.   
  173.     @Override  
  174.     public void onStart() {  
  175.         super.onStart();  
  176.   
  177.         getWindow().addFlags(  
  178.                   WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON  
  179.                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED  
  180.                 );  
  181.     }  
  182.   
  183.     @Override  
  184.     public void onResume() {  
  185.         super.onResume();  
  186.         mBoard = new Board(thisnull);  
  187.         setContentView(mBoard);  
  188.   
  189.         mBoard.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {  
  190.             @Override  
  191.             public void onSystemUiVisibilityChange(int vis) {  
  192.                 if (0 == (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) {  
  193.                     Nyandroid.this.finish();  
  194.                 }  
  195.             }  
  196.         });  
  197.     }  
  198.   
  199.     @Override  
  200.     public void onUserInteraction() {  
  201. //        android.util.Log.d("Nyandroid", "finishing on user interaction");  
  202.         finish();  
  203.     }  
  204. }
这里面FlyingCat继承了ImageView,每次产生一个FlyingCat,生成的图片大小都是随机的。

Board继承了FrameLayout,所有的星星和机器人图片都添加到Board中。

Board使用TimeAnimator定时刷新每个机器人图片的位置,实现了移动。

星星和机器本身的变化是同过boolean postDelayed(Runnable r, long delayMillis)实现自身形状变化的。

  1.                    postDelayed(new Runnable() {   
  2.                         public void run() {  
  3.                             anim.start();  
  4.                         }}, (int) randfrange(01000));

你可能感兴趣的:(android)