ANDROID APP WIDGET WITH LISTVIEW
android
40
White

tienbm viết ngày 07/03/2016

Thân bài

Để làm một widget với một listview bao gồm các thành phần:

1: AppWidgetProvider

Được extend từ BroadcastReceiver được dùng đến như một controlled .
Bao gồm 3 method
+Widget Update :được gọi khi update widget
+Widget Delete :được gọi khi xóa một widget
+Widget enabled/disabled :được gọi khi tất cả widget bị xóa hay mở
Tiếp theo cần một file config xml
Mỗi một widget cần phải có một file widgetinfo.xml được đặt trong res/xml

widgetinfo.xml
<?xml version="1.0" encoding="utf-8"?>
<!--Activity sẽ được mở khi thêm 1 widget ra screen..Có thể bỏ qua  -->
android:configure="com.tienbm.ConfigActivity"

<!-- layout mà sử dụng cho widget-->
android:initialLayout="@layout/widget_layout"

<!-- kích thước nhỏ nhất của widget -->
android:minHeight="110dip"
android:minWidth="250dip"

<!-- Ảnh đại diện cho widget -->
android:previewImage="@drawable/widget_preview"

<!-- Chế độ resize có thể mở rộng theo 2 chiều -->
android:resizeMode="vertical|horizontal"

<!-- widget sẽ được update sau một khoảng thời gian mặc định..Hiện tại là 30p-->
<!-- 30 min =30x60x1000 -->
android:updatePeriodMillis="1800000"/>

Tiếp theo cần thêm một khai báo trên AndroidManifest.xml

<receiver android:name=".WidgetProvider" >
   <intent-filter>
<!-- This widget provider receives broadcast with following action 
       name or simply onUpdate of AppWidgetProvider is called -->
     <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
   </intent-filter>
<!-- linking up xml file of appwidget-provider to AppWidgetProvider -->
     <meta-data
          android:name="android.appwidget.provider"
           android:resource="@xml/widgetinfo" />
</receiver>

Tao layout cho widget

widget_layout.xml
    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/black" >

    <!-- ListView to be shown on widget -->
    <ListView
        android:id="@+id/listViewWidget"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Empty view is show if list items are empty -->
    <TextView
        android:id="@+id/empty_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="@string/empty_string"
        android:textColor="#ffffff"
        android:textSize="20sp"
        android:visibility="gone" />

</LinearLayout>

Ngay bây giờ để listview có thể hoạt động thì phải cần data và adapter

2:RemoteViewsService:

Để gọi một adapter bắt buộc phải thông qua một service.Ở đây bạn cũng có thể get data từ một nguồn nào đó rồi truyền vào adapter

public class WidgetService extends RemoteViewsService {
/*
* So pretty simple just defining the Adapter of the listview
* here Adapter is ListProvider
* */

@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
      int appWidgetId = intent.getIntExtra(
      AppWidgetManager.EXTRA_APPWIDGET_ID,
      AppWidgetManager.INVALID_APPWIDGET_ID);
       return (new ListProvider(this.getApplicationContext(), intent));
   }

}

Tạo xog service mở file AndroidManifest.xml và thêm khai báo

 <service
   android:name=".WidgetService"
   android:permission="android.permission.BIND_REMOTEVIEWS" /

3:RemoteViewsFactory:

Cũng giống như adapter của listview

/**
* If you are familiar with Adapter of ListView,this is the same as adapter
* with few changes
*
*/
public class ListProvider implements RemoteViewsFactory {
private ArrayList listItemList = new ArrayList();
private Context context = null;
private int appWidgetId;

public ListProvider(Context context, Intent intent) {
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);

populateListItem();
}

private void populateListItem() {
for (int i = 0; i &lt; 10; i++) {
        ListItem listItem = new ListItem();
        listItem.heading = "Heading" + i;
        listItem.content = i
        + " This is the content of the app widget listview.";
        listItemList.add(listItem);
    }

}

@Override
public int getCount() {
return listItemList.size();
}

@Override
public long getItemId(int position) {
return position;
}

