I wanna do something like a sticky menu, but I do not have any clue about this. My XML is something like this:
<com.example.customscrollview.scrollview
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- I need sticky this element bellow! -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="210.0dip"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="210.0dip">
<!-- A lot of TextViews -->
<TextView...>
<TextView...>
<TextView...>
</LinearLayout>
</FrameLayout>
</com.example.customscrollview.scrollview>
I tried do it programmatically:
private void setTouchListeners() {
setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
boolean rt = false;
if (event.getAction() == MotionEvent.ACTION_MOVE) {
final View element = (View) findViewById(R.id.element);
LayoutParams params = new LayoutParams(
LayoutParams.MATCH_PARENT,
element.getHeight()
);
params.setMargins(0, (int) getScrollY(), 0, 0);
params.gravity = Gravity.TOP;
element.setLayoutParams(params);
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
childElement.requestLayout();
}
});
}
return rt;
}
});
}
It works but isn't perfect. When the ScrollView begin fling, the movement isn't completed, because the MotionEvent only hook the touch events. So I overwrite the onScrollChanged to do the same function (with some changes). Good, now the element stays in the top, but it do not follow the scroll movement, it becomes "unstable" until the scroll stops (result of the fling and fast scroll velocity).
What is the better way to do it?
You can get there most easily by changing the nesting. If you make the FrameLayout the root element, you can float the overlay on top of the ScrollView. The price that you pay is that it appears in the layout twice. If it's not too many views, that's probably worth paying.
You need programmatic control to change the visibility of the sticky navigation once the the scrolling navigation hits the top of the view. You don't need programmatic control to keep the sticky navigation in place.
<!-- FrameLayout simply positions all its children at the requested height, width,
gravity and margins. It doesn't try to avoid child views overlapping each
other. The items are rendered in top-to-bottom XML order. -->
<FrameLayout layout_width="match_parent"
layout_height="match_parent">
<!-- The scrollable main content. -->
<ScrollView layout_width="match_parent"
layout_height="match_parent">
<LinearLayout layout_width="match_parent"
layout_height="wrap_content"
orientation="vertical">
<!-- The scrolling version of the navigation section -->
<LinearLayout layout_width="match_parent"
layout_height="wrap_content"
orientation="horizontal">
<!-- menu items go here -->
</LinearLayout>
<!-- content views go here. Note: if you're doing data binding to
populate this, consider RecyclerView instead of ScrollView. -->
<TextView />
<TextView />
</LinearLayout>
</ScrollView>
<!-- This is a copy of the navigation section. -->
<LinearLayout layout_width="match_parent"
layout_height="wrap_content"
layout_gravity="top"
visibility="invisible"
orientation="horizontal">
<!-- menu items go here -->
</LinearLayout>
</FrameLayout>
(I've left out the android: prefixes for the example. You do need them.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With