Как добавить виджет приложения для Android?
Известно, что многие из установленных на телефоне приложений для 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 } } |
Выход: