Android AppWidget如何支持复杂的View

Android AppWidget如何支持复杂的View

一直想知道如何在AppWidget里面添加 ListView,EditText 这些复杂的View.我们知道要在AppWidget里添加 View都是通过RemoteView来做到了,然而RemoteView本身功能很弱,支持的操作很少,而且支持RemoteView的Widget很 少:
在Dev Guide中有下面这段:

A RemoteViews object (and, consequently, an App Widget) can support the following layout classes:

And the following widget classes:

Descendants of these classes are not supported.

所以从这里可以知道,为什么在AppWidget里添加 EditText会显示LoadError了,因为本身它就不支持这些复杂的 Widget.


但我们又会有疑问了, 为什么Google Search会有EditText呢?其实这些都是假象,并不是AppWidget支持EditText.

具体怎么回 事,我猜有两种情况:

1.一种确实是EditText但确不是AppWidget 支持的,而是集成到Home里面去了。

具 体可以参考这里:http://www.eoeandroid.com/archiver/tid-1729.html

2.最新的SDK 1.6中,显示在桌面的EditText只是一个ImageView,而这个ImageView的背景就是EditText的截图了。我们点中这个 “EditText”后,会调起一个Activity,

而这个Activity就是复杂输入的EditText,并且会全屏显示。所以我们 就误以会那是一个单纯的EditText.


最近看过HTC Hero Sense UI的人都看到了,它的AppWidget是确实支持复杂Widget的,比如:Bookmark Widget:ListView/GridView,Twitter Widget:EditText. 这些确实是我们可以看到的,但它是怎么做到的呢?我也很想知道,AppWidget支持到那么强大,甚至超过了本身AP的功能,很抢眼。但不管是怎么实现 的,我想人家肯定是花了大力气去做到了,我猜想可能是将Google 提供的AppWidget进行了比较大的改动。我们查看一下framework下的appwidget:

pjq@gentoo-pjq ~/android/donut $ ls frameworks/base/core/java/android/appwidget/ -lh
total 60K
-rw-r--r-- 1 pjq users 7.9K 2009-09-29 21:49 AppWidgetHost.java
-rw-r--r-- 1 pjq users  12K 2009-09-29 21:49 AppWidgetHostView.java
-rw-r--r-- 1 pjq users  14K 2009-09-29 21:49 AppWidgetManager.java
-rw-r--r-- 1 pjq users  691 2009-09-29 21:49 AppWidgetProviderInfo.aidl
-rw-r--r-- 1 pjq users 5.6K 2009-09-29 21:49 AppWidgetProviderInfo.java
-rwxr-xr-x 1 pjq users 6.3K 2009-09-29 21:49 AppWidgetProvider.java
-rw-r--r-- 1 pjq users 1.5K 2009-09-29 21:49 package.html

可以看 到,appwidget的文件很少,虽然不能说明什么,但按照正常的推理,文件少功能一般也强大不到哪里去,这种想法虽然有些牵强,但暂且就这样认为吧。

所 以我想HTC一定是将这里给改动了,以支持复杂的Widget,有知道内情的透露一点最好了。

要知道RemoteView的功能很少,特别 是对事件处理的能力,都需要通过PendingIntent,传到BroadcastReceiver去处理。所以这里对一些事件处理也仅限于比较简单事 件:比如说:Button Clicked,其它的我好像还没怎么用过,orz....  对复杂的View:比如ListView(当然这里还不支持,打个比方),ListView里面那么多Item,要设置Listener,要传值,这些 RemoteView都不能像一个单纯的Activity那样处理,呵呵 ,扯远了,如果能的话,我也就没有必要这么费劲的写这篇博客了。


写 这篇文章的时候,我已经实现了在 AppWidget里显示ListView/GridView这些复杂的Widget了,我这里只说显示,并不是说我已经能让AppWidget支持 ListView/GridView了。所以我这里更倾向于教你如何在AppWidget里支持显示ListView/GridView这些复杂的 Widget.


我们知道AppWidget只支持RemoteView,那哪些Widget是RemoteView 呢,我来教你搜一下:

