AndroidのAlipayのような折りたたみ式ヘッド

以前のバージョンのAlipayには効果がありました。リストを一番上に引くと、検索ボックスと4つの大きなボタンが表示されます。リストがある程度スライドすると、4つの大きなボタンが上部の4つの小さなボタンになり、検索ボックスは表示されなくなります。この効果は非常にクールに見えますが、折りたたみ可能なツールバーを使用して簡単に実現できます。

1つ目はメインレイアウトactivity_main.xmlです

<androidx.coordinatorlayout.widget.CoordinatorLayout
    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:focusable="true"
    android:focusableInTouchMode="true"
    android:fitsSystemWindows="true">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/abl_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:background="#1983D1">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
            app:contentScrim="#1983d1">

            <include
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"
                layout="@layout/life_pay" />

            <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="60dp"
                app:layout_collapseMode="pin"
                app:contentInsetLeft="0dp"
                app:contentInsetStart="0dp">

                <include
                    android:id="@+id/tl_expand"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    layout="@layout/toolbar_expand" />

                <include
                    android:id="@+id/tl_collapse"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    layout="@layout/toolbar_collapse"
                    android:visibility="gone" />
            </androidx.appcompat.widget.Toolbar>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

3つのレイアウトが含まれています

life_pay.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#1983d1"
    android:paddingBottom="20dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:orientation="horizontal"
        android:layout_marginTop="60dp">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/big_scan" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="5dp"
                    android:text="扫一扫"
                    android:textColor="#ffffff"
                    android:textSize="16sp" />
            </LinearLayout>
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/big_pay" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="5dp"
                    android:text="付一付"
                    android:textColor="#ffffff"
                    android:textSize="16sp" />
            </LinearLayout>
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/big_chat" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="5dp"
                    android:text="聊一聊"
                    android:textColor="#ffffff"
                    android:textSize="16sp" />
            </LinearLayout>
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@mipmap/big_qrcode" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="5dp"
                    android:text="咻一咻"
                    android:textColor="#ffffff"
                    android:textSize="16sp" />
            </LinearLayout>
        </RelativeLayout>
    </LinearLayout>

    <View
        android:id="@+id/v_pay_mask"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#00000000" />

</FrameLayout>

ツールバー_collapse.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="#1983d1">

    <ImageView
        android:id="@+id/iv_scan"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:src="@mipmap/small_scan" />

    <ImageView
        android:id="@+id/iv_pay"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@+id/iv_scan"
        android:src="@mipmap/small_pay" />

    <ImageView
        android:id="@+id/iv_charge"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@+id/iv_pay"
        android:src="@mipmap/small_charge" />

    <ImageView
        android:id="@+id/iv_money"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@+id/iv_charge"
        android:src="@mipmap/small_money" />

    <ImageView
        android:id="@+id/iv_plus"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="20dp"
        android:src="@mipmap/icon_plus" />

    <View
        android:id="@+id/v_collapse_mask"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00000000" />

</RelativeLayout>

ツールバー_expand.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#1983d1"
    android:orientation="horizontal">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        android:layout_toLeftOf="@+id/iv_contact"
        android:background="@drawable/shape_search"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">

        <ImageView
            android:id="@+id/iv_search"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:src="@mipmap/icon_search" />

        <EditText
            android:id="@+id/et_search"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/iv_search"
            android:paddingLeft="10dp"
            android:background="@null"
            android:hint="搜索商品"
            android:textColorHint="#ffffff"
            android:textSize="16sp" />
    </RelativeLayout>

    <ImageView
        android:id="@+id/iv_plus"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"
        android:src="@mipmap/icon_plus" />

    <ImageView
        android:id="@+id/iv_contact"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"
        android:layout_toLeftOf="@+id/iv_plus"
        android:src="@mipmap/icon_contact" />

    <View
        android:id="@+id/v_expand_mask"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00000000" />

</RelativeLayout>

次はMainActivity.javaです

public class MainActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener {

