以前のバージョンの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のスライディングモニターでの透明度の計算にあります。