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);
}