Fix handling for onItemClick of fixed collection items

The onItemClick handling code assumed that the item would be nested at
least one layer deep due to the RemoteViewsAdapter adding a wrapper view
group.

Rather than add another case to that logic, I've refactored this to
traverse the view's children looking for a view with the tag. As the
tag is internal, there should only ever be one child with it and we'll
always want that one to handle the click.

Fix: 190353630
Test: locally
Test: atest RemoteViewsFixedCollectionAdapterTest
Change-Id: I22057f148d33482ad84fff592b9f7f554fa2bfad
This commit is contained in:
Stevie Kideckel
2021-06-07 14:46:52 +00:00
parent ebcaa39d6b
commit bfbe46198c

View File

@@ -114,6 +114,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -812,29 +813,8 @@ public class RemoteViews implements Parcelable, Filter {
AdapterView<?> av = (AdapterView<?>) target;
// The PendingIntent template is stored in the view's tag.
OnItemClickListener listener = (parent, view, position, id) -> {
// The view should be a frame layout
if (view instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) view;
// AdapterViews contain their children in a frame
// so we need to go one layer deeper here.
if (parent instanceof AdapterViewAnimator) {
vg = (ViewGroup) vg.getChildAt(0);
}
if (vg == null) return;
RemoteResponse response = null;
int childCount = vg.getChildCount();
for (int i = 0; i < childCount; i++) {
Object tag = vg.getChildAt(i).getTag(R.id.fillInIntent);
if (tag instanceof RemoteResponse) {
response = (RemoteResponse) tag;
break;
}
}
if (response == null) return;
response.handleViewInteraction(view, handler);
}
RemoteResponse response = findRemoteResponseTag(view);
response.handleViewInteraction(view, handler);
};
av.setOnItemClickListener(listener);
av.setTag(pendingIntentTemplate);
@@ -845,6 +825,28 @@ public class RemoteViews implements Parcelable, Filter {
}
}
@Nullable
private RemoteResponse findRemoteResponseTag(@Nullable View rootView) {
if (rootView == null) return null;
ArrayDeque<View> viewsToCheck = new ArrayDeque<>();
viewsToCheck.addLast(rootView);
while (!viewsToCheck.isEmpty()) {
View view = viewsToCheck.removeFirst();
Object tag = view.getTag(R.id.fillInIntent);
if (tag instanceof RemoteResponse) return (RemoteResponse) tag;
if (!(view instanceof ViewGroup)) continue;
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
viewsToCheck.addLast(viewGroup.getChildAt(i));
}
}
return null;
}
@Override
public int getActionTag() {
return SET_PENDING_INTENT_TEMPLATE_TAG;