stu*_*low 0 layout android components widget android-appwidget
如何AnalogClock在app小部件中设置Android的自定义时间?
作为替代方案,我正在考虑覆盖默认的AnalogClock来设置代码的时间.换句话说,我会创建自定义时钟,它从默认的View或AnalogClock扩展.然后将我的自定义时钟放在小部件布局UI上.
这可能吗?我担心RemoteViews会限制我们自己的自定义组件.
更新: 这是错误日志我首先遵循vArDo给出的解决方案.

在app小部件中包含自定义视图是不可能的.根据文档,在布局中只能使用小的预定义视图子集.所以,正如你所提到的,不可能创建自己的AnalogClock视图(正如我在其他答案中所示)并将其包含在app小部件中.
但是,还有其他方法可用于AnalogClock在app小部件中创建自定义.在这样的实现中,设置时间直接AnalogClock应该不成问题.
其中一个做到这一点的方法之一是借鉴自AnalogClock成ImageView(这是在应用小部件允许的景色之一).重复PendingIntent使用每60秒Service画ImageView一次(通过RemoteViews).
请记住,调用Service操作以更新的应用程序插件通过RemoteViews每隔60秒不上电池,所以重量轻.在Jelly Bean示例实施中,夜间使用2%的电池(屏幕关闭,平均网络强度).但是,我每隔15秒就更新一次屏幕,这在模拟时钟方面是不必要的.因此粗略估计,每晚更新一次的应用程序小部件将在夜间消耗大约0.5%的电量 - 这对您的用户来说可能很重要.
首先,您必须创建Service将ImageView在您的视图中绘制的内容.绘图代码几乎取决于AnalogClock实现,并根据需要重新排列.首先,没有检查时间是否已经改变 - 这是因为Service只有在我们决定时才会调用(例如每60秒).第二个变化是我们Drawable从方法中的资源创建s.
另一个变化是代码Bitmap使用Canvas以下方法将模拟时钟绘制到本地
// Creating Bitmap and Canvas to which analog clock will be drawn.
Bitmap appWidgetBitmap = Bitmap.createBitmap(availableWidth, availableHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(appWidgetBitmap);
Run Code Online (Sandbox Code Playgroud)
更新被吸引到ImageViewvia RemoteViews.汇总更改,然后将其推送到主屏幕上的应用小部件 - 有关详细信息,请参阅文档.在我们的例子中,只有一个变化,它通过特殊方法完成:
remoteViews.setImageViewBitmap(R.id.imageView1, appWidgetBitmap);
Run Code Online (Sandbox Code Playgroud)
请记住,要使代码工作,您必须声明绘制模拟时钟的可用空间.根据您声明的内容widget_provider.xml,您可以确定尺寸ImageView.请注意,在绘制之前,您必须将dp单位转换为px单位:
// You'll have to determine tour own dimensions of space to which analog clock is drawn.
final int APP_WIDGET_WIDTH_DP = 210; // Taken from widget_provider.xml: android:minWidth="210dp"
final int APP_WIDGET_HEIGHT_DP = 210; // Taken from widget_provider.xml: android:minHeight="210dp"
final int availableWidth = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, APP_WIDGET_WIDTH_DP, r.getDisplayMetrics()) + 0.5f);
final int availableHeight = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, APP_WIDGET_HEIGHT_DP, r.getDisplayMetrics()) + 0.5f);
Run Code Online (Sandbox Code Playgroud)
我在这里粘贴了Service子类的完整代码.
同样在顶部,您将找到负责设置将显示的时间的代码 - 根据需要进行修改:
mCalendar = new Time();
// Line below sets time that will be displayed - modify if needed.
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
Run Code Online (Sandbox Code Playgroud)
另外,不要忘记Service在AndroidManifest.xml文件中声明此和app小部件,例如:
<receiver
android:name="TimeSettableAnalogClockAppWidget"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="android.appwidget.action.APPWIDGET_DISABLED"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider"/>
</receiver>
<service android:name="TimeSettableAnalogClockService"/>
Run Code Online (Sandbox Code Playgroud)
有关使用服务更新应用小部件的最重要信息,请参阅此博客文章.
调度更新是在onUpdate()您的AppWidgetProvider子类的方法中完成的- 在您的AndroidManifest.xml文件中声明的on .PendingIntent当从主屏幕移除app小部件时,我们还需要删除.这是在重写onDisabled()方法中完成的.请记住声明将调用每种方法之一的两个操作:APPWIDGET_UPDATE和APPWIDGET_DISABLED.见AndroidManifest.xml上面的摘录.
package com.example.anlogclocksettimeexample;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
public class TimeSettableAnalogClockAppWidget extends AppWidgetProvider {
private PendingIntent service = null;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// super.onUpdate(context, appWidgetManager, appWidgetIds);
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Calendar time = Calendar.getInstance();
time.set(Calendar.SECOND, 0);
time.set(Calendar.MINUTE, 0);
time.set(Calendar.HOUR, 0);
final Intent intent = new Intent(context, TimeSettableAnalogClockService.class);
if (service == null) {
service = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}
alarmManager.setRepeating(AlarmManager.RTC, time.getTime().getTime(), 1000 * 60 /* ms */, service);
}
@Override
public void onDisabled(Context context) {
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(service);
}
}
Run Code Online (Sandbox Code Playgroud)
最后一行onUpdate()方法安排重复事件每60秒发生一次,第一次更新立即发生.
AnalogClock仅绘制一次使用上面的代码,只调用一次服务的最简单方法是及时安排单个事件而不是重复一个.alarmManager.setRepeating()用以下行简单替换呼叫:
alarmManager.set(AlarmManager.RTC, time.getTime().getTime(), service);
Run Code Online (Sandbox Code Playgroud)
下面是一个自定义AnalogClock应用程序窗口小部件的屏幕截图,其时间只设置一次(注意状态栏中显示的模拟时钟时间和时间之间的差异):
