'disable the scroll effect of the action list
I've got a GuidedStepSupportFragment
fragment like this.
public class SampleStepFragment extends GuidedStepSupportFragment {
@NonNull
@Override
public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
String title = "Title";
String breadcrumb = "Breadcrumb";
String description = "Description";
Drawable icon = getActivity().getDrawable(R.drawable.ic_videocam_black_24dp);
return new GuidanceStylist.Guidance(title, description, breadcrumb, icon);
}
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
addAction(actions, ACTION_CONTINUE, "Action1");
addAction(actions, ACTION_BACK, "Action2");
}
}
Problem: When I scroll the action list, it shows like this;
But I want to something like this;
How can I disable this effect on my action list?
Thanks
Solution 1:[1]
I managed it and it wasn't easy to figure out.
There's no supported way of doing it, since the APIs that actually make this possible are package private or hidden from public use on purpose. (You can do it yourself, but you just end up copying classes from the leanback libraries.)
The solution:
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
addAction(actions, GuidedAction.ACTION_ID_CONTINUE, "Action1");
addAction(actions, GuidedAction.ACTION_ID_CANCEL, "Action2");
// Run code delayed on mainThread (any other/better method can/should be used)
// It's delayed because if focus scroll is disabled, the list will stick to the top of the layout
new Handler(Looper.getMainLooper()).postDelayed(this::disableFocusScroll, 500);
}
private void disableFocusScroll() {
RecyclerView.LayoutManager layoutManager = SampleStepFragment.this.getGuidedActionsStylist().getActionsGridView().getLayoutManager();
try {
Method method = layoutManager.getClass().getMethod("setFocusScrollStrategy", int.class);
method.invoke(layoutManager, 1 /* FOCUS_SCROLL_ITEM */);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.e(TAG, "disableFocusScroll: ", e);
}
}
The explanation:
A GuidedStepSupportFragment
requests a GuidedActionsStylist
which is responsible for rendering the list items on the right side. source
The GuidedActionsStylist
stylist inflates the layout lb_guidedactions.xml
which contains a VerticalGridView
source
The VerticalGridView
extends BaseGridView
and creates a GridLayoutManager
as its layout manager. This GridLayoutManager
is sadly package private and final... (android why..?). It has the method setFocusScrollStrategy
which is used to determine how scrolling behaves.source
See the different focus scroll strategies:
/**
* Always keep focused item at a aligned position. Developer can use
* WINDOW_ALIGN_XXX and ITEM_ALIGN_XXX to define how focused item is aligned.
* In this mode, the last focused position will be remembered and restored when focus
* is back to the view.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final static int FOCUS_SCROLL_ALIGNED = 0;
/**
* Scroll to make the focused item inside client area.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final static int FOCUS_SCROLL_ITEM = 1;
/**
* Scroll a page of items when focusing to item outside the client area.
* The page size matches the client area size of RecyclerView.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final static int FOCUS_SCROLL_PAGE = 2;
So since the API is hidden, we just use reflection to expose the setFocusScrollStrategy
method and set it to FOCUS_SCROLL_ITEM
.
We can't do this immediately though, since without the default scroll setting, the list items will pop to the top of the layout and won't stay centered. So I added a delay of 500ms which is horrible... If you manage to find out when it's best to trigger this, let me know.
Solution 2:[2]
It turns out there is a much more elegant and simpler solution. It is enough to add to the body of onViewCreated
in the class that inherits guideStepSupportFragment
windowAlignment option (there are other alignment options):
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// ...
val gridView = guidedActionsStylist.actionsGridView
gridView.windowAlignment = VerticalGridView.WINDOW_ALIGN_BOTH_EDGE
// ...
super.onViewCreated(view, savedInstanceState)
}
Solution 3:[3]
Here is a simple way to disable VerticalGridView scrolling
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
VerticalGridView gridView = getGuidedActionsStylist().getActionsGridView();
gridView.setScrollEnabled(false);
super.onViewCreated(view, savedInstanceState);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | XJIOP |