天天看點

Android動畫效果Widget(飛行模式)

1. 功能:

建立Widget後,若為飛行模式,點選Widget,取消飛行模式,否則設定為飛行模式。在變化過程中有動畫效果。

2. 實作思想:

對應main.xml布局檔案,Widget由三張圖檔組成,pane上層左邊為airplane,右邊為switch點選桌面widget時圖示的時候,左邊airplane四張圖示動态的在切換,直到設定為飛行模式或者取消飛行模式狀态完成時,airplane切換停止,同時右邊switch圖檔切換settrings_switch_on或者settrings_switch_off。

3.       程式中用到圖檔資源檔案如下:

settings_icon_airplane_01.png     

Android動畫效果Widget(飛行模式)
settings_icon_airplane_02.png     
Android動畫效果Widget(飛行模式)
settings_icon_airplane_03.png     
Android動畫效果Widget(飛行模式)
settings_icon_airplane_04.png 
Android動畫效果Widget(飛行模式)
settings_pane_off.png    
Android動畫效果Widget(飛行模式)
settings_switch_off.png     
Android動畫效果Widget(飛行模式)
settings_switch_on.png      
Android動畫效果Widget(飛行模式)

  1. code: 
  2. 布局檔案main.xml 
  3. <?xml version="1.0" encoding="utf-8"?> 
  4. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  5.     android:layout_width="wrap_content" 
  6.     android:layout_height="wrap_content"> 
  7.     <ImageView android:id="@+id/setting_pane" 
  8.        android:layout_width="wrap_content" 
  9.        android:layout_height="wrap_content" 
  10.        android:src="@drawable/settings_pane_off"/> 
  11.     <ImageView android:id="@+id/setting_airplane" 
  12.            android:layout_width="wrap_content" 
  13.            android:layout_height="wrap_content" 
  14.            android:layout_alignParentLeft="true" 
  15.            android:layout_centerVertical="true" 
  16.            android:layout_marginLeft="6dip" 
  17.            android:src="@drawable/settings_icon_airplane_04"/> 
  18.     <ImageView android:id="@+id/setting_switch" 
  19.            android:layout_width="wrap_content" 
  20.            android:layout_height="wrap_content" 
  21.            android:layout_toRightOf="@id/setting_airplane" 
  22.            android:layout_centerVertical="true" 
  23.            android:layout_marginLeft="4dip" 
  24.            android:src="@drawable/settings_switch_off"/> 
  25. </RelativeLayout> 
  26. 在res下建立xml檔案夾,然後建立widget_provider.xml 
  27. <?xml version="1.0" encoding="UTF-8"?> 
  28. <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 
  29.     android:minWidth="50dip" <-指定寬度度-> 
  30.     android:minHeight="50dip" <-指定高度-> 
  31.     android:initialLayout="@layout/main"/> 
  32. 建立AirplaneModeEnabler類 
  33. public class AirplaneModeEnabler{ 
  34. //此方法判斷是否為飛行模式 
  35.  public static boolean isAirplaneModeOn(Context context){ 
  36.   return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,0)!=0; 
  37.  } 
  38. //此方法設定或取消飛行模式,enabling參數為true,則設為飛行模式,否則取消飛行模式
  39.  public static void setAirplaneModeOn(Context context,boolean enabling){ 
  40.   Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, enabling?1:0); 
  41.   Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 
  42.   intent.putExtra("state", enabling); 
  43.   context.sendBroadcast(intent); 
  44.  } 
  45. 建MyWidget 類,繼承AppWidgetProvider,此類則widget第一次建立時執行oupdate方法,
  46. 即是廣播接受者,也是廣播發送者
  47. public class MyWidget extends AppWidgetProvider { 
  48.  private Context mContext = null; 
  49.  public RemoteViews remoteViews = new RemoteViews("com.archermind.widget", R.layout.main); 
  50.  public final static String SET_AIRPLANE_ACTION = "com.archermind.set_airplane_mode"; 
  51.  private static final int START_ANIMATION = 0; //開始動畫
  52.  private static final int END_ANIMATION = 1; //結束動畫
  53.  private static Boolean mRunAnimation = false; 
  54.  private Handler mHandler = new Handler() { 
  55.   @Override 
  56.   public void handleMessage(Message msg) { 
  57.    //接受到消息後開始動畫效果,即連續切換4張圖檔
  58.    if (msg.what == START_ANIMATION) { 
  59.     Log.i("state", "START_ANIMATION: mRunAnimation = " + mRunAnimation); 
  60.     if (!mRunAnimation) { 
  61.      return; 
  62.     }
  63.     //更新widget背景圖檔
  64.     remoteViews.setImageViewResource(R.id.setting_airplane, mDrawable[msg.arg1]); 
  65.     AppWidgetManager appWidgetManger = AppWidgetManager 
  66.      .getInstance(mContext); 
  67.     int[] appIds = appWidgetManger.getAppWidgetIds(new ComponentName( 
  68.             mContext, MyWidget.class)); 
  69.     for (int id: appIds) { 
  70.      appWidgetManger.updateAppWidget(id, remoteViews); 
  71.     } 
  72.     // send message for next frame 
  73.     Message message = mHandler.obtainMessage(START_ANIMATION); 
  74.     message.arg1 = (msg.arg1 + 1) % 4; 
  75.     mHandler.sendMessageDelayed(message, 200); 
  76.    } else if (msg.what == END_ANIMATION) {  //結束動畫,
  77.     Log.i("state", "END_ANIMATION: mRunAnimation = " + mRunAnimation); 
  78.     AppWidgetManager appWidgetManger = AppWidgetManager 
  79.         .getInstance(mContext); 
  80.     int[] appIds = appWidgetManger.getAppWidgetIds(new ComponentName( 
  81.            mContext, MyWidget.class)); 
  82.     for (int id: appIds) { 
  83.      updateAppWidget(mContext, appWidgetManger, id); 
  84.     } 
  85.    } 
  86.    Log.i("hThreadId",Long.toString(Thread.currentThread().getId())); 
  87.   } 
  88.  }; 
  89.  private int[] mDrawable = { 
  90.   R.drawable.settings_icon_airplane_01, 
  91.   R.drawable.settings_icon_airplane_02, 
  92.   R.drawable.settings_icon_airplane_03, 
  93.   R.drawable.settings_icon_airplane_04 
  94.  }; 
  95.  @Override 
  96.  public void onDeleted(Context context, int[] appWidgetIds) { 
  97.   super.onDeleted(context, appWidgetIds); 
  98.   Log.i("method", "onDeleted()"); 
  99.  } 
  100.  @Override 
  101.  public void onDisabled(Context context) { 
  102.   super.onDisabled(context); 
  103.   Log.i("method", "onDisabled()"); 
  104.  } 
  105.  @Override 
  106.  public void onEnabled(Context context) { 
  107.   super.onEnabled(context); 
  108.   Log.i("method", "onEnabled()"); 
  109.  //建立widgt時,調用此方法,注冊電話監聽器
  110.   TelephonyManager telephonyManager=(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 
  111.   telephonyManager.listen( mPhoneStateListener,PhoneStateListener.LISTEN_SERVICE_STATE); 
  112.  }
        //接受到發送到廣播時執行此方法
  1.  @Override 
  2.  public void onReceive(Context context, Intent intent) { 
  3.   Log.i("method", "onReceive()"); 
  4.   super.onReceive(context, intent); 
  5.   Log.i("action",intent.getAction()); 
  6.   if(mContext ==null){ 
  7.    mContext = context; 
  8.   }
  9.   if(intent.getAction().equals(SET_AIRPLANE_ACTION)){ 
  10.    boolean airplaneMode = AirplaneModeEnabler.isAirplaneModeOn(context); 
  11.    if(airplaneMode){ 
  12.           AirplaneModeEnabler.setAirplaneModeOn(context, !airplaneMode); 
  13.          }else{ 
  14.           AirplaneModeEnabler.setAirplaneModeOn(context, !airplaneMode); 
  15.          } 
  16.    Log.e("state", "onReceive: mRunAnimation = true"); 
  17.    mRunAnimation = true; 
  18.    Message msg = mHandler.obtainMessage(START_ANIMATION); 
  19.    msg.arg1 = 0; 
  20.    mHandler.sendMessage(msg); 
  21.   } 
  22.  } 
  23.  @Override 
  24.  public void onUpdate(Context context, AppWidgetManager appWidgetManager, 
  25.    int[] appWidgetIds) { 
  26.   super.onUpdate(context, appWidgetManager, appWidgetIds); 
  27.   Log.i("method", "onUpdate()"); 
  28.   if(mContext==null){ 
  29.    mContext = context; 
  30.   }
  31. //建立RemoteViews,并調用updateAppWidget更新背景圖檔
  32.   remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); 
  33.   int n = appWidgetIds.length; 
  34.      for (int i = 0; i < n; i++) { 
  35.         int appWidgetId = appWidgetIds[i]; 
  36.         updateAppWidget(context, appWidgetManager, appWidgetId); 
  37.      } 
  38.      Log.i("length of appIds", ""+appWidgetIds.length); 
  39.  } 
  40.  //判斷目前是否為飛行模式,并設定不同到背景圖檔
  41.  public void updateAppWidget(Context context, 
  42.             AppWidgetManager appWidgeManger, int appWidgetId) { 
  43.   boolean airplaneMode = AirplaneModeEnabler.isAirplaneModeOn(context); 
  44.   if(airplaneMode){ 
  45.    remoteViews.setImageViewResource(R.id.setting_airplane,R.drawable.settings_icon_airplane_04); 
  46.    remoteViews.setImageViewResource(R.id.setting_switch,R.drawable.settings_switch_on); 
  47.   }else{ 
  48.    remoteViews.setImageViewResource(R.id.setting_airplane,R.drawable.settings_icon_airplane_04); 
  49.    remoteViews.setImageViewResource(R.id.setting_switch,R.drawable.settings_switch_off); 
  50.   }
  51. //單機widget時發送廣播
  52.   Intent intentClick = new Intent(SET_AIRPLANE_ACTION); 
  53.         PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
  54.                 intentClick, 0); 
  55.         remoteViews.setOnClickPendingIntent(R.id.setting_pane, pendingIntent); 
  56.         appWidgeManger.updateAppWidget(appWidgetId, remoteViews); 
  57.     } 
  58.  //電話監聽器,用來監聽是否為飛行模式
  59.  PhoneStateListener mPhoneStateListener = new PhoneStateListener(){ 
  60.   @Override 
  61.   public void onServiceStateChanged(ServiceState serviceState) { 
  62.    super.onServiceStateChanged(serviceState); 
  63.    Log.i("phThreadId",Long.toString(Thread.currentThread().getId())); 
  64.    switch(serviceState.getState()){ 
  65.    case ServiceState.STATE_IN_SERVICE: 
  66.     Log.i("state", "STATE_IN_SERVICE mRunAnimation = false"); 
  67.     mRunAnimation = false; 
  68.     mHandler.sendMessage(Message.obtain(mHandler, END_ANIMATION)); 
  69.     break; 
  70.    case ServiceState.STATE_POWER_OFF: 
  71.     Log.i("state", "STATE_POWER_OFF mRunAnimation = false"); 
  72.     mRunAnimation = false; 
  73.     mHandler.sendMessage(Message.obtain(mHandler, END_ANIMATION)); 
  74.     break; 
  75.    case ServiceState.STATE_OUT_OF_SERVICE: 
  76.     Log.i("state", "STATE_OUT_OF_SERVICE"); 
  77.     break; 
  78.    case ServiceState.STATE_EMERGENCY_ONLY: 
  79.     Log.i("state", "STATE_EMERGENCY_ONLY"); 
  80.     break; 
  81.    } 
  82.   } 
  83.  }; 
  84. <?xml version="1.0" encoding="utf-8"?> 
  85. <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  86.       package="com.archermind.widget" 
  87.       android:versionCode="1" 
  88.       android:versionName="1.0"> 
  89.     <application android:icon="@drawable/widget_icon_airplane" android:label="@string/app_name"> 
  90.         <receiver android:name=".MyWidget" 
  91.                   android:label="@string/app_name" android:icon="@drawable/widget_icon_airplane"> 
  92.             <intent-filter> 
  93.                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> 
  94.                 <action android:name="com.archermind.set_airplane_mode" /> 
  95.             </intent-filter> 
  96.             <meta-data android:name="android.appwidget.provider" 
  97.                  android:resource="@xml/widget_provider"/> 
  98.         </receiver> 
  99.     </application> 
  100.     <uses-permission android:name="android.permission.WRITE_SETTINGS" /> 
  101. </manifest>