Android AppWidget Listview change selected imagebutton onClick - android

I've this homescreen widget:
It's easy to update for example two buttons next to the logo from activity, because I have their appWidgetIds from onUpdate method from AppWidgetProvider, but imagebuttons in the list are created in RemoteViewsFactory class in getViewAt() method.
#Override
public RemoteViews getViewAt(int position) {
RemoteViews row = new RemoteViews(ctxt.getPackageName(), R.layout.list_row_widget);
row.setTextViewText(R.id.tvDescription, items.get(position).name);
Intent i = new Intent();
Bundle extras = new Bundle();
extras.putBoolean(TimeWidgetProvider.ACTION_WORK_START, true);
extras.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
i.putExtras(extras);
row.setOnClickFillInIntent(R.id.btnStartWork, i);
return (row);
}
so every of them have same id (R.id.btnStartWork), and same appWidgetId which is not the row id but the whole widget id.
I need to change imagebutton in the row which I have clicked on, but because I've only one appwidget id in Activity and its for whole widget, everytime I use:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getBaseContext());
RemoteViews views = new RemoteViews(getBaseContext().getPackageName(), R.layout.widget_layout);
views.setImageViewResource(R.id.btnStartWork, R.drawable.button_active);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
It changes the first imagebutton not the selected one.
I have tried to pass remoteviews row from factory, but it didn't work because when I called
appWidgetManager.updateAppWidget(mAppWidgetId, row);
with the id of whole widget, widget was gone and only the selected row was visible. I can get the position of item in list, but it's not helpful because it's not a viewId.
I have read many tutorial including this: http://developer.android.com/guide/topics/appwidgets/index.html
But still haven't found the answer, It's my first widget. Help please.
Thanks ;)

Actually the solution was quite simple, in getViewAt() method save the position of every imagebutton to extras:
extras.putInt(TimeWidgetProvider.POSITION, position);
then in handling method store somewhere the index of selected item
TimeWidgetProvider.selected = extras.getInt(TimeWidgetProvider.POSITION);
and after that, use this:
appWidgetManager.notifyAppWidgetViewDataChanged(mAppWidgetId, R.id.list);
at last again in the getViewAt() method change imagebutton on index which you have previously stored.
if (position == TimeWidgetProvider.selected) {
row.setImageViewResource(R.id.btnStartWork, R.drawable.button_active);
} else {
row.setImageViewResource(R.id.btnStartWork, R.drawable.button_inactive);
}
The whole list is refreshed with changed states of selected items.
Thx Tamás Müller for this solution.

Related

Android Widgets Listview Button Clicked

i have a listview in my widget that have a button in each row .
i want to visible a view when button clicked .
how i can found which row s button is clicked ?
#Override
public RemoteViews getViewAt(int i) {
// Log.d("MyWidgetViewsFactory", "getViewAt(" + position + "):" + items.get(position));
// Item item = items.get(i);
RemoteViews itemView = new RemoteViews(context.getPackageName(), R.layout.widget_listview_item);
if(wordItems != null) {
itemView.setTextViewText(R.id.ques, wordItems.get(i).getWord());
itemView.setTextViewText(R.id.answer, wordItems.get(i).getMean());
Log.d("word item size", wordItems.size() + " -- ");
itemView.setViewVisibility(i , View.VISIBLE);
// -- how can find which rows is clicked and how visible a layout
Intent intent = new Intent();
itemView.setOnClickFillInIntent(R.id.seeasnwer, intent);
}
return itemView;
}
Updated :
as you see in screen shot i want when i clicked "show answer" button a view set visible
Through ViewHolder concept, we can achieve it..
or
Provide the position for button by using setTag method. Whenever click the button, get the position of that button by using getTag method and play with item what ever you want.

How to add images dynamically to ViewFlipper which is under RemoteView

I have a requirement to load a list of images into RemoteView's. For that purpose I am using ViewFlipper to show when the user clicks next and previous buttons. But the problem I am facing with ViewFlipper is that I couldn't able to add the images dynamically, whereas I am getting output once if I load the images from drawables locally inside the ViewFlipper. Kindly please help. I couldn't able to find the solution for this with RemoteViews. I am posting my code for your reference as follows:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RemoteViews expandedView = new RemoteViews(this.getPackageName(), R.layout.notification_viewflipper);
expandedView.setOnClickPendingIntent(R.id.img_left,getPendingSelfIntent(MainActivity.this, IMAGE_LEFT));
expandedView.setOnClickPendingIntent(R.id.img_right,getPendingSelfIntent(MainActivity.this, IMAGE_RIGHT));
}
protected PendingIntent getPendingSelfIntent(Context context, String action) {
Intent intent = new Intent(context,MyNotificationReceiver.class);
intent.setAction(action);
return PendingIntent.getBroadcast(context, 0, intent, 0);
}
Any sort of tips and hints will be much helpful for me. Thanks in advance.
Just stumbled uppon this question and seeing nobody has answered... This is my code to add childs to viewFlipper inside a remoteview:
RemoteViews carrouselItem = new RemoteViews(getPackageName(), R.layout.item_carrousel_notification);
contentView1.setImageViewResource(R.id.product_image, R.drawable.ic_launcher);
contentView1.setTextViewText(R.id.notification_title, "First Product");
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.carrousel_notification);
contentView.addView(R.id.notification_view_flipper, carrouselItem);
Replace R.drawable.ic_launcher with the image you want to add to the viewflipper (get it from url or from other sources). Guess that should work. My problem is using the viewflipper in the expanded notification =/

RemoteViewsFactory called getViewAt when empty dataset

