I have a FrameLayout (teaserContainer) and BottomSheet (invitesContainer). The FrameLayout is outside (and above) the BottomSheet. I want the FrameLayout shrink and follow the BottomSheet, so the FremeLayout collapses as the BottomSheet expands.
What happens now is that the FrameLayout occupies the whole page because of its android:layout_height="match_parent" but if I set it to android:layout_height="wrap_content" it shows behind the BottomSheet and vertically centred like a FAB would.
I want that when the BottomSheet (invitesContainer) is fully expanded the FrameLayout (teaserContainer) should occupy the rest of the screen up to the toolbar.
All examples of anchoring views to the BottomSheet involve a FAB, so not any help to me here.
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".social.friends.FriendsListFragment">
<FrameLayout
android:id="#+id/teaserContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:fitsSystemWindows="true"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
app:layout_anchor="#+id/invitesContainer"
app:layout_anchorGravity="top">
<com.myapp.android.common.social.friends.views.FriendsTeaser
android:id="#+id/teaser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
app:friendsTeaserState="EMPTY" />
</FrameLayout>
<LinearLayout
android:id="#+id/invitesContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:alpha="0.1"
android:background="#color/body" />
<com.myapp.android.common.social.friends.views.FriendsConnectItem
android:id="#+id/connectFacebook"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:friendsConnectType="facebook" />
<com.myapp.android.common.social.friends.views.FriendsConnectItem
android:id="#+id/connectContacts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:friendsConnectType="contacts" />
<com.myapp.android.common.social.friends.views.FriendsConnectItem
android:id="#+id/share"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:friendsConnectType="invite" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
--------------------------------------------------------------------------------------------------------------
Solution:
This is a Kotlin version of Vadim's suggestion
BottomSheetBehavior.from(invitesContainer).setBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
val currentHeight = teaserContainer.height - bottomSheet.height
val bottomSheetShiftDown = currentHeight - bottomSheet.top
teaserContainer.setPadding(
0,
0,
0,
(bottomSheet.height + bottomSheetShiftDown)
)
}
})
My example is like:
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
int currentHeight = teaserContainer.getHeight() - bottomSheet.getHeight();
int bottomSheetShiftDown = currentHeight - bottomSheet.getTop();
rootContainer.setPadding(
0,
0,
0,
(mBottomSheet.getPeekHeight() + bottomSheetShiftDown));
}
and the mBottomSheet - BottomSheetBehavior mBottomSheet = BottomSheetBehavior.from(invitesContainer);
So this will add/remove padding of yours teaserContainer when you pull it down.
Related
I am trying to implement a layout like this:
The issue is that when scrolling up the card touches the toolbar and it does not go up anymore like this:
I want it to scroll up till the viewpager to fills the screen ie, at least the rectangle card, should scroll up beyond the toolbar(Even the tabLayout can also scroll up). But I don't want it to stay sticky at the top.
The main layout is here:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="#layout/activity_main">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/toolbarCollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:src="#drawable/ic_launcher_foreground"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:behavior_overlapTop="90dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="#+id/lin"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/debit_card_item" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_marginTop="40dp"
android:background="?attr/colorPrimary" />
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The fragments of the pager are inside a NestedScrollView like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rcView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
Things that I tried:
I have tried to remove the NestedScrollView above the linear layout and added the app:behavior_overlapTop="90dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior" to the linear layout. but it's still giving me the same output.
Set the height of the view pager statically(gave the same result).
-->>>EDIT<<<
3. I thought of a workaround and I am trying to add custom behavior to my LinearLayout in my mainActivity. so as to reduce the margin-bottom and height of the rectangular card. It is giving good results when I fling and close the collapsing toolbar. But when I hold down and scroll, the screen is flickering as shown below:
My Custom behavior is
class CustomHeaderBehavior : AppBarLayout.ScrollingViewBehavior {
private var mContext: Context
var height = 0
var width = 0
var marginBottom = 0
var firstTime = true
constructor(
context: Context,
attrs: AttributeSet?
) : super(context, attrs) {
mContext = context
}
constructor(
context: Context?,
attrs: AttributeSet?,
mContext: Context
) : super(context, attrs) {
this.mContext = mContext
}
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: View,
dependency: View
): Boolean {
return super.layoutDependsOn(parent, child, dependency)
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
childP: View,
dependency: View
): Boolean {
val child = childP.findViewById<RelativeLayout>(R.id.cardParent)
val maxScroll: Int = (dependency as AppBarLayout).totalScrollRange
val percentage =
abs(dependency.y) / maxScroll.toFloat()
Log.d("Behavx","D.y "+abs(dependency.y)+ " m s "+maxScroll+ " p "+percentage)
val lp: LinearLayout.LayoutParams =
child.layoutParams as LinearLayout.LayoutParams
if(firstTime){
height = child.height
width = child.width
marginBottom = lp.bottomMargin
firstTime = false
}
Log.d("Behaviour", "P "+ ((1-(percentage))*100).toString() +" H " +height+ " U H " +(height*(((1-(percentage))*100))/100) )
// lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100) - ((height*((((percentage))*100))/100))).toInt()
lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100)).toInt() //updating margin bottom
lp.height = ((height*(((1-(percentage))*100))/100)).toInt() //updating height
child.layoutParams = lp
child.alpha = 1 - (percentage * 4)
return super.onDependentViewChanged(parent, childP, dependency)
}
companion object {
fun getToolbarHeight(context: Context): Int {
var result = 0
val tv = TypedValue()
if (context.theme.resolveAttribute(R.attr.actionBarSize, tv, true)) {
result = TypedValue.complexToDimensionPixelSize(
tv.data,
context.resources.displayMetrics
)
}
return result
}
}
}
The flicker seems to be happening because the dependency.y is becoming wrong randomly, while I hold down and scroll and update the height of the card(if I only update the margin flicker is not occurring). For some reason controlling the width is happening smoothly. But unfortunately, that's not helping me here.
I also tried to do something similar by adding an offsetChangedListener to the app bar like this:
appBar.addOnOffsetChangedListener(OnOffsetChangedListener { appBarLayout, verticalOffset ->
if (abs(verticalOffset) == appBarLayout.totalScrollRange) {
// Collapsed
cardParent.visibility = View.GONE
} else {
//Expanded
cardParent.visibility = View.VISIBLE
}
})
But I am still getting the flicker
I have added the sample project here:
github link
The custom behavior is pushed to a new branch custom_behaviour
Finally Solved my issue. I added the card inside the collapsing layout like Kalyans answer and added a dummy view and a -ve margin to the card to have the overlap behavior effect like
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/toolbarCollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#000" />
<include
layout="#layout/debit_card_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-90dp"
app:layout_collapseMode="parallax" />
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
I have also pushed my code to the github.
In order to achieve that effect, the card layout should be inside the collapsing toolbar.
Try replacing this:
<ImageView
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:src="#drawable/ic_launcher_foreground"
app:layout_collapseMode="parallax" />
with:
<include layout="#layout/debit_card_item"
android:layout_width="match_parent"
android:layout_height="190dp"
android:minHeight="190dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="72dp"
app:layout_collapseMode="parallax"/>
and remove <include layout="#layout/debit_card_item" /> in the NestedScrollView.
Hope this helps.
I'm trying to make the BottomSheetDialogFragment appear at the top of BottomNavigationView and below the BottomNavigationView, ie with a lower elevation.
The BottomSheetDialogFragment will feature a YouTube-like video player with a RecyclerView and expanding and collapsing the bottomsheet.
I already researched several suggestions and nothing solved. Including Stackoverflow.
I tried the two variants of the Show () method, as per the code below - but none worked.
I can do Expand, Collapsed and other actions, do not worry about it. The problem is to make the BottomSheet behind the BottomNavigationView and above the RecyclerView of the Activity.
CODE ACTIVITY
public class myController extends CommonActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//inflate the layout of the activity
setContentView(R.layout.controller_layout);
//other activity codes
//progressBar = findViewById(R.id.progressBar);
//contains initialization codes for views and recyclerview
//initViews();
}
OPTION 01: It's the CALL that everyone is pointing to BottomSheetDilogFragment, except BottomSheet is over BottomNavigationView
INITIALIZED when clicking on a item (thumbnail) of a RecyclerView in the layout of the activity/fragment
public void initBottomSheet(Bundle b){
VideoViewBottomSheet fragment = new VideoViewBottomSheet();
fragment.setArguments( b );
fragment.show( getSupportFragmentManager(), VideoViewBottomSheet.FRAGMENT_KEY );}
OPTION 02: I tried this option for BottomSheetDilogFragment, in it the BottomSheet is
DOWN of the BottomNavigationView, BUT behave like a NORMAL FRAGMENT and not as BottomSheetDilogFragment, DO NOT EXPAND, DO NOT COLLAPSE, NOTHING.
public void initBottomSheet(Bundle b){
VideoViewBottomSheet fragment = new VideoViewBottomSheet();
fragment.setArguments( b );
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.bottom_sheet_loyout, fragment);
ft.commit();
}
}
CODE BottomSheetFragment
#Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
View view = getView();
final View parent = (View) view.getParent();
final View bottomSheet = dialog.findViewById(R.id.rv_bottom_sheet);
final View videoView = bottomSheet.findViewById(R.id.videoView);
final View bottom_nav_view = getActivity().findViewById(R.id.bottom_nav_view);
final int screenHeight = ViewGroup.LayoutParams.MATCH_PARENT;
final View relativeLayout = getActivity().getWindow().getDecorView().getRootView().findViewById(R.id.relativelayout);
final View coodinatorLayout = getActivity().getWindow().getDecorView().getRootView().findViewById(R.id.coordinatorlayout);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
parent.setFitsSystemWindows(false);
bottomSheet.getLayoutParams().height = screenHeight;
params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
final BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
if (bottomSheetBehavior instanceof BottomSheetBehavior) {
offsetY = 0;
((BottomSheetBehavior) bottomSheetBehavior).setBottomSheetCallback(
new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
if(slideOffset>0.2 ){
bottomSheetBehavior.setHideable(false);
bottomSheetBehavior.setPeekHeight(bottom_nav_view.getHeight()+56 );
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
parent.setPadding(0,0,0,bottom_nav_view.getHeight()+56);
parent.setBackgroundColor(Color.GREEN);
bottom_nav_view.setVisibility(View.VISIBLE);
bottom_nav_view.setBackgroundColor(Color.YELLOW);
}
offsetY = slideOffset;
}
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
}
});
}
}
}
The expected result is a BottoSheet similar to that of the Youtube Player. That is, a BottomSheet that contains a Fragment RecyclerView and Play Videos.
XMLS
mycontroller_layout.xml
-----------------------
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relativelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:fitsSystemWindows="false"
tools:context=".myController">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinatorlayout"
android:layout_above="#+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:fitsSystemWindows="false">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone" />
<include layout="#layout/content" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/bottomsheet"/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_nav_view"
android:layout_below="#+id/coordinatorlayout"
android:layout_width="match_parent"
android:layout_height="56dp"
android:elevation="50dp"
android:visibility="visible"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
app:itemIconTint="#color/colorWhite"
android:background="#color/colorPrimary"
app:menu="#menu/activity_main_bottom" />
</RelativeLayout>
content.xml
-----------
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingTop="4dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".RebootController"
tools:showIn="#layout/reboot_controller_layout">
<RelativeLayout
android:id="#+id/containerContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</RelativeLayout>
</RelativeLayout>
bottom_sheet_loyout.xml
-------------------
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/rv_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom_nav_view"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:elevation="3dp"
android:fitsSystemWindows="false"
android:orientation="vertical"
app:layout_behavior="#string/bottom_sheet_behavior" >
<RelativeLayout
android:id="#+id/rlVideoView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<VideoView
android:id="#+id/videoView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/srl_swipe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/videoView">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:clipToPadding="false"
android:paddingBottom="56dp"/>
</android.support.v4.widget.SwipeRefreshLayout>
<ProgressBar
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:visibility="gone" />
<!--<LinearLayout
anĂșncio google
</LinearLayout>-->
</RelativeLayout>
</RelativeLayout>
I have a group horizontal RecycleViews inside a SwipeRefreshLayout and I am having trouble with swiping the Recycleviews on the start of the page as it keeps stopping it and detecting a refresh swipe.
How to stop this from happening?
Or is there a way to trigger refresh only if not swiping?
Also, is this the best way to implement my desired layout?
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/activity_main_swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="70dp"
android:isScrollContainer="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/block_border"
android:orientation="vertical">
<TextView
android:id="#+id/trending_episodes_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--This is the first affected recycle -->
<android.support.v7.widget.RecyclerView
android:id="#+id/trendingEpisodesRecycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal" />
</LinearLayout>
<!--This is the Second affected recycle -->
<android.support.v7.widget.RecyclerView
android:id="#+id/allNewsRecycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/title_top"
android:clipToPadding="false"
android:orientation="horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/block_border"
android:orientation="vertical">
<TextView
android:id="#+id/moods_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/title_top"
android:textColor="#color/colorBlack"
android:textSize="20sp"
android:textStyle="bold" />
<android.support.v7.widget.RecyclerView
android:id="#+id/moodsRecycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="horizontal" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
Ok so I solved this problem by disabling the SwipeRefreshLayout when the RecycleView is being touched, and re-enabling it again once the user let go of the RecycleView.
Bellow are the code for that from my program:
MyRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(final RecyclerView recyclerView, int newState)
{
super.onScrollStateChanged(recyclerView,newState);
if (newState != RecyclerView.SCROLL_STATE_IDLE) { // on scroll stop
mSwipeRefreshLayout.setEnabled(false);
}
else
{
mSwipeRefreshLayout.setEnabled(true);
}
}
}
Zaid answer works fine. But in my case I had horizontal recycle views inside adapter, so for me it would be hard to connect adapter with activity recycler.
Easier approach is to create custom VerticalRefreshLayout and use it instead of SwipeRefreshLayout.
Kotlin solution:
class VerticalRefreshLayout(context: Context?, attrs: AttributeSet?) : SwipeRefreshLayout(context!!, attrs) {
private val mTouchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
private var mPrevX = 0f
#SuppressLint("Recycle")
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> mPrevX = MotionEvent.obtain(event).x
MotionEvent.ACTION_MOVE -> {
val eventX = event.x
val xDiff = abs(eventX - mPrevX)
if (xDiff > mTouchSlop) {
return false
}
}
}
return super.onInterceptTouchEvent(event)
}
I used Nestedscrollview as Bottomsheetbehaviour but when it changes its state from normal to expanded some of space from toolbar left but when second time state changed from normal to expanded it works fine..
It looks as it leaves space exactly twice of the margin I provide to the sheet in xml. My code looks like this...
MyLayoutFile.xml
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
tools:context=".fragments.StoreLocationDetailsFragment">
<include layout="#layout/toolbar"/>
<FrameLayout
android:id="#+id/mapHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"/>
<include android:id="#+id/nested_scroll_view"
layout="#layout/store_details_scroll_view"/>
</android.support.design.widget.CoordinatorLayout>
store_details_scroll_view.xml
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
android:background="#color/colorLightGrey"
android:clipToPadding="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingTop="#dimen/activity_horizontal_margin">
<TextView
android:id="#+id/tvStoreName"
style="#style/styleOswaldBold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:text="Adidas Shoes"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Title"/>
<TextView
android:id="#+id/tvAddress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sub_title"
android:textAlignment="center"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:background="#color/colorDarkGrey"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
and code in onClick Function in java file looks like
View bottomSheet = rootLayout.findViewById(R.id.nested_scroll_view);
behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setPeekHeight(new ScreenDimensions(getActivity())
.getHeightWithGivenPercentage(60));
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_DRAGGING:
break;
case BottomSheetBehavior.STATE_COLLAPSED:
behavior.setPeekHeight(0);
break;
case BottomSheetBehavior.STATE_EXPANDED:
break;
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
Here rootlayout is my Coordinator layout. Can anyone suggest me solution of the above problem. Thanks in advance.
I have a FrameLayout at top
and ViewPager at bottom
FrameLayout has PagerTabStrips
ViewPager has ScrollView in it.
What I am trying to achieve is that on the scroll of ViewPager's ScrollView, I want to translate Y position of ViewPager and FrameLayout together in sync smoothly.
And at some point I have to fix the position of FrameLayout and stop its further scrolling to top.
Below is my xml code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:id="#+id/parentRelativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:clickable="true"
android:clipToPadding="false"
android:fitsSystemWindows="true" >
<FrameLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.sticky.pager.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dip"
android:layout_gravity="bottom"
android:layout_marginTop="2dp" />
</FrameLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/header"
android:background="#color/blue" />
</RelativeLayout>
How can I achieve this programmatically:
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount, int pagePosition) {
float scrollY=getScrollY(view);
mViewPager.setTranslationY(-scrollY);
mHeader.setTranslationY(-scrollY);
//What to write here??? This does not work
You should change the top and bottom of that view instead of moving it. You can synchronize the scroll via the scroll offset
override fun onScrollChange(v: NestedScrollView?, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) {
view.bottom = valueBottomTranslate.toInt()
view.top = valueTopTranslate.toInt()
}