Java ClipDrawable用作小部件的布局背景时不工作
我试图制作一个简单的小部件,在小部件中以文本和图形方式显示电池百分比。文本部分工作没有问题,但是我很难让小部件以图形方式更新 从图形上看,我有一个电池图像,我根据电池百分比剪辑。我正在尝试为此使用Java ClipDrawable用作小部件的布局背景时不工作,java,android,android-widget,android-linearlayout,Java,Android,Android Widget,Android Linearlayout,我试图制作一个简单的小部件,在小部件中以文本和图形方式显示电池百分比。文本部分工作没有问题,但是我很难让小部件以图形方式更新 从图形上看,我有一个电池图像,我根据电池百分比剪辑。我正在尝试为此使用ClipDrawable battery\u widget\u layout.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widgetLayout
ClipDrawable
battery\u widget\u layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widgetLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:padding="@dimen/widget_padding"
android:background="@drawable/battery_clip_layer" >
<TextView
android:id="@+id/batteryPercentageWidgetTextView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="@string/battery_percentage_widget_default"
android:gravity="center" />
</LinearLayout>
在BatteryService
中,请查看更新小部件的两种不同尝试(updateWidget()
和updatewidgetattett2()
)。两次尝试都没有成功
我觉得我在做一些根本错误的事情。我非常感谢您的帮助/建议!:) 您需要在可绘制实例上设置级别,这是正确的,但不幸的是,您无法获取可绘制实例,因为它位于远程视图中 但是,ImageView确实有一个名为
setImageLevel
的方法,您可以远程调用该方法。我的建议是将可绘制图像放在ImageView中,而不是作为容器的背景,然后使用setInt(R.id.image\u视图,“setImageLevel”,level)
以下是布局的外观:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widgetLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/widget_padding" >
<ImageView
android:id="@+id/battery"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/battery_clip_layer" />
<TextView
android:id="@+id/batteryPercentageWidgetTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/battery_percentage_widget_default"
android:gravity="center" />
</FrameLayout>
关于在小部件中使用
ClipDrawable
的两次尝试是不正确的。在第一次尝试中,您错误地使用了setInt()
方法,因为该方法期望第一个int
参数是来自小部件布局的视图的id
(而不是您尝试的可绘制引用),而且也没有setLevel()
方法在Android SDK的任何视图
子类上,该方法存在于可绘制的
类中。您的第二种方法也是不正确的,因为您所做的只是加载一个Drawable
,设置其级别,仅此而已,新创建的Drawable
与小部件的LinearLayout
根无关
要使ClipDrawable
工作,您需要将其级别设置为所需的值,而drawable已设置为LinearLayout
的背景,或者可以将其设置为背景。不幸的是,我不知道在小部件中使用布局时如何做到这一点
您需要使用一个变通方法(Jschools提供了一个) 你的两次尝试是错误的。在第一次尝试中,您错误地使用了setInt()
方法,因为该方法期望第一个int
是来自小部件布局的视图的id(而不是您尝试的可绘制引用),而且在任何视图上都没有setLevel()
方法,该方法存在于可绘制类中。你的第二种方法也是不正确的,因为你所做的只是加载一个可绘制的,设置它的级别,仅此而已,与小部件的LinearLayout
无关。要使用ClipDrawble
,您需要能够在小部件已设置为背景时获取对其的引用,并更改其级别或设置其级别,然后将其设置为背景。我怀疑你能在小部件中使用目标视图完成上述任何一项。@Luksprog谢谢,你能在回答中发布上述信息吗?我将奖励你。是的,这将是我的下一次尝试。不幸的是,我不能根据赏金条件授予您赏金“我不会向替代解决方案授予赏金,例如向线性布局添加ImageView。”但是,我可以接受您的回答。我会这样做一旦确认。谢谢你的回答。这很好地工作,我可以在FrameLayout
中控制remoteview
中的多个imageview
。
public class BatteryService extends Service {
private static final String LOG = BatteryService.class.getName();
private final AtomicInteger batteryPercentage = new AtomicInteger(100);
private final BroadcastReceiver batteryUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int level = intent.getIntExtra("level", 0);
batteryPercentage.set(level);
updateWidget();
}
};
@Override
public void onCreate() {
super.onCreate();
registerReceiver(batteryUpdateReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Log.i(LOG, "Created...");
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(batteryUpdateReceiver);
Log.i(LOG, "Destroyed...");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG, "Started...");
updateWidget();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
private void updateWidget() {
final int percentage = batteryPercentage.get();
log.i(LOG, "Updated... " + percentage);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.battery_widget_layout);
remoteViews.setTextViewText(R.id.batteryPercentageWidgetTextView, percentage + "%");
//ATTEMPT 1 - no cigar
remoteViews.setInt(R.drawable.battery_clip_layer, "setLevel", 5000);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
appWidgetManager.updateAppWidget(new ComponentName(this, BatteryAppWidgetProvider.class), remoteViews);
}
private void updateWidgetAttempt2() {
final int percentage = batteryPercentage.get();
Log.i(LOG, "Updated... " + percentage);
//ATTEMPT 2 - still no cigar
Drawable clipLayer = getApplicationContext().getResources().getDrawable(R.drawable.battery_clip_layer);
if (clipLayer instanceof ClipDrawable) {
ClipDrawable clipDrawable = (ClipDrawable) clipLayer;
int level = clipDrawable.getLevel();
if (clipDrawable.setLevel(10000)) {
clipDrawable.invalidateSelf();
}
Log.i(LOG, "Updated clip amount..." + level + " -> " + ((ClipDrawable) clipLayer).getLevel());
}
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.battery_widget_layout);
remoteViews.setTextViewText(R.id.batteryPercentageWidgetTextView, percentage + "%");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
appWidgetManager.updateAppWidget(new ComponentName(this, BatteryAppWidgetProvider.class), remoteViews);
}
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widgetLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/widget_padding" >
<ImageView
android:id="@+id/battery"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/battery_clip_layer" />
<TextView
android:id="@+id/batteryPercentageWidgetTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/battery_percentage_widget_default"
android:gravity="center" />
</FrameLayout>
private void updateWidget() {
final int percentage = batteryPercentage.get();
log.i(LOG, "Updated... " + percentage);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.battery_widget_layout);
remoteViews.setTextViewText(R.id.batteryPercentageWidgetTextView, percentage + "%");
remoteViews.setInt(R.id.battery, "setImageLevel", percentage * 100);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
appWidgetManager.updateAppWidget(new ComponentName(this, BatteryAppWidgetProvider.class), remoteViews);
}