gpt4 book ai didi

android - FAB 结合 NestedScrollView

转载 作者:行者123 更新时间:2023-11-29 01:10:12 26 4
gpt4 key购买 nike

我有一个“细节” fragment ,它有很多 TextView 、相对布局等。它们被包裹在 NestedScrollView 中:

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:orientation="vertical"
android:paddingBottom="10dp">

<android.support.v4.widget.NestedScrollView
android:id="@+id/movie_details_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent">

// Here are the textviews, relativelayouts etc...
</android.support.v4.widget.NestedScrollView>

<android.support.design.widget.FloatingActionButton
android:id="@+id/edit_movies_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_edit_white_24dp"
/>
</android.support.design.widget.CoordinatorLayout>

现在我想在屏幕底部添加一个 FAB(不在 nestedscrollview 的底部),当我滚动浏览 nestedscrollview 时它也会向下滚动。但是在我的代码中,FAB 始终位于嵌套 ScrollView 的底部。所以当我一直向下滚动时,FAB 出现了。我希望 FAB 在右下角始终可见...

编辑

我忘了说我使用了渐变操作栏 ( https://github.com/ManuelPeinado/FadingActionBar ) 但有点编辑。

相关代码:

m_FadingActionBarHelper.createView(getContext()); // this will create the view with header content etc.

创建 View :

public final View createView(LayoutInflater inflater) {
//
// Prepare everything

mInflater = inflater;
if (mContentView == null) {
mContentView = inflater.inflate(mContentLayoutResId, null); // this will load my view which i already posted.
}
if (mHeaderView == null) {
mHeaderView = inflater.inflate(mHeaderLayoutResId, null, false);
}

// See if we are in a ListView, WebView or ScrollView scenario

ListView listView = (ListView) mContentView.findViewById(android.R.id.list);
View root;
if (listView != null) {
root = createListView(listView);
} else if (mContentView instanceof CDMObservableWebViewWithHeader){
root = createWebView();
} else {
root = createScrollView(); // this will be called in my example
}

if (mHeaderOverlayView == null && mHeaderOverlayLayoutResId != 0) {
mHeaderOverlayView = inflater.inflate(mHeaderOverlayLayoutResId, mMarginView, false);
}
if (mHeaderOverlayView != null) {
mMarginView.addView(mHeaderOverlayView);
}

// Use measured height here as an estimate of the header height, later on after the layout is complete
// we'll use the actual height
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
mHeaderView.measure(widthMeasureSpec, heightMeasureSpec);
updateHeaderHeight(mHeaderView.getMeasuredHeight());

root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int headerHeight = mHeaderContainer.getHeight();
if ((!mFirstGlobalLayoutPerformed || (headerHeight != mLastHeaderHeight)) && headerHeight != 0) {
updateHeaderHeight(headerHeight);
mFirstGlobalLayoutPerformed = true;
}
}
});
return root;
}

创建 ScrollView :

private View createScrollView() {
ViewGroup scrollViewContainer = (ViewGroup) mInflater.inflate(R.layout.fab__scrollview_container, null);

CDMObservableScrollView scrollView = (CDMObservableScrollView) scrollViewContainer.findViewById(R.id.fab__scroll_view);
scrollView.setOnScrollChangedCallback(mOnScrollChangedListener);

ViewGroup contentContainer = (ViewGroup) scrollViewContainer.findViewById(R.id.fab__container);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mContentView.setLayoutParams(layoutParams);
contentContainer.addView(mContentView);
mHeaderContainer = (FrameLayout) scrollViewContainer.findViewById(R.id.fab__header_container);
initializeGradient(mHeaderContainer);
mHeaderContainer.addView(mHeaderView, 0);
mMarginView = (FrameLayout) contentContainer.findViewById(R.id.fab__content_top_margin);

return scrollViewContainer;
}

将要加载的 xml:

<denis.de.meperdia.fadingactionbar.CDMRootLayout
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">

<include layout="@layout/fab__header_container"/>

<denis.de.meperdia.fadingactionbar.CDMObservableScrollView
android:id="@+id/fab__scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:id="@+id/fab__container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<FrameLayout
android:id="@+id/fab__content_top_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"/>
</LinearLayout>
</denis.de.meperdia.fadingactionbar.CDMObservableScrollView>

</denis.de.meperdia.fadingactionbar.CDMRootLayout>

CDMRootLayout 类:

public class CDMRootLayout extends CoordinatorLayout {

private View mHeaderContainer;
private View mListViewBackground;
private boolean mInitialized = false;

public CDMRootLayout(Context context) {
super(context);
}

public CDMRootLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CDMRootLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//at first find headerViewContainer and listViewBackground
if(mHeaderContainer == null)
mHeaderContainer = findViewById(R.id.fab__header_container);
if(mListViewBackground == null)
mListViewBackground = findViewById(R.id.fab__listview_background);

//if there's no headerViewContainer then fallback to standard FrameLayout
if(mHeaderContainer == null) {
super.onLayout(changed, left, top, right, bottom);
return;
}

if(!mInitialized) {
super.onLayout(changed, left, top, right, bottom);
//if mListViewBackground not exists or mListViewBackground exists
//and its top is at headercontainer height then view is initialized
if(mListViewBackground == null || mListViewBackground.getTop() == mHeaderContainer.getHeight())
mInitialized = true;
return;
}

//get last header and listViewBackground position
int headerTopPrevious = mHeaderContainer.getTop();
int listViewBackgroundTopPrevious = mListViewBackground != null ? mListViewBackground.getTop() : 0;

//relayout
super.onLayout(changed, left, top, right, bottom);

//revert header top position
int headerTopCurrent = mHeaderContainer.getTop();
if(headerTopCurrent != headerTopPrevious) {
mHeaderContainer.offsetTopAndBottom(headerTopPrevious - headerTopCurrent);
}
//revert listViewBackground top position
int listViewBackgroundTopCurrent = mListViewBackground != null ? mListViewBackground.getTop() : 0;
if(listViewBackgroundTopCurrent != listViewBackgroundTopPrevious) {
mListViewBackground.offsetTopAndBottom(listViewBackgroundTopPrevious - listViewBackgroundTopCurrent);
}
}
}

和 CDMObservableScrollView 类:

public class CDMObservableScrollView extends ScrollView implements CDMObservableScrollable {
// Edge-effects don't mix well with the translucent action bar in Android 2.X
private boolean mDisableEdgeEffects = true;

private CDMOnScrollChangedCallback mOnScrollChangedListener;

public CDMObservableScrollView(Context context) {
super(context);
}

public CDMObservableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public CDMObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedListener != null) {
mOnScrollChangedListener.onScroll(l, t);
}
}

@Override
protected float getTopFadingEdgeStrength() {
// http://stackoverflow.com/a/6894270/244576
if (mDisableEdgeEffects && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return 0.0f;
}
return super.getTopFadingEdgeStrength();
}

@Override
protected float getBottomFadingEdgeStrength() {
// http://stackoverflow.com/a/6894270/244576
if (mDisableEdgeEffects && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return 0.0f;
}
return super.getBottomFadingEdgeStrength();
}

@Override
public void setOnScrollChangedCallback(CDMOnScrollChangedCallback callback) {
mOnScrollChangedListener = callback;
}
}

编辑 2

我现在可以划定问题了:

如果我使用这些行,FAB 将按照我的意愿工作:

    <denis.de.meperdia.fadingactionbar.CDMObservableScrollView
android:id="@+id/fab__scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">

但随后我的淡入淡出操作栏的同步被破坏了......

抱歉,代码太多了,但如果没有这个,理解起来真的很复杂。

最佳答案

导入app命名空间,用RelativeLayout包围NestedScrollView,然后将RelativeLayout设置为FAB 的 anchor

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" //Import app namespace
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:orientation="vertical"
android:paddingBottom="10dp">

<android.support.v4.widget.NestedScrollView
android:id="@+id/mainview"
android:layout_width="match_parent"
android:layout_height="match_parent">

// Here are the textviews, relativelayouts etc...
</android.support.v4.widget.NestedScrollView>

<android.support.design.widget.FloatingActionButton
android:id="@+id/edit_movies_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_edit_white_24dp"
app:layout_anchor="@id/mainview" //attributes of app namespace
app:layout_anchorGravity="bottom|end"
/>
</android.support.design.widget.CoordinatorLayout>

关于android - FAB 结合 NestedScrollView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43719011/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com