I'm working on widget for my application which based on StackView and should display some items. Count of items can vary due to user actions - lets say it is some kind of favorites menu. I have implemented RemoteViewsFactory descendant to generate views for StackView:
public class StackRemoteViewsFactory implements RemoteViewsFactory {
private List<Item> data;
private Context context;
public StackRemoteViewsFactory(Context context) {
this.context = context;
data = new DAO(context).getFavouriteCards();
}
#Override
public void onDataSetChanged() {
data = new DAO(context).getWidgetItems(); // refresh widget dataset
}
#Override
public int getCount() {
return data.size();
}
#Override
public RemoteViews getViewAt(int position) {
Item item = data.get(position);
// this is my problem and will be explained below -
// here I'm getting IndexOutOfBoundsException, position = 0
...
}
// I have omitted other methods to avoid verbosity
}
All works well at first widget start - widget successfully displays empty view and all goes well. After I added some new element to favourites I notify AppWidgetManager immediately:
AppWidgetManager widgetManager = AppWidgetManager.getInstance(getActivity());
ComponentName component = new ComponentName(getActivity(), MyWidgetProvider.class);
int[] widgetIds = widgetManager.getAppWidgetIds(component);
widgetManager.notifyAppWidgetViewDataChanged(widgetIds, R.id.widgets_stack);
All is well at this point - dataset successfully changed and I see my favorite item on widget. But when I remove my single element from favorites and favorites become empty (AppWidgetManager notified of course) I receive IndexOutOfBoundsException in my getViewAtMethod:
10-15 17:26:36.810: E/AndroidRuntime(30964): java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
First of all I've checked what getCount() returns after onDataSetChanged() fires - it was 0. So I don't understand why RemoteViewsFactory calls getViewAt() when getCount() returns 0. As far as I understanding, RemoteViewFactory is like a usual adapter so this behavior is completely confusing me. So maybe my suggestions about it are incorrect and I doing something wrong?
UPDATE
Today I've changed my widget layout to use ListView instead of StackView while trying to fix some gui bug. And all works well at now. Further experiment shows that AdapterViewFlipper have same issue as StackView. As far as I understood there are some aspects working with AdapterViewAnimator descendants - can anyone confirm/refute my assumption?
Same problem here. Since the solution is not yet coming (Android 4.4 here and it still happens), I think the best solution for now is basically a workaround to avoid the crash. Some devs will call it "hack"...
For now:
public RemoteViews getViewAt(int position) {
if (position >= getCount())
return getLoadingView();
}
//.... Rest of your normal configuration
}
Make sure you return a view properly on getLoadingView()

Android ListView getViewAt

I'm trying to get click event on my ListView on homesreen widget.
For this I'm using following code:
public class ViewFactory implements RemoteViewsService.RemoteViewsFactory {
...
#Override
public RemoteViews getViewAt(int position) {
RemoteViews row=new RemoteViews(ctxt.getPackageName(),
R.layout.row);
Log.i("position receive trans", Integer.toString(position));
row.setTextViewText(android.R.id.text1, items[position]);
Intent i = new Intent(this.ctxt, AppWidget.class);
i.setAction(ACTION_WIDGET_UPDATE_POSITION);
i.putExtra("position", position);
row.setOnClickFillInIntent(android.R.id.text1, i);
return(row);
}
But I'm getting this event not only after clicking on widget. I'm getting this also after adding widget to the home screen.
Is there any way to determine different actions (Click and adding to homescreen?)
Such situation can be determined by
intent.getAction();
For enabling widget is : android.appwidget.action.APPWIDGET_ENABLED
For updatewidget is : android.appwidget.action.APPWIDGET_UPDATE

How to show textviews in widget and display a next button?

I have a list of items i retrieve from html.
They are all titles.
What i am doing is testing each title for a specific thing..
If it has it i want to add it to a TextView in a widget.
The only problem is that if they are more than 1 item the widget wont hold all of the items.
and listview layout isnt supported in widgets older than 3.0.
SO how can i add each item to its on TextView and then display each item using a next button to show the next textview?
EDIT:
Okay that SOunds like it makes sense.
SO here how i retrieve my titles...
What would you recommend as far as setting them to a ArrayList and showing the next item in the list when the textview is clicked?
while(doc == null && retry < 5){
retry++;
try {
doc = Jsoup.connect(site).get();
} catch (IOException e) {
Log.e("Html", "JSoup get retrieved no document", e);
}
}
if(doc != null){
title = doc.select("tr> td.indexList1, tr > td.indexList2");
if(title != null){
// Iterator over those elements
ListIterator<Element> postIt = title.listIterator();
//Loads all the items until there is no .hasNExt()
while (postIt.hasNext()) {
// Add the game text to the ArrayList
Element name = postIt.next();
nameString = name.text();
list.add(new Release(nameString));
So how would i use this to set a textview initially, and then( with the code you suggested) allow the next item in the list to be loaded into a text view?
Keep titles in a list (java list, like ArrayList for example) and have only 1 textview defined in your layout.
In your manifest add a new intent filter to your widgetprovider (reciever) for example:
<intent-filter>
<action android:name="WIDGET_NEXT_TITLE" />
</intent-filter>
And in your widget provider class add an onClickPendingIntent to your textview:
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
final Intent nextTitleIntent = new Intent("WIDGET_NEXT_TITLE");
nextTitleIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, nextTitleIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.textview_id, pendingIntent);
You can do it in your onUpdate method for example.
Now on every click and intent will be fired and all you need is to catch it and set the next title in a textview. In your widgetprovider override method onRecieve like this:
if ("WIDGET_NEXT_TITLE".equals(intent.getAction())) {
final int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
// get the next title here and set the text in a textview through RemoteView
}
} else {
super.onReceive(context, intent);
}
Something like that. Of course it's very simplified, since you need to keep the track of the currently displayed title, but I hope you get the idea.

Categories

Resources