/*
*Similar to getView of Adapter where instead of View
*we return RemoteViews
*
*/
@Override
public RemoteViews getViewAt(int position) {
    final RemoteViews remoteView = new RemoteViews(
    context.getPackageName(), R.layout.list_row);
    ListItem listItem = listItemList.get(position);
    remoteView.setTextViewText(R.id.heading, listItem.heading);
    remoteView.setTextViewText(R.id.content, listItem.content);
    return remoteView;
 }
}

Cuối cùng là AppWidgetProvider

WidgetProvider.java
public class WidgetProvider extends AppWidgetProvider {

/**
* this method is called every 30 mins as specified on widgetinfo.xml
* this method is also called on every phone reboot
**/

@Override
public void onUpdate(Context context, AppWidgetManager 
                appWidgetManager,int[] appWidgetIds) {

/*int[] appWidgetIds holds ids of multiple instance 
 * of your widget
 * meaning you are placing more than one widgets on 
 * your homescreen*/
 for (int i = 0; i <appWidgetIds.length; ++i) {
     RemoteViews remoteViews = updateWidgetListView(context,
                                           appWidgetIds[i]);
     appWidgetManager.updateAppWidget(appWidgetIds[i], 
                                           remoteViews);
    }
 super.onUpdate(context, appWidgetManager, appWidgetIds);
}

private RemoteViews updateWidgetListView(Context context,
                                     int appWidgetId) {

   //which layout to show on widget
   RemoteViews remoteViews = new RemoteViews(
         context.getPackageName(),R.layout.widget_layout);

  //RemoteViews Service needed to provide adapter for ListView
  Intent svcIntent = new Intent(context, WidgetService.class);
  //passing app widget id to that RemoteViews Service
  svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
  //setting a unique Uri to the intent
  //don't know its purpose to me right now
  svcIntent.setData(Uri.parse(
                    svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
  //setting adapter to listview of the widget
  remoteViews.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
                                svcIntent);
  //setting an empty view in case of no data
  remoteViews.setEmptyView(R.id.listViewWidget, R.id.empty_view);
  return remoteViews;
 }

}

Tiếp theo để refesh từ một button widget ta sử dụng một intent được thêm vào updateWidgetListView như sau

 Intent intent = new Intent(context, WidgetProvider .class);
 intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
 intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
 PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
 //R.id.actionButton:id của button
 remoteViews.setOnClickPendingIntent(R.id.actionButton, pendingIntent);

Chú ý

Dùng để update cho toàn bộ widget
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
Chỉ update widget hiện tại
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);

Refesh từ một activity

Intent intent = new Intent(this, WidgetProvider.class);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
int ids[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids);
sendBroadcast(intent);

Kết bài

Vậy là đã hoàn thành một widget.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

tienbm

5 bài viết.
3 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
8 1
Mở đầu Deep Links for App Content theo mình hiểu thì là liên kết tới app của bạn thông qua một đường link trên site nào đó.Đơn giản hơn là sẽ mở a...
tienbm viết 2 năm trước
8 1
White
2 1
Upload a File using Retrofit Có rất nhiều docs hướng dẫn nhưng mình thấy upload như này hiệu quả nhất nên note lại Mình sẽ đi vào ví dụ luôn cho ...
tienbm viết 10 tháng trước
2 1
White
1 0
Thêm hành động sử dụng hành động trên bàn phím android http://javatechig.com/android/androidkeyboardhackshidekeyboardandcustomizeactions 07052016
tienbm viết gần 2 năm trước
1 0
Bài viết liên quan
White
8 4
Ở bài viết lần trước](), tôi đã nói về "hoàn cảnh" tại sao tôi lại cần sử dụng openssl trên android native, đồng thời cũng đã giới thiệu qua về các...
huydx viết gần 3 năm trước
8 4
White
6 0
Gradle là gì? Sao lại xử dụng Gradle trong Android? Sử dụng Gradle như thế nào? Đó là một trong rất nhiều câu hỏi mà các Android developer mới làm ...
khoatd92 viết 9 tháng trước
6 0
White
6 0
Để play video trên webview thì tất nhiên trình duyệt web của thiết bị android của bạn phải hổ trợ HTML5. Trong bài này tôi xin nói về cách play vid...
Anh Nguyễn viết gần 3 năm trước
6 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
5 bài viết.
3 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!