Как добавить виджет приложения для Android?

Опубликовано: 5 Января, 2022

Известно, что многие из установленных на телефоне приложений для Android содержат виджеты. Наиболее распространенными примерами являются виджет «Календарь» и «Часы». Так что же это за виджеты? Виджеты - это просто мини-приложение, которое находится на главном экране, помимо небольших значков запуска, которые обычно появляются на главном экране. Виджеты занимают больше места и отображают актуальную информацию о приложении. Размер некоторых из них также можно изменять. Наиболее распространенный вариант использования виджета - запуск приложения или его определенного действия.

Виджет - это, по сути, широковещательное сообщение, которое связывается с приложением с помощью приемника, поэтому вы также должны включить его в свой файл манифеста. Кажется, это большая работа, благодаря Android Studio она может сделать все за нас. Итак, просто зайдите в Android Studio и нажмите app-> New-> Widget-> AppWidget . Дайте ему имя, и вы закончите настройку виджета. Вы даже можете проверить, что после установки будет свой виджет с Simple TextView.

Теперь, после краткого объяснения того, что такое виджет, давайте углубимся в то, как его создать. Чтобы настроить виджет вашего приложения, нужно выполнить три шага.

  • Шаг 1. Класс WidgetProviderClass, скажем, MyWidget, расширяет класс AppWidgetProvider.
  • Шаг 2: WidgetProviderInfo, представляющий собой XML, описывающий метаданные виджета, включая такую информацию, как минимальная высота и ширина.
  • Шаг 3. Файл макета виджета, в котором будет описан внешний вид вашего виджета, но у него есть ограничения по сравнению с другими файлами макета.

Файл MainActivity

Теперь давайте приступим к созданию нашего собственного пользовательского виджета, который сейчас требует кодирования. Создайте файл MainActivity.xml в папке Layout каталога res следующим образом, содержащим Listview.

XML

<--!MainActivity.xml-->
< androidx.constraintlayout.widget.ConstraintLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity" >
<!--List view to display all food items-->
< ListView
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:id = "@+id/recipies"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
</ androidx.constraintlayout.widget.ConstraintLayout >
  • Теперь создайте файл java, инициализирующий все представления и настройку Listview, а также заполнение его элементами.
  • Назовите файл Java как MainActivity.Java .

Джава

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
ListView recipies;
public String[] addRecipie
= new String[] { "Lemonade" , "BreadToast" };
@Override
protected void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
// Attach your aml file with java file here
setContentView(R.layout.activity_main);
// Creating Java object for List of all food items.
recipies = findViewById(R.id.recipies);
// Adapter to hold your data of all food items
ArrayAdapter<String> adapter
= new ArrayAdapter<String>(
this , android.R.layout.simple_list_item_1,
addRecipie);
recipies.setAdapter(adapter);
// Set a clickListener on each item,so on clicking
// item an intent will launch.
recipies.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(
AdapterView<?> adapterView, View view,
int i, long l)
{
Intent in
= new Intent(MainActivity. this ,
DetailsActivity. class );
// putExtra method allows you to pass
// data between two activities easily
in.putExtra( "name" , addRecipie[i]);
in.putExtra( "pos" , i);
startActivity(in);
}
});
}
}

Выход:

Файл DetailsActivity

Теперь мы добавили два элемента в наш список получателей, и каждый элемент содержит прикрепленный прослушиватель кликов, который будет переходить к DetailsActivity.java с предполагаемой информацией, проходящей через намерение. Ниже приведен макет для DetailsActivity.xml, содержащий два текстовых представления и кнопку AddWidget (ImageView).

XML

<--!DetailsActivity.xml>
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".DetailsActivity" >
<!--A Textview to display name of food-->
< TextView
android:id = "@+id/name"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "16dp"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintHorizontal_bias = "0.0"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
<!--A ImageView to let user add a widget by clicking on it -->
< ImageView
android:id = "@+id/addToWidget"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:background = "@android:color/white"
android:clickable = "true"
android:contentDescription = "@string/addtowidget"
android:focusable = "true"
android:src = "@drawable/not_widget"
app:layout_constraintBottom_toTopOf = "@+id/steps"
app:layout_constraintStart_toStartOf = "parent" />
<!--A TextView to show steps -->
< TextView
android:id = "@+id/steps"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintHorizontal_bias = "0.0"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toBottomOf = "@+id/name"
app:layout_constraintVertical_bias = "0.158" />
</ androidx.constraintlayout.widget.ConstraintLayout >
  • Создайте экземпляр объекта AppWidgetManager.
  • Дайте ему идентификатор, например AppWidgetId , чтобы сделать его уникальным.
  • Используйте приложение-> новый-> векторный актив-> выберите чертеж, который вы хотите, чтобы ваше изображение отображалось, как мы выбрали звездный вектор ( R.drawable.addToWidget ).

