Widget开发心得及几个问题

在Launcher中增加一个widget,需要以下几个步骤:

  1. 修改AndroidManifest.xml,在其中引用widgetexample_info.xml

            <receiver android:name=".widget.WidgetExample" >
                <intent-filter>
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                </intent-filter>
    
                <meta-data
                    android:name="android.appwidget.provider"
                    android:resource="@xml/widgetexample_info" />
            </receiver>

  2. 将源文件放入src目录下合适的位置

  3. widgetexample_info.xml 放入res/xml, 其中引用layout文件

  4. layout文件 放入res/layout


在开发的过程中,遇到如下几个问题:

Widget 中不能自订字体 

我在网上查了刚好有人碰到同样的问题,并且提出了一个很好的解决方案(http://www.hksilicon.com/kb/cn/articles/486492/Android-Widget)。这里引用一下:

在 Activity 中,可以用以下的方法使用其他字型:

Typeface customTypeFace = Typeface.createFromAsset(getAssets(),"fonts/custom_font.ttf");
((TextView)findViewById(R.id.custom_text_view)).setTypeface(customTypeFace);

可是在 Widget 中,由于只能使用 RemoteViews,没有 setTypeface。要使用其他非内置的字型时,只能将文字变成 Bitmap,然后在 ImageView 显示。

问题来了,怎样知道文字变成图片后的长度和阔度呢?网上有不同的方法,但都不能因应 font size 而自动调整。几经研究后,才找到以下的方法:

Paint textPaint = new Paint();
textPaint.setTypeface(typeface);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextAlign(Align.LEFT);

Rect bound = new Rect();
textPaint.getTextBounds(text, 0, text.length(), bound);

int imageViewSize = Math.max(Math.abs(bound.top), bound.width());
Bitmap myBitmap = Bitmap.createBitmap(imageViewSize, imageViewSize, Bitmap.Config.ARGB_8888);
Canvas myCanvas = new Canvas(myBitmap);
myCanvas.drawText(text, -bound.left + (imageViewSize - bound.width())/2, -bound.top + (imageViewSize -bound.height())/2, textPaint);

重点是 imageViewSize 的设定和最后 drawText 的 xy 座标。不过以上的字型是正方形的字体,若大家用的为长方形的话,可能又有所不同。


Widget的更新周期 

不要倚赖 updatePeriodMillis 作更新,因为它的最短的更新时间为 30 分钟,就算你设定为一分钟也没有用。想要更短的更新时间的话只能用 AlarmManager,或者构建service用来更新数据。我这里需要更新桌面时钟,所以直接监听了时钟相关的intent。
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_TIME_TICK);
    filter.addAction(Intent.ACTION_TIME_CHANGED);
    filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    context.getApplicationContext().registerReceiver(mReceiver, filter);

Widget的context和Application的context

上面注册监听intent,一开始我直接用的
context.registerReceiver(mReceiver, filter);
一运行就报错: android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents
查阅资料发现,将这里不能直接用context,而应该使用
context.getApplicationContext()

由此看来widget的context和application的context,生命周期是不同的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值