I have a need from the product team to get the instance of the currently open Spinner
dropdown view and alter it or present a Showcase
above one of it's dropdown items. After going over some questions here and other articles like this one:
Android Spinner - How to make dropdown view transparent?
and this one:
How to customize the Spinner dropdown view
I'm getting the feeling that the only access I have to the dropdown is using the xml parameters or the Spinner
adapter. Yet I decided to ask the question anyway to relax my superior.
Another thing that might be helpful in my case is to get notified when the Spinner
is expended, and find the opened popup instance as a result of this notification, but following this question:
Spinner: get state or get notified when opens
It looks like this is also can't be done without extending the Spinner into a custom view, something that in my case is not possible, as I need to do it from the SDK side that I'm writing for use on a standard Spinner
.
Has any one here dealt with a Spinner
and managed to get the view instance of the dropdown or even better the view instance of one of the dropdown items? I would be grateful if you can direct me in the right direction on how this can be achieved?
UPDATE: I have managed to get the view hierarchy of the spinner dropdown using the following code:
//Function to get all available windows of the application using reflection
private void logRootViews() {
try {
Class wmgClass = Class.forName("android.view.WindowManagerGlobal");
Object wmgInstnace = wmgClass.getMethod("getInstance").invoke(null, (Object[])null);
Method getViewRootNames = wmgClass.getMethod("getViewRootNames");
Method getRootView = wmgClass.getMethod("getRootView", String.class);
String[] rootViewNames = (String[])getViewRootNames.invoke(wmgInstnace, (Object[])null);
for(String viewName : rootViewNames) {
View rootView = (View)getRootView.invoke(wmgInstnace, viewName);
Log.i(TAG, "Found root view: " + viewName + ": " + rootView);
getViewHierarchy(rootView);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//Functions to get hierarchy
private void getViewHierarchy(View view) {
//This is how I start recursion to get view hierarchy
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
dumpViewHierarchyWithProperties(group, 0);
} else {
dumpViewWithProperties(view, 0);
}
}
private void dumpViewHierarchyWithProperties(ViewGroup group, int level) {
if (!dumpViewWithProperties(group, level)) {
return;
}
final int count = group.getChildCount();
for (int i = 0; i < count; i++) {
final View view = group.getChildAt(i);
if (view instanceof ViewGroup) {
dumpViewHierarchyWithProperties((ViewGroup) view, level + 1);
} else {
dumpViewWithProperties(view, level + 1);
}
}
}
private boolean dumpViewWithProperties(View view, int level) {
//Add to view Hierarchy.
if (view instanceof TextView) {
Log.d(TAG, "TextView from hierarchy dumped: " + view.toString() + " with text: " + ((TextView) view).getText().toString() + " ,in Level: " + level);
} else {
Log.d(TAG, "View from hierarchy dumped: " + view.toString() + " ,in Level: " + level);
}
return true;
}
The problem is that to get all the decor windows of the application I need to use reflection, which is something I can't do in the SDK I'm writing, more over as I understand I use here a private API which can be changed at any moment and as I understood Google blocks applications from the store which do use a private API.
So the updated question is: Is there a way to do the same operation without reflection and private API?