如何在没有嵌套的scrollview的情况下实现新的材质gmail工具栏?

时间:2019-03-02 08:16:23

标签: android material-design material-ui toolbar

我想实现没有嵌套滚动视图的新gmail类工具栏,该视图具有滚动功能,但是向下滚动时背景应该可见。

它看起来像这样: enter image description here

4 个答案:

答案 0 :(得分:1)

您只需要在“活动”布局中创建自定义图标,如

htmlEditor.markText({line:4,ch:1},{line:7,ch:1},{readOnly:true});

并将您的活动样式更改为“ NoActionBar”。对我来说有帮助。

答案 1 :(得分:0)

它不是嵌套的滚动视图,它的recyclerView。 如果需要这样的搜索栏,可以使用CardView和Edittext或使用Material searchba r库来进行搜索。您可以使用frameLayout或CoordinatorLayout将其锁定在该位置。

这是我制作的示例屏幕!

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:background="#dadada"
        android:layout_height="match_parent">

        <android.support.v7.widget.CardView
            app:cardUseCompatPadding="true"
            android:layout_margin="8dp"
            app:cardCornerRadius="8dp"
            android:layout_width="match_parent"
            android:layout_height="64dp">

            <android.support.constraint.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <ImageView
                    android:id="@+id/imageView2"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_marginStart="8dp"
                    android:src="@drawable/ic_menu_black_24dp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

                <EditText
                    android:id="@+id/editText"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="16dp"
                    android:layout_marginTop="8dp"
                    android:layout_marginBottom="8dp"
                    android:background="@android:color/transparent"
                    android:hint="Search..."
                    android:minWidth="100dp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintStart_toEndOf="@+id/imageView2"
                    app:layout_constraintTop_toTopOf="parent" />

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_marginTop="8dp"
                    android:layout_marginEnd="8dp"
                    android:layout_marginBottom="8dp"
                    android:src="@drawable/ic_search_black_24dp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

            </android.support.constraint.ConstraintLayout>

        </android.support.v7.widget.CardView>

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </android.support.v7.widget.RecyclerView>

    </android.support.design.widget.CoordinatorLayout>

这是结果。

enter image description here

答案 2 :(得分:0)

对于任何尝试使用RecyclerView实现此功能的人,只需使用具有不同布局的项目视图类型。 保存主数据的BaseAdapter:

public class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.BaseViewHolder> 

 @Override
    @NonNull
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// this is the main adapter so by default
// it should display the main content.
// Notice the layout being inflated here
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_song_list, null);
        return createViewHolder(v);

    }
// BaseViewHolder is the ViewHolder of this adapter
    protected BaseViewHolder createViewHolder(View view) {
        return new BaseViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final BaseViewHolder holder, final int position) {
        // Do something here
    }

现在创建一个扩展先前适配器的抽象适配器:

public abstract class BaseHeaderAdapter extends BaseAdapter {

    protected static final int ITEM_HEADER = 0;
    protected static final int ITEM_LIST = 1;

   @NonNull
    @Override
    public BaseAdapter.BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ITEM_HEADER) {
// Notice the layout being inflated here
// This is a different layout
            View view = LayoutInflater.from(activity).inflate(R.layout.item_tab_header, parent, false);
            return createViewHolder(view);
        }
// This will return the default layout from the extended adapter
        return super.onCreateViewHolder(parent, viewType);
    }
// BaseAdapter and BaseViewHolder are extended
    @Override
    protected BaseAdapter.BaseViewHolder createViewHolder(View view) {
// Notice: BaseHeaderAdapter is the current adapter
// BaseViewHolder is the extended holder
        return new BaseHeaderAdapter.BaseViewHolder(view);
    }

 @Override
    public int getItemCount() {
        int superItemCount = super.getItemCount();
        return superItemCount == 0 ? 0 : superItemCount + 1;
    }

    @Override
    public int getItemViewType(int position) {
        return position == 0 ? ITEM_HEADER : ITEM_LIST;
    }
// This adapter's ViewHolder
public class BaseHeaderViewHolder extends BaseAdapter.BaseViewHolder {
...
}

}

现在显示所有内容的适配器:

public class MyAdapter extends BaseHeaderAdapter
.....
@Override
    protected BaseAdapter.BaseViewHolder createViewHolder(View view) {
        return new MyAdapter.BaseViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final BaseAdapter.BaseViewHolder holder, int position) {
        if (holder.getItemViewType() == ITEM_HEADER) {
// do some stuff
            holder.mHeaderTitle.setText("Header");
        } else {
            super.onBindViewHolder(holder, position - 1);
        }
    }
// The ViewHolder extends the BaseHeaderAdapter.BaseHeaderViewHolder

Final result 2 Final result 1

答案 3 :(得分:0)

您也可以使用 AppBarLayout 和自定义 CoordinatorLayout.Behavior 解决此问题。首先,以这种方式设置布局:

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior=".view.SearchBarBehaviour">

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            .../>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        app:elevation="0dp">

        <!-- the searchbar with a layout_margin and transparent background etc -->
        <include layout="@layout/searchbar" />

    </com.google.android.material.appbar.AppBarLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

注意设置为 SwipeRefreshLayout 的自定义行为。看起来像这样:

class SearchBarBehaviour(
    context: Context,
    attrs: AttributeSet
) : CoordinatorLayout.Behavior<View>(context, attrs) {

    private var previousY: Float = 0f

    override fun layoutDependsOn(
        parent: CoordinatorLayout, 
        child: View, dependency: View
    ): Boolean = dependency is AppBarLayout

    override fun onDependentViewChanged(
        parent: CoordinatorLayout, 
        child: View, 
        dependency: View
    ): Boolean {
        val currentY = dependency.y
        // When the AppBarLayout scrolls, scroll the RecyclerView for the same distance
        (child as SwipeRefreshLayout)
            .getChildAt(0)
            .scrollBy(0, (previousY - currentY).toInt())

        previousY = currentY
        return false
    }
}

如果您将行为直接附加到 SwipeRefreshLayout/RecyclerView/... 并调整自定义行为中的行以滚动子项本身,这显然也适用于没有 NestedScrollView .

这解决了默认 RecyclerViewScrollingViewBehavior 大小调整问题,该问题导致 RecyclerView 在向下滚动时弹出其项目。