    private final static String TAG = "ScrollAlipayActivity";
    private View tl_expand, tl_collapse; // 分别声明伸展时候与收缩时候的工具栏视图
    private View v_expand_mask, v_collapse_mask, v_pay_mask; // 分别声明三个遮罩视图
    private int mMaskColor; // 遮罩颜色

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获取默认的蓝色遮罩颜色
        mMaskColor = 0xFF1983D1;
        // 从布局文件中获取名叫rv_content的循环视图
        RecyclerView rv_content = findViewById(R.id.rv_content);
        // 设置循环视图的布局管理器(四列的网格布局管理器)
        rv_content.setLayoutManager(new GridLayoutManager(this, 4));
        // 给rv_content设置生活频道网格适配器
        rv_content.setAdapter(new LifeRecyclerAdapter(this, LifeItem.getDefault()));
        // 从布局文件中获取名叫abl_bar的应用栏布局
        AppBarLayout abl_bar = findViewById(R.id.abl_bar);
        // 从布局文件中获取伸展之后的工具栏视图
        tl_expand = findViewById(R.id.tl_expand);
        // 从布局文件中获取收缩之后的工具栏视图
        tl_collapse = findViewById(R.id.tl_collapse);
        // 从布局文件中获取伸展之后的工具栏遮罩视图
        v_expand_mask = findViewById(R.id.v_expand_mask);
        // 从布局文件中获取收缩之后的工具栏遮罩视图
        v_collapse_mask = findViewById(R.id.v_collapse_mask);
        // 从布局文件中获取生活频道的遮罩视图
        v_pay_mask = findViewById(R.id.v_pay_mask);
        // 给abl_bar注册一个位置偏移的监听器
        abl_bar.addOnOffsetChangedListener(this);
    }

    // 每当应用栏向上滚动或者向下滚动,就会触发位置偏移监听器的onOffsetChanged方法
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        int offset = Math.abs(verticalOffset);
        // 获取应用栏的整个滑动范围,以此计算当前的位移比例
        int total = appBarLayout.getTotalScrollRange();
        int alphaIn = px2dip(this, offset) * 2;
        int alphaOut = (200 - alphaIn) < 0 ? 0 : 200 - alphaIn;
        // 计算淡入时候的遮罩透明度
        int maskColorIn = Color.argb(alphaIn, Color.red(mMaskColor),
                Color.green(mMaskColor), Color.blue(mMaskColor));
        // 工具栏下方的生活频道布局要加速淡入或者淡出
        int maskColorInDouble = Color.argb(alphaIn * 2, Color.red(mMaskColor),
                Color.green(mMaskColor), Color.blue(mMaskColor));
        // 计算淡出时候的遮罩透明度
        int alphaOutFinal = alphaOut * 3 > 255 ? 255 : alphaOut * 3;
        int maskColorOut = Color.argb(alphaOutFinal, Color.red(mMaskColor),
                Color.green(mMaskColor), Color.blue(mMaskColor));
        if (offset < total * 0.45) { // 偏移量小于一半,则显示伸展时候的工具栏
            tl_expand.setVisibility(View.VISIBLE);
            tl_collapse.setVisibility(View.GONE);
            v_expand_mask.setBackgroundColor(maskColorInDouble);
        } else { // 偏移量大于一半,则显示收缩时候的工具栏
            tl_expand.setVisibility(View.GONE);
            tl_collapse.setVisibility(View.VISIBLE);
            Log.i("aaaaaaaaaaa","显示:"+alphaOutFinal);
            v_collapse_mask.setBackgroundColor(maskColorOut);
        }
        // 设置life_pay.xml即生活频道视图的遮罩颜色
        v_pay_mask.setBackgroundColor(maskColorIn);
    }

    // 根据手机的分辨率从 px(像素) 的单位 转成为 dp
    public static int px2dip(Context context, float pxValue) {
        // 获取当前手机的像素密度
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f); // 四舍五入取整
    }
}

アダプターとBeanクラスを使用します

LifeRecyclerAdapter.java
public class LifeRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context mContext; // 声明一个上下文对象
    private ArrayList<LifeItem> mItemArray;

    public LifeRecyclerAdapter(Context context, ArrayList<LifeItem> itemArray) {
        mContext = context;
        mItemArray = itemArray;
    }

    // 创建列表项的视图持有者
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 根据布局文件item_life.xml生成视图对象
        View v = LayoutInflater.from(mContext).inflate(R.layout.item_life, parent, false);
        return new ItemHolder(v);
    }

    // 绑定列表项的视图持有者
    public void onBindViewHolder(RecyclerView.ViewHolder vh, int position) {
        ItemHolder holder = (ItemHolder) vh;
        holder.iv_pic.setImageResource(mItemArray.get(position).pic);
        holder.tv_title.setText(mItemArray.get(position).title);
    }

    // 获取列表项的个数
    public int getItemCount() {
        return mItemArray.size();
    }

    // 获取列表项的类型
    public int getItemViewType(int position) {
        return 0;
    }

    // 获取列表项的编号
    public long getItemId(int position) {
        return position;
    }

    // 定义列表项的视图持有者
    public class ItemHolder extends RecyclerView.ViewHolder {
        public ImageView iv_pic; // 声明列表项图标的图像视图
        public TextView tv_title; // 声明列表项标题的文本视图

        public ItemHolder(View v) {
            super(v);
            iv_pic = v.findViewById(R.id.iv_pic);
            tv_title = v.findViewById(R.id.tv_title);
        }
    }

}

item_life.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dp"
    android:background="#ffffff"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_pic"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:layout_gravity="center"
        android:scaleType="fitCenter" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="17sp" />

</LinearLayout>

LifeItem.java

public class LifeItem {
    public int pic;
    public String title;

    public LifeItem(int pic, String title) {
        this.pic = pic;
        this.title = title;
    }

    public static ArrayList<LifeItem> getDefault() {
        ArrayList<LifeItem> itemArray = new ArrayList<LifeItem>();
        for (int i = 0; i < 40; i++) {
            itemArray.add(new LifeItem(R.mipmap.icon_transfer, "转账"));
        }
        return itemArray;
    }
}

このようにして、スライディングヘッドを変更する効果が得られます。誰もがコードをプロジェクトにコピーし、自分で実装します。焦点は、activity_mainのレイアウト方法と、MainActivity.javaのスライディングモニターでの透明度の計算にあります。

おすすめ

転載: blog.csdn.net/weixin_38322371/article/details/115024864