pjq@gentoo-pjq ~/android/donut/frameworks/base/core/java/android/widget $ grep -i -n -A 1  @remoteview *.java
AbsoluteLayout.java:40:@RemoteView
AbsoluteLayout.java-41-public class AbsoluteLayout extends ViewGroup {
--
AnalogClock.java:39:@RemoteView
AnalogClock.java-40-public class AnalogClock extends View {
--
Button.java:58:@RemoteView
Button.java-59-public class Button extends TextView {
--
Chronometer.java:45:@RemoteView
Chronometer.java-46-public class Chronometer extends TextView {
--
FrameLayout.java:47:@RemoteView
FrameLayout.java-48-public class FrameLayout extends ViewGroup {
--
ImageButton.java:66:@RemoteView
ImageButton.java-67-public class ImageButton extends ImageView {
--
ImageView.java:55:@RemoteView
ImageView.java-56-public class ImageView extends View {现在没什么问题。
--
LinearLayout.java:44:@RemoteView
LinearLayout.java-45-public class LinearLayout extends ViewGroup {
--
ProgressBar.java:122:@RemoteView
ProgressBar.java-123-public class ProgressBar extends View {
--
RelativeLayout.java:66:@RemoteView
RelativeLayout.java-67-public class RelativeLayout extends ViewGroup {
--
TextView.java:186:@RemoteView
TextView.java-187-public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {

就是这些了,类名前面加了"@RemoteView",和我 前面列出的那些是不是一样的呢?--对了,就是这些了,所以以后你想知道你在AppWidget支持哪些Widget就可以像我这样去搜一下就知道了,这 样最适时。


写到这里我已经将最关键的内容都已经写出来了,还不明白?

其实简单点讲就是在一个 Widget类前面加上"@RemoteView",加上了它就等于说RemoteView可以支持它, RemoteView支持就等于是AppWidget支持这它了。

好了,现在你只需要自定义一些你需要的Widget,加 上"@RemoteView"标记,你就可以在AppWidget里使用它了。


关于如何自定义一个Widget你完 全可以参照frameworks/base/core/java/android/widget已有的这些Widget.依样加一个。

其实 如果你需要自定义一个Widget,比如说支持ListView,你可以先在一个activity里实现它,然后将它移到framework下面去。


这 里说一下可能需要注意的地方:

1.如果有多个文件,需要Package的时候,名字最好按照这样的形 式:android.widget.bookmark

其中bookmark就是你要添加一个Widget存放的地方,这样的话你就可以在 frameworks/base/core/java/android/widget 目录下新增bookmark文件夹,将java文件放在这个目录下。

如果你新增的Widget只有一个java文件就可以不用这样了,可以 完全按照已经存在的Widget的样子,直接将java文件放到frameworks/base/core/java/android/widget目录 下。


2.资源文件存放:

frameworks/base/core/res/res 

资 源文件都放到这个目录下。


3.资源的引用:

要用这样的方式引用:com.android.internal.R.drawable.**


4. 记着在这个Customer Widget类名前加上"@RemoteView"标记.

 

 


 

这 些都做完了,你就已经将一个自定义的Widget添加到framework了。之后要做的工作就是编译整个工程了,重新生成SDK。

最 后你就可以在AppWidget引用你新加的这个Widget了:com.widget.bookmark.***。

至 此,你已经用上了你新加的这个Widget,并且可以加到AppWidget.

 


在 新加Widget的时候可能会遇到的一些问题:

1.构造函数初始化问题。

如 果在XML里写的layout不能直接指定哪个构造函数进行初始化,如果你不确定会跑哪个构造函数,最好在每个构造函数里对加上log,这样你就知道初始 化时会跑哪个构造函数,并将初始化的工作加到里面。我当时就遇到了这个问题,因为用XML写layout,你不能显示调用哪个构造函数进行初始化,如果你 将初始化的操作放到一个不会自动跑到的构造函数里面,那面你运行的时候就好像没添加到Widget一样。


2. 其它的再说吧。


后继我可能会写如何添加 Bookmark Widget(支持ListView/GridView,见过HTC Hero Sense UI吗,就是那个样子)到AppWidget,敬请期待!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio中仿制聊天app可以通过以下步骤实现: 1. 创建一个新的Android项目,并设置项目名称和包名。 2. 在布局文件中设计聊天界面的UI,包括消息列表、输入框和发送按钮等组件。 3. 创建一个Java类来处理聊天逻辑,例如ChatActivity.java。 4. 在ChatActivity.java中,使用RecyclerView来显示消息列表,并创建一个适配器来管理消息数据。 5. 实现发送消息的功能,当用户点击发送按钮时,将消息添加到消息列表中,并更新RecyclerView的显示。 6. 添加数据库支持,可以使用SQLite或者Room来保存聊天记录。 7. 实现其他功能,例如消息的发送和接收、消息的时间戳、头像等。 以下是一个简单的示例代码,用于演示如何在Android Studio中创建一个仿聊天app: ```java // ChatActivity.java public class ChatActivity extends AppCompatActivity { private RecyclerView recyclerView; private ChatAdapter chatAdapter; private List<Message> messageList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); recyclerView = findViewById(R.id.recyclerView); messageList = new ArrayList<>(); chatAdapter = new ChatAdapter(messageList); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(chatAdapter); // 添加示例消息 messageList.add(new Message("Hello", true)); messageList.add(new Message("Hi", false)); chatAdapter.notifyDataSetChanged(); } public void sendMessage(View view) { EditText editText = findViewById(R.id.editText); String messageText = editText.getText().toString().trim(); if (!messageText.isEmpty()) { messageList.add(new Message(messageText, true)); chatAdapter.notifyDataSetChanged(); editText.setText(""); } } } ``` ```xml <!-- activity_chat.xml --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="16dp" android:paddingTop="16dp" android:paddingRight="16dp" android:paddingBottom="16dp" tools:context=".ChatActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/inputLayout" android:paddingTop="8dp" android:paddingBottom="8dp" /> <LinearLayout android:id="@+id/inputLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="horizontal"> <EditText android:id="@+id/editText" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="Type a message" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" android:onClick="sendMessage" /> </LinearLayout> </RelativeLayout> ``` ```java // ChatAdapter.java public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> { private List<Message> messageList; public ChatAdapter(List<Message> messageList) { this.messageList = messageList; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Message message = messageList.get(position); holder.messageTextView.setText(message.getText()); if (message.isSentByUser()) { holder.messageTextView.setBackgroundResource(R.drawable.bg_message_sent); } else { holder.messageTextView.setBackgroundResource(R.drawable.bg_message_received); } } @Override public int getItemCount() { return messageList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView messageTextView; public ViewHolder(View itemView) { super(itemView); messageTextView = itemView.findViewById(R.id.messageTextView); } } } ``` ```xml <!-- item_message.xml --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/messageTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" android:textColor="#FFFFFF" android:textSize="16sp" /> ``` 请注意,这只是一个简单的示例,你可以根据自己的需求进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值