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

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="yanzm.example.progressbar.appwidget"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name=".WidgetProvider"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/appwidget"/>
</receiver>

<activity android:name=".WidgetConfigure"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateAlwaysHidden">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>

</application>
</manifest>


res/xml/appwidget.xml

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


WidgetConfigure.java

package yanzm.example.progressbar.appwidget;

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Spinner;

public class WidgetConfigure extends Activity {

private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
private static final String PREFS_NAME
= "yanzm.example.progressbar.appwidget";
private static final String PREF_PREFIX_KEY = "prefix_";

public void onCreate(Bundle icicle) {
super.onCreate(icicle);

setResult(RESULT_CANCELED);

setContentView(R.layout.config);

// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);

Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_CANCELED, resultValue);
}

// If they gave us an intent without the widget id, just bail.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
}

/**
* called when OK button is clicked
*
* @param v
*/
public void onClickOk(View v) {
finishConfigure();
}

/**
* called when Cancel button is clicked
*
* @param v
*/
public void onClickCancel(View v) {
finish();
}

/**
* Store some settings to application preferences.
*/
private void finishConfigure() {
final Context context = WidgetConfigure.this;

Spinner spinner = (Spinner) findViewById(R.id.spinner);

int colorIndex = spinner.getSelectedItemPosition();

saveSettings(context, mAppWidgetId, colorIndex);

// Push widget update to surface with newly set prefix
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
WidgetProvider.updateAppWidget(context, appWidgetManager,
mAppWidgetId, colorIndex);

// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}

/**
* save current settings to preference
*
* @param colorIndex
*/
static void saveSettings(Context context, int appWidgetId, int colorIndex) {
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE).edit();
prefs.putInt(PREF_PREFIX_KEY + appWidgetId + "_color", colorIndex);
prefs.commit();
}

/**
* load color setting from preference
*
* @param context
* @param appWidgetId
* @return color
*/
static int loadColorIndex(Context context, int appWidgetId) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
int color = prefs.getInt(PREF_PREFIX_KEY + appWidgetId + "_color", 0);
return color;
}
}


res/layout/config.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:entries="@array/color_name"/>

<!-- OK, Cancel Button -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">

<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClickOk"
android:text="OK" />

<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClickCancel"
android:text="Cancel" />

</LinearLayout>
</LinearLayout>




WidgetProvider.java

package yanzm.example.progressbar.appwidget;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;

public class WidgetProvider extends AppWidgetProvider {

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {

int color = WidgetConfigure.loadColorIndex(context, appWidgetIds[0]);

updateAppWidget(context, appWidgetManager, appWidgetIds[0], color);
}


static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, int colorIndex) {

RemoteViews container = new RemoteViews(context.getPackageName(), R.layout.main);
RemoteViews nestedView = null;
switch(colorIndex) {
case 0:
nestedView = new RemoteViews(context.getPackageName(), R.layout.child1);
break;
case 1:
nestedView = new RemoteViews(context.getPackageName(), R.layout.child2);
break;
case 2:
nestedView = new RemoteViews(context.getPackageName(), R.layout.child3);
break;
case 3:
nestedView = new RemoteViews(context.getPackageName(), R.layout.child4);
break;
}

if(nestedView != null) {
container.removeAllViews(R.id.container);
container.addView(R.id.container, nestedView);
}

// Tell the widget manager
appWidgetManager.updateAppWidget(appWidgetId, container);
}
}


res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dip"
/>


res/layout/child1.xml

<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:progress="500"
android:max="1000"
android:progressDrawable="@drawable/seekbar_bg1"
/>

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

res/drawable/seekbar_bg1.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ff666666"
android:centerColor="#ffaaaaaa"
android:centerY="0.3"
android:endColor="#ff444444"
android:angle="270" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ff000000"
android:centerColor="#ff000000"
android:centerY="0.3"
android:endColor="#ff000000"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>

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


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


 

1 件のコメント: