2011年7月1日金曜日

AppWidget の ProgressBar の色を変える

# 某MLで AppWidget 上のプログレスバー (ProgressBar) の色を
# 変えたいという質問があったのでやってみたらできたので、
# せっかくだからブログに書きます。

注意 その1 : API Level 7 (2.1) 以上です。
注意 その2 : 最低限のことしかやってないので、あとは自分でなんとかしてね。

---

キーは RemoteView クラスの addView() メソッドです。

最初の設定画面でどの色を選択したのかを Preference に保存しておき、その値によって AppWidget の update で addView() で挿入するレイアウトを変えます。
レイアウトや背景画像の XML を設定で選択できる数用意しないといけないのがちょっとかっこ悪いですが、Drawable は RemoteView で指定できないのでしょうがないです。。。




AndroidManifest.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="yanzm.example.progressbar.appwidget"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="7" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <receiver android:name=".WidgetProvider"  
  10.             android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />  
  13.             </intent-filter>      
  14.             <meta-data android:name="android.appwidget.provider"  
  15.                 android:resource="@xml/appwidget"/>  
  16.         </receiver>  
  17.   
  18.   <activity android:name=".WidgetConfigure"  
  19.       android:screenOrientation="portrait"  
  20.       android:windowSoftInputMode="adjustPan|stateAlwaysHidden">  
  21.    <intent-filter>  
  22.     <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>  
  23.    </intent-filter>  
  24.   </activity>  
  25.   
  26.     </application>  
  27. </manifest>  


res/xml/appwidget.xml
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <appwidget-provider  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:minWidth="294dip"  
  5.     android:minHeight="72dip"  
  6.     android:initialLayout="@layout/main"  
  7.     android:updatePeriodMillis="0"  
  8.     android:configure="yanzm.example.progressbar.appwidget.WidgetConfigure"  
  9.     />  


WidgetConfigure.java
  1. package yanzm.example.progressbar.appwidget;  
  2.   
  3. import android.app.Activity;  
  4. import android.appwidget.AppWidgetManager;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.SharedPreferences;  
  8. import android.os.Bundle;  
  9. import android.view.View;  
  10. import android.widget.Spinner;  
  11.   
  12. public class WidgetConfigure extends Activity {  
  13.    
  14.     private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;  
  15.     private static final String PREFS_NAME  
  16.     = "yanzm.example.progressbar.appwidget";  
  17.     private static final String PREF_PREFIX_KEY = "prefix_";  
  18.   
  19.     public void onCreate(Bundle icicle) {  
  20.         super.onCreate(icicle);  
  21.   
  22.         setResult(RESULT_CANCELED);  
  23.   
  24.         setContentView(R.layout.config);  
  25.   
  26.         // Find the widget id from the intent.   
  27.         Intent intent = getIntent();  
  28.         Bundle extras = intent.getExtras();  
  29.         if (extras != null) {  
  30.             mAppWidgetId = extras.getInt(  
  31.                     AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);  
  32.               
  33.             Intent resultValue = new Intent();  
  34.             resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);  
  35.             setResult(RESULT_CANCELED, resultValue);  
  36.         }  
  37.   
  38.         // If they gave us an intent without the widget id, just bail.  
  39.         if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {  
  40.             finish();  
  41.         }  
  42.     }      
  43.       
  44.     /** 
  45.      * called when OK button is clicked 
  46.      *  
  47.      * @param v 
  48.      */  
  49.     public void onClickOk(View v) {  
  50.      finishConfigure();  
  51.     }  
  52.   
  53.     /** 
  54.      * called when Cancel button is clicked 
  55.      *  
  56.      * @param v 
  57.      */  
  58.     public void onClickCancel(View v) {  
  59.      finish();  
  60.     }  
  61.   
  62.     /** 
  63.      * Store some settings to application preferences. 
  64.      */  
  65.     private void finishConfigure() {       
  66.         final Context context = WidgetConfigure.this;  
  67.   
  68.         Spinner spinner = (Spinner) findViewById(R.id.spinner);  
  69.           
  70.         int colorIndex = spinner.getSelectedItemPosition();  
  71.   
  72.         saveSettings(context, mAppWidgetId, colorIndex);  
  73.   
  74.         // Push widget update to surface with newly set prefix  
  75.         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);  
  76.         WidgetProvider.updateAppWidget(context, appWidgetManager,  
  77.                 mAppWidgetId, colorIndex);  
  78.        
  79.         // Make sure we pass back the original appWidgetId  
  80.         Intent resultValue = new Intent();  
  81.         resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);  
  82.         setResult(RESULT_OK, resultValue);  
  83.         finish();  
  84.     }  
  85.       
  86.     /** 
  87.      * save current settings to preference 
  88.      *  
  89.      * @param colorIndex 
  90.      */  
  91.     static void saveSettings(Context context, int appWidgetId, int colorIndex) {  
  92.         SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit();  
  93.         prefs.putInt(PREF_PREFIX_KEY + appWidgetId + "_color", colorIndex);  
  94.         prefs.commit();  
  95.     }      
  96.   
  97.     /** 
  98.      * load color setting from preference 
  99.      *  
  100.      * @param context 
  101.      * @param appWidgetId 
  102.      * @return color 
  103.      */  
  104.     static int loadColorIndex(Context context, int appWidgetId) {  
  105.         SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);  
  106.         int color = prefs.getInt(PREF_PREFIX_KEY + appWidgetId + "_color"0);          
  107.         return color;  
  108.     }  
  109. }  


res/layout/config.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.     <Spinner   
  8.         android:id="@+id/spinner"  
  9.         android:layout_width="fill_parent"   
  10.         android:layout_height="wrap_content"  
  11.         android:entries="@array/color_name"/>  
  12.       
  13.     <!-- OK, Cancel Button -->  
  14.     <LinearLayout   
  15.         android:orientation="horizontal"  
  16.         android:layout_width="fill_parent"  
  17.         android:layout_height="wrap_content">  
  18.   
  19.         <Button  
  20.             android:layout_width="0dip"   
  21.             android:layout_height="wrap_content"  
  22.             android:layout_weight="1"  
  23.             android:onClick="onClickOk"  
  24.             android:text="OK" />  
  25.   
  26.         <Button  
  27.             android:layout_width="0dip"   
  28.             android:layout_height="wrap_content"  
  29.             android:layout_weight="1"  
  30.             android:onClick="onClickCancel"  
  31.             android:text="Cancel" />  
  32.       
  33.     </LinearLayout>      
  34. </LinearLayout>  




WidgetProvider.java
  1. package yanzm.example.progressbar.appwidget;  
  2.   
  3. import android.appwidget.AppWidgetManager;  
  4. import android.appwidget.AppWidgetProvider;  
  5. import android.content.Context;  
  6. import android.widget.RemoteViews;  
  7.   
  8. public class WidgetProvider extends AppWidgetProvider {  
  9.   
  10.  @Override  
  11.  public void onUpdate(Context context, AppWidgetManager appWidgetManager,  
  12.    int[] appWidgetIds) {  
  13.     
  14.   int color = WidgetConfigure.loadColorIndex(context, appWidgetIds[0]);  
  15.     
  16.   updateAppWidget(context, appWidgetManager, appWidgetIds[0], color);  
  17.  }  
  18.   
  19.       
  20.     static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,  
  21.             int appWidgetId, int colorIndex) {  
  22.   
  23.   RemoteViews container = new RemoteViews(context.getPackageName(), R.layout.main);  
  24.   RemoteViews nestedView = null;  
  25.   switch(colorIndex) {  
  26.    case 0:  
  27.     nestedView = new RemoteViews(context.getPackageName(), R.layout.child1);  
  28.     break;  
  29.    case 1:  
  30.     nestedView = new RemoteViews(context.getPackageName(), R.layout.child2);  
  31.     break;  
  32.    case 2:  
  33.     nestedView = new RemoteViews(context.getPackageName(), R.layout.child3);  
  34.     break;  
  35.    case 3:  
  36.     nestedView = new RemoteViews(context.getPackageName(), R.layout.child4);  
  37.     break;  
  38.   }  
  39.     
  40.   if(nestedView != null) {  
  41.    container.removeAllViews(R.id.container);  
  42.    container.addView(R.id.container, nestedView);  
  43.   }  
  44.   
  45.   // Tell the widget manager  
  46.         appWidgetManager.updateAppWidget(appWidgetId, container);  
  47.     }  
  48. }  


res/layout/main.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/container"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:orientation="vertical"  
  7.     android:padding="10dip"  
  8.     />  


res/layout/child1.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       android:id="@+id/progressBar"  
  4.       style="?android:attr/progressBarStyleHorizontal"   
  5.       android:layout_width="fill_parent"   
  6.       android:layout_height="wrap_content"  
  7.       android:progress="500"  
  8.       android:max="1000"  
  9.       android:progressDrawable="@drawable/seekbar_bg1"  
  10.       />  

child2.xml, child3.xml, child4.xml は progressDrawable が違うだけ

res/drawable/seekbar_bg1.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <layer-list xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   <item android:id="@android:id/background">  
  4.     <shape>  
  5.       <corners android:radius="5dip" />  
  6.       <gradient  
  7.         android:startColor="#ff666666"  
  8.         android:centerColor="#ffaaaaaa"  
  9.         android:centerY="0.3"  
  10.         android:endColor="#ff444444"  
  11.         android:angle="270" />  
  12.     </shape>  
  13.   </item>  
  14.   <item android:id="@android:id/progress">  
  15.     <clip>  
  16.       <shape>  
  17.         <corners android:radius="5dip" />  
  18.         <gradient  
  19.           android:startColor="#ff000000"  
  20.           android:centerColor="#ff000000"  
  21.           android:centerY="0.3"  
  22.           android:endColor="#ff000000"  
  23.           android:angle="270"  
  24.           />  
  25.       </shape>  
  26.     </clip>  
  27.   </item>  
  28.  </layer-list>  

seekbar_bg2.xml, seekbar_bg3.xml, seekbar_bg4.xml は色が違うだけ


# 時間がなくて GitHub にあげられなかった。そのうちあげるかも。。。


 

0 件のコメント:

コメントを投稿