Джава

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 processig as String variables
// recipie1 and recipie2.
private String recipie1
= "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 recipie2
= "Step1: Take a bread and apply some butter on it" +
"Step2:Put it in the toaster and it is ready" ;
ArrayList<String> steps = new ArrayList<String>();
public static Recipie recipie;
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(recipie1);
steps.add(recipie2);
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 );
recipie = new Recipie(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 RecipieWidget to update
// widges of app
RecipieWidget.updateAppWidget(
DetailsActivity. this ,
appWidgetManager, appWidgetId,
recipie);
Toast
.makeText(DetailsActivity. this ,
"Added to Widegt" ,
Toast.LENGTH_SHORT)
.show();
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.add_widget));
}
else {
addToWidget.setImageDrawable(
getResources().getDrawable(
R.drawable.not_widget));
RecipieWidget.updateAppWidget(
DetailsActivity. this ,
appWidgetManager, appWidgetId,
null );
}
}
});
}
// This method was created to pass Recipe object
// information to AppWidget.
public static Recipie getRecipie() { return recipie; }
}

Выход:

Файл Recipe.Java

Теперь каждый рецепт содержит имя рецепта (строка) и шаги рецепта (строка), поэтому для простоты обслуживания мы создадим объект рецепта.

Джава

package com.tanya.widgettutorial;
public class Recipe {
// The recipie 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() { steps; } return steps; }

Три слова, которые вы должны знать о виджете:

  • RemoteView: Ранее я упоминал, что макет виджета такой же, как и любой другой макет. Итак, в основном макет виджетов основан на RemoteView, потому что они рассматриваются как отдельное приложение на вашем рабочем столе. RemoteView используется для описания иерархии представлений, которая будет отображаться в другом процессе.
  • Метод onUpdate () : метод onUpdate () вызывается при создании нового виджета, а также во время каждого интервала обновления, который установлен в файле Widgetinfo.xml, т.е. генерируется, когда вы создали виджет для своего приложения в каталоге xml.
  • Класс AppWidgetManager: этот класс содержит всю информацию о виджетах, которые есть дома. Он также обеспечивает доступ к обновлениям всех существующих виджетов.

RecipeWidget.Java

Джава

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.util.Log;
import android.widget.RemoteViews;
// Implementation of App Widget functionality.
public class RecipeWidget extends AppWidgetProvider {
public static String TAG = RecipeWidget. class .getName();
static void
updateAppWidget(Context context,
AppWidgetManager appWidgetManager,
int appWidgetId, Recipie recipie)
{
// Create RemoteView Object to handle your view of
// widget
RemoteViews views
= new RemoteViews(context.getPackageName(),
R.layout.recipie_widget);
assert recipie != null ;
// Set what content you want to display on Widget by
// providing id of view and corresponding content
views.setTextViewText(R.id.heading_text,
recipie.getName());
views.setTextViewText(R.id.steps_text,
recipie.getSteps());
appWidgetManager.updateAppWidget(appWidgetId,
views);
}
@Override
public void onUpdate(Context context,
AppWidgetManager appWidgetManager,
int [] appWidgetIds)
{
// There may be multiple widgets active, so update
// all of them
for ( int appWidgetId : appWidgetIds) {
Recipie recipie = DetailsActivity.getRecipie();
Log.d(TAG, recipie.getName());
updateAppWidget(context, appWidgetManager,
appWidgetId, recipie);
}
}
@Override public void onEnabled(Context context)
{
// Enter relevant functionality for when the first
// widget is created
}
@Override public void onDisabled(Context context)
{
// Enter relevant functionality for when the last
// widget is disabled
}
}

Выход:

Хотите более динамичную и конкурентную среду для изучения основ Android?
Щелкните здесь, чтобы перейти к уникальному руководству, составленному нашими экспертами с целью мгновенно подготовить вашу отрасль!