如何添加 Android 应用程序的小部件?
众所周知,手机上安装的许多安卓应用程序都包含小部件。最常见的示例是日历和时钟小部件。那么这些小部件是什么?小部件只是一个位于主屏幕上的迷你应用程序,除了通常出现在主屏幕上的小型启动器图标。小部件确实占用更多空间并显示应用程序的最新信息。其中一些也是用户可调整大小的。小部件最常见的用例是启动应用程序或它的某些特定活动。
小部件基本上是使用接收器与应用程序通信的广播消息,因此您还必须将其包含到您的清单文件中。这似乎需要做很多工作,感谢 Android Studio,它可以为我们完成所有这些工作。所以,只需去 Android Studio 点击app->New->Widget->AppWidget 。给它一个名字,你就完成了小部件的设置。您甚至可以检查它是否在安装后将拥有自己的带有 Simple TextView 的小部件。
现在,在简要解释了小部件是什么之后,让我们深入了解如何创建它。设置应用程序的小部件分为三个步骤。
- 第 1 步:一个 WidgetProviderClass 说,MyWidget,它扩展了 AppWidgetProvider 类。
- 第 2 步:一个 WidgetProviderInfo,它是一个描述 Widget 元数据的 XML,包括最小高度和宽度等信息。
- 第 3 步:一个小部件布局文件,它将描述您的小部件的外观,但它受到其他布局文件的限制。
主活动文件
现在让我们来创建我们自己的现在需要编码的自定义小部件。在 res 目录的 Layout 文件夹中按以下方式创建一个MainActivity.xml文件,其中包含一个 Listview。
XML
<--!MainActivity.xml-->
Java
import android.appwidget.AppWidgetManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class DetailsActivity extends AppCompatActivity {
TextView name, content;
ImageView addToWidget;
boolean added = false;
// Take your steps of food processing as String variables
// recipe1 and recipe2.
private String recipe1
= "Step1: Take a Lemon and required no of glasses of water" +
"Step2: Squeeze out the lemon juice into glasses,stir well" +
"and put iceCubes before serve";
private String recipe2
= "Step1: Take a bread and apply some butter on it" +
"Step2:Put it in the toaster and it is ready";
ArrayList steps = new ArrayList();
public static Recipe recipe;
AppWidgetManager appWidgetManager;
int appWidgetId;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// attach xml file for detailsActivity,that will
// show detail of every food item
setContentView(R.layout.activity_details);
// Add Steps into step ArrayList
steps.add(recipe1);
steps.add(recipe2);
addToWidget = findViewById(R.id.addToWidget);
// AppWidgetManager manages creating and updating
// the multiple widgets an application can have.
appWidgetManager = AppWidgetManager.getInstance(
DetailsActivity.this);
appWidgetId = 1;
// Each AppWidget has a different appWidgetId to
// make it unique.
name = findViewById(R.id.name);
content = findViewById(R.id.steps);
final String heading
= getIntent().getStringExtra("name");
final int pos = getIntent().getIntExtra("pos", -1);
recipe = new Recipe(heading, steps.get(pos));
name.setText(heading);
content.setText(steps.get(pos));
// Attach clickListener on ImageView Object so when
// we will click it will handle the widget adding
// code.
addToWidget.setOnClickListener(
new View.OnClickListener() {
@Override public void onClick(View view)
{
added
= !added; // boolean variable to
// know the state ,if
// widget is added or not.
Toast
.makeText(DetailsActivity.this,
"Click",
Toast.LENGTH_SHORT)
.show();
if (added) {
// Calling updateAppWidget static
// method of RecipeWidget to update
// widgets of app
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
recipe);
Toast
.makeText(DetailsActivity.this,
"Added to Widget",
Toast.LENGTH_SHORT)
.show();
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.add_widget));
}
else {
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.not_widget));
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
null);
}
}
});
}
// This method was created to pass Recipe object
// information to AppWidget.
public static Recipe getRecipe() { return recipe; }
}
XML
<--!DetailsActivity.xml>
Java
import android.appwidget.AppWidgetManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class DetailsActivity extends AppCompatActivity {
TextView name, content;
ImageView addToWidget;
boolean added = false;
// Take your steps of food processing as String variables
// recipe1 and recipe2.
private String recipe1
= "Step1: Take a Lemon and required no of glasses of water" +
"Step2: Squeeze out the lemon juice into glasses,stir well" +
"and put iceCubes before serve";
private String recipe2
= "Step1: Take a bread and apply some butter on it" +
"Step2:Put it in the toaster and it is ready";
ArrayList steps = new ArrayList();
public static Recipe recipe;
AppWidgetManager appWidgetManager;
int appWidgetId;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// attach xml file for detailsActivity,that will
// show detail of every food item
setContentView(R.layout.activity_details);
// Add Steps into step ArrayList
steps.add(recipe1);
steps.add(recipe2);
addToWidget = findViewById(R.id.addToWidget);
// AppWidgetManager manages creating and updating
// the multiple widgets an application can have.
appWidgetManager = AppWidgetManager.getInstance(
DetailsActivity.this);
appWidgetId = 1;
// Each AppWidget has a different appWidgetId to
// make it unique.
name = findViewById(R.id.name);
content = findViewById(R.id.steps);
final String heading
= getIntent().getStringExtra("name");
final int pos = getIntent().getIntExtra("pos", -1);
recipe = new Recipe(heading, steps.get(pos));
name.setText(heading);
content.setText(steps.get(pos));
// Attach clickListener on ImageView Object so when
// we will click it will handle the widget adding
// code.
addToWidget.setOnClickListener(
new View.OnClickListener() {
@Override public void onClick(View view)
{
added
= !added; // boolean variable to
// know the state ,if
// widget is added or not.
Toast
.makeText(DetailsActivity.this,
"Click",
Toast.LENGTH_SHORT)
.show();
if (added) {
// Calling updateAppWidget static
// method of RecipeWidget to update
// widgets of app
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
recipe);
Toast
.makeText(DetailsActivity.this,
"Added to Widget",
Toast.LENGTH_SHORT)
.show();
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.add_widget));
}
else {
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.not_widget));
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
null);
}
}
});
}
// This method was created to pass Recipe object
// information to AppWidget.
public static Recipe getRecipe() { return recipe; }
}
Java
package com.tanya.widgettutorial;
public class Recipe {
// The recipe include name of food item and steps to
// cook it.
private String name;
private String steps;
public Recipe(String name, String steps)
{
this.name = name;
this.steps = steps;
}
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSteps() { return steps; }
Java
package com.tanya.widgettutorial;
public class Recipe {
// The recipe include name of food item and steps to
// cook it.
private String name;
private String steps;
public Recipe(String name, String steps)
{
this.name = name;
this.steps = steps;
}
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSteps() { return steps; }
- 现在创建一个Java文件,初始化所有视图并设置 Listview,同时用项目填充它。
- 将Java文件命名为MainActivity。Java。
Java
import android.appwidget.AppWidgetManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class DetailsActivity extends AppCompatActivity {
TextView name, content;
ImageView addToWidget;
boolean added = false;
// Take your steps of food processing as String variables
// recipe1 and recipe2.
private String recipe1
= "Step1: Take a Lemon and required no of glasses of water" +
"Step2: Squeeze out the lemon juice into glasses,stir well" +
"and put iceCubes before serve";
private String recipe2
= "Step1: Take a bread and apply some butter on it" +
"Step2:Put it in the toaster and it is ready";
ArrayList steps = new ArrayList();
public static Recipe recipe;
AppWidgetManager appWidgetManager;
int appWidgetId;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// attach xml file for detailsActivity,that will
// show detail of every food item
setContentView(R.layout.activity_details);
// Add Steps into step ArrayList
steps.add(recipe1);
steps.add(recipe2);
addToWidget = findViewById(R.id.addToWidget);
// AppWidgetManager manages creating and updating
// the multiple widgets an application can have.
appWidgetManager = AppWidgetManager.getInstance(
DetailsActivity.this);
appWidgetId = 1;
// Each AppWidget has a different appWidgetId to
// make it unique.
name = findViewById(R.id.name);
content = findViewById(R.id.steps);
final String heading
= getIntent().getStringExtra("name");
final int pos = getIntent().getIntExtra("pos", -1);
recipe = new Recipe(heading, steps.get(pos));
name.setText(heading);
content.setText(steps.get(pos));
// Attach clickListener on ImageView Object so when
// we will click it will handle the widget adding
// code.
addToWidget.setOnClickListener(
new View.OnClickListener() {
@Override public void onClick(View view)
{
added
= !added; // boolean variable to
// know the state ,if
// widget is added or not.
Toast
.makeText(DetailsActivity.this,
"Click",
Toast.LENGTH_SHORT)
.show();
if (added) {
// Calling updateAppWidget static
// method of RecipeWidget to update
// widgets of app
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
recipe);
Toast
.makeText(DetailsActivity.this,
"Added to Widget",
Toast.LENGTH_SHORT)
.show();
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.add_widget));
}
else {
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.not_widget));
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
null);
}
}
});
}
// This method was created to pass Recipe object
// information to AppWidget.
public static Recipe getRecipe() { return recipe; }
}
输出:
详细活动文件
现在,我们在食谱列表中添加了两个项目,每个项目都包含一个附加的 clicklistener,它将导航到DetailsActivity。 Java具有通过意图传递的预期信息。以下是DetailsActivity.xml的布局,其中包含两个 textview 和一个 AddWidget Button(ImageView)。
XML
<--!DetailsActivity.xml>
- 创建AppWidgetManager对象的实例。
- 给它一个 id,即AppWidgetId ,使其独一无二。
- 使用app->new->vector 资产->选择您希望图像显示的可绘制对象,就像我们选择了星形矢量( R.drawable.addToWidget )一样。
Java
import android.appwidget.AppWidgetManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
public class DetailsActivity extends AppCompatActivity {
TextView name, content;
ImageView addToWidget;
boolean added = false;
// Take your steps of food processing as String variables
// recipe1 and recipe2.
private String recipe1
= "Step1: Take a Lemon and required no of glasses of water" +
"Step2: Squeeze out the lemon juice into glasses,stir well" +
"and put iceCubes before serve";
private String recipe2
= "Step1: Take a bread and apply some butter on it" +
"Step2:Put it in the toaster and it is ready";
ArrayList steps = new ArrayList();
public static Recipe recipe;
AppWidgetManager appWidgetManager;
int appWidgetId;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// attach xml file for detailsActivity,that will
// show detail of every food item
setContentView(R.layout.activity_details);
// Add Steps into step ArrayList
steps.add(recipe1);
steps.add(recipe2);
addToWidget = findViewById(R.id.addToWidget);
// AppWidgetManager manages creating and updating
// the multiple widgets an application can have.
appWidgetManager = AppWidgetManager.getInstance(
DetailsActivity.this);
appWidgetId = 1;
// Each AppWidget has a different appWidgetId to
// make it unique.
name = findViewById(R.id.name);
content = findViewById(R.id.steps);
final String heading
= getIntent().getStringExtra("name");
final int pos = getIntent().getIntExtra("pos", -1);
recipe = new Recipe(heading, steps.get(pos));
name.setText(heading);
content.setText(steps.get(pos));
// Attach clickListener on ImageView Object so when
// we will click it will handle the widget adding
// code.
addToWidget.setOnClickListener(
new View.OnClickListener() {
@Override public void onClick(View view)
{
added
= !added; // boolean variable to
// know the state ,if
// widget is added or not.
Toast
.makeText(DetailsActivity.this,
"Click",
Toast.LENGTH_SHORT)
.show();
if (added) {
// Calling updateAppWidget static
// method of RecipeWidget to update
// widgets of app
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
recipe);
Toast
.makeText(DetailsActivity.this,
"Added to Widget",
Toast.LENGTH_SHORT)
.show();
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.add_widget));
}
else {
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.not_widget));
RecipeWidget.updateAppWidget(
DetailsActivity.this,
appWidgetManager, appWidgetId,
null);
}
}
});
}
// This method was created to pass Recipe object
// information to AppWidget.
public static Recipe getRecipe() { return recipe; }
}
输出:
食谱。 Java文件
现在,每个食谱都包含一个食谱名称(字符串)和一个食谱步骤(字符串),因此为了便于维护,我们将创建一个食谱对象。
Java
package com.tanya.widgettutorial;
public class Recipe {
// The recipe include name of food item and steps to
// cook it.
private String name;
private String steps;
public Recipe(String name, String steps)
{
this.name = name;
this.steps = steps;
}
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSteps() { return steps; }
关于小部件你必须知道的三个词:
- RemoteView:现在,我之前提到小部件布局与任何其他布局相同。因此,基本上,小部件布局基于 RemoteView,因为它们在您的主屏幕上被视为单独的应用程序。 RemoteView 用于描述将在另一个进程中显示的视图层次结构。
- onUpdate()方法: onUpdate()方法在创建新 Widget 时以及在 Widgetinfo.xml 文件中设置的每个更新间隔期间调用,即在您为 xml 目录下的应用程序创建 Widget 时生成。
- AppWidgetManager 类:该类包含有关家中存在的小部件的所有信息。它还提供对所有现有小部件的访问强制更新。
食谱小部件。Java
Java
package com.tanya.widgettutorial;
public class Recipe {
// The recipe include name of food item and steps to
// cook it.
private String name;
private String steps;
public Recipe(String name, String steps)
{
this.name = name;
this.steps = steps;
}
// Getters and Setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSteps() { return steps; }
输出: