Можно ли в виджете приложения со StackView изменить текст только в одном элементе стека?

Рейтинг: 1Ответов: 1Опубликовано: 13.05.2023

введите сюда описание изображенияЯ сделала виджет со StackView и конфигурационным экраном. Я хочу из конфигурационного экрана изменять текст и фон в элементах стека. Точнее, в одном элементе виджета-стека за раз. Моя конфигурационная активность:

public class ConfigActivity extends Activity {

int widgetID = AppWidgetManager.INVALID_APPWIDGET_ID;
Intent resultValue;

 public final static String WIDGET_PREF = "widget_pref";
 public final static String STECK_TEXT = "steck_text_";
 public final static String STECK_COLOR = "steck_color_";

 //Создаём строку для сохранения текстов в списке 
String textS;

 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// извлекаем ID конфигурируемого виджета из Intent
//Объявим Intent и привяжем его к полученному:
       Intent intent = getIntent();
//Создадим хранилище (Bundle) и выгрузим в
//него данные из полученного интента
       Bundle extras = intent.getExtras();
             if (extras != null) {
  //Получаем и настраиваем идентификатор виджета
 widgetID = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
           AppWidgetManager.INVALID_APPWIDGET_ID);
}
         // и проверяем его корректность.
         //Если widgetID некорректный - выходим
    if (widgetID == AppWidgetManager.INVALID_APPWIDGET_ID) {
              finish();
 }

 // формируем intent ответа с ID для метода setResult
          resultValue = new Intent();             
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetID);
          // отрицательный ответ
      setResult(RESULT_CANCELED, resultValue);

          //Метод  setContentView() устанавливает
          //содержимое активити из layout-файла
            setContentView(R.layout.config);                     
}


//В onClick мы читаем выбранный цвет и введенный
//в поле текст и записываем эти значения в Preferences
public void onClick(View v) {

    //Получаем ID выбранного переключателя 
 int selRBColor = ((RadioGroup) findViewById(R.id.rgColor))
            .getCheckedRadioButtonId();
             int color = Color.RED;

switch (selRBColor) {

       case R.id.radioRed:
            color = Color.parseColor("#ff0040");
            break;

       case R.id.radioGreen:
            color = Color.parseColor("#00ffBF");
            break;
       case R.id.radioBlue:
            color = Color.parseColor("#0080ff");
            break;
}

                  //Создаём EditText
   EditText etText = (EditText) findViewById(R.id.etText);
         //получаем введенный пользователем текст
         //из элементов EditText, используя метод getText()                                                textS=etText.getText().toString();

         // Записываем значения текста с экрана в Preferences
         //и сохраняем его и выбранный цвет
SharedPreferences sp = getSharedPreferences(WIDGET_PREF, MODE_PRIVATE);
Editor editor = sp.edit();
editor.putString(STECK_TEXT + widgetID, etText.getText()
   .toString());
editor.putInt(STECK_COLOR + widgetID, color);
editor.commit();

//Метод getInstance(соntext) позволяет получить экземпляр
//AppWidgetManager с предоставленным объектом 
AppWidgetManager appWidgetManager = AppWidgetManager.                                                                              getInstance(this);          

//Мы вызываем метод updateWidget и передаем туда context,
//AppWidgetManager, SharedPreferences и ID экземпляра, чтобы
//обновить виджет сразу, а не через 40 мин.                                                              StackWidgetProvider.updateWidget(this, appWidgetManager, sp,                                                                               widgetID);         

              // Возвращаем положительный ответ
           setResult(RESULT_OK, resultValue);
             //Закрываем активность конфигуратора
            finish();
 }
}

Мой виджет изменяет либо текст и цвет во всех элементах стека, либо просто выдаёт с этими параметрами простой одиночный виджет без стека в зависимости от местонахождения этого куска кода:

RemoteViews rv = new RemoteViews(context.getPackageName(),
                                             R.layout.widget_item);
// Читаем параметры настройкиPreferences

 sp = context.getSharedPreferences(
                                                      
ConfigActivity.WIDGET_PREF, Context.MODE_PRIVATE);

 if (position<mCount) {             
//Создаём строку для сохранённого текста
String steckText = sp.getString(ConfigActivity.STECK_TEXT+ widgetID, "");                                                                          

//Создаём int для сохранённого цвета
int steckColor = sp.getInt(ConfigActivity.STECK_COLOR +  widgetID, 1);                                                                                                                         

// Настраиваем внешний вид элемента виджета                        

//Вызываем методы для формирования вида элемента виджета  
                                                 

rv.setTextViewText(R.id.widget_item, steckText);   
                                                                                       

rv.setInt(R.id.widget_item, "setBackgroundColor", steckColor);
                                                                            
 }

Я пыталась вставить этот кусок кода и в класс-сервис, и в класс-провайдер, и в конфигурационную активность. Но либо меняется текст и цвет всех элементов стека (если он в сервисе); либо формируется простой одиночный виджет без стека (если он в провайдере); либо меняется цвет и текст только одного элемента стека, остальные прозрачные, они вроде бы есть, но нажать на них нельзя, когда я попробовала вместо id виджета вставить позицию position элемента в SharedPreferences в конф. активности:

Editor editor=sp.edit();
editor.putString(STECK_TEXT + position, etText.getText()
.toString());
editor.putInt(STECK_COLOR + position, color);
editor.commit();

в сервисе:

//Создаём строку для сохранённого текста
 String steckText = sp.getString(ConfigActivity.STECK_TEXT
+ position, "");

//Создаём int для сохранённого цвета
int steckColor = sp.getInt(ConfigActivity.STECK_COLOR +                                                              position, 1);

; либо один элемент стека пытается измениться, но дальше слова "загрузка" ничего не меняется (когда вставила этот кусок в метод onDataSetChanged). Я пробовала указать и id виджета, и позицию элемента в имени при сохранении в SP, но это ничего не изменило.

Я понимаю, почему получаю такие результаты, но не знаю, как мне это исправить. Как изменить текст и цвет только в одном элементе стека? Помогите, пожалуйста, если кто-то делал это. Я прочитала все учебники, в которых есть хоть что-то про виджеты, и все статьи в интернете, но нигде ничего по этому вопросу нет.

Кроме того, после первого выбора параметров в конфигурационной активности в стеке вообще ничего не изменяется. Параметры изменяются только после повторного входа в конфигурационную активность из элемента стека.

Я не понимаю, как и где мне указать, что я изменяю только один элемент в стеке, а не все сразу. И почему после первого выбора параметров в конфигурационной активности стек формируется в соответствии с параметрами заданными в сервисе, а не в соответствии с параметрами выбранными на конфигурационном экране?

Я думаю, что может быть нужно попытаться после конфигурационной активности или в ней формировать новый элемент списка объектов с выбранными параметрами для стека, и только потом формировать стек из списка? Но тогда придётся переделывать весь код. Может быть, есть способ исправить мой код?

Это важно: У меня телефон с API19, поэтому я не могу использовать возможности, которые появились позже.

Ответы

▲ 1

Вся работа происходит в классе RemoteViewsFactoryMy в методе getViewAt. Я, для примера, разукрасил элемент с позицией 0.

public class RemoteViewsServiceMy extends RemoteViewsService{
    @Override
    public RemoteViewsFactory onGetViewFactory( Intent intent ){
        return new RemoteViewsFactoryMy();
    }

    class RemoteViewsFactoryMy implements RemoteViewsFactory{
        String [] data = { "Item 0", "Item 1", "Item 2", "Item 3", "Item 4" };
        @Override
        public void onCreate(){
        }

        @Override
        public void onDataSetChanged(){
        }

        @Override
        public void onDestroy(){
        }

        @Override
        public int getCount(){
            return data.length;
        }

        @Override
        public RemoteViews getViewAt( int position ){
            RemoteViews rv = new RemoteViews(  getPackageName(), R.layout.item );
            rv.setTextViewText( R.id.text_view, data[position] );
            rv.setTextColor( R.id.text_view, position==0?0xfff00000:0xff000000 );
            rv.setInt( R.id.text_view, "setBackgroundColor", position==0?0xfff0f000:0xfff0f0f0 );
            return rv;
        }

        @Override
        public RemoteViews getLoadingView(){
            return null;
        }

        @Override
        public int getViewTypeCount(){
            return 1;
        }

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

        @Override
        public boolean hasStableIds(){
            return true;
        }
    }
}

Для комплекта приведу код AppWidgetProviderMy

public class AppWidgetProviderMy extends AppWidgetProvider{
    @Override
    public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds ){
        super.onUpdate( context, appWidgetManager, appWidgetIds );

        for (int i=0; i < appWidgetIds.length; i++){
            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget12);
            rv.setRemoteAdapter( appWidgetIds[i], R.id.stack_view, new Intent( context, RemoteViewsServiceMy.class ) );
            appWidgetManager.updateAppWidget( appWidgetIds[i], rv);
        }
    }
}

введите сюда описание изображения