📜  颤动底部导航栏所选项目填充 (1)

📅  最后修改于: 2023-12-03 14:58:47.587000             🧑  作者: Mango

颤动底部导航栏所选项目填充

在移动应用程序设计中,底部导航栏通常用来给用户提供快速、轻松的导航方式。为了增强用户的交互体验,设计师与开发人员常常会为底部导航栏添加一个颤动效果。当用户点击导航栏中的某个项目时,该项目会通过颤动效果来提示用户已经选中。

本文介绍如何通过编写代码实现“颤动底部导航栏所选项目填充”的效果。

实现步骤

以下是构建颤动底部导航栏所选项目填充效果的步骤:

  1. 在布局文件中定义底部导航栏,并为每个项目添加选中和未选中的状态:
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
    android:orientation="horizontal" android:background="@color/colorBackground">

    <ImageView android:id="@+id/navigation_home" android:layout_width="0dp"
        android:layout_height="wrap_content" android:layout_weight="1"
        android:src="@drawable/ic_home" android:contentDescription="@string/nav_home"
        android:padding="8dp" android:layout_margin="8dp"
        android:background="@drawable/nav_item_selector"/>

    <ImageView android:id="@+id/navigation_dashboard" android:layout_width="0dp"
        android:layout_height="wrap_content" android:layout_weight="1"
        android:src="@drawable/ic_dashboard" android:contentDescription="@string/nav_dashboard"
        android:padding="8dp" android:layout_margin="8dp"
        android:background="@drawable/nav_item_selector"/>

    <ImageView android:id="@+id/navigation_notifications" android:layout_width="0dp"
        android:layout_height="wrap_content" android:layout_weight="1"
        android:src="@drawable/ic_notifications" android:contentDescription="@string/nav_notifications"
        android:padding="8dp" android:layout_margin="8dp"
        android:background="@drawable/nav_item_selector"/>

</LinearLayout>

在这里,nav_item_selector 是一个 XML 文件,定义了导航栏项目的选中和未选中状态。下面是示例代码:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_home_selected" android:state_selected="true"/>
    <item android:drawable="@drawable/ic_home_unselected"/>
</selector>
  1. 在活动或碎片中创建一个导航栏选项选中监听器,以便捕获每个导航栏项目的选择状态:
public class MainActivity extends AppCompatActivity {

    private ImageView mHomeImageView;
    private ImageView mDashboardImageView;
    private ImageView mNotificationsImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHomeImageView = findViewById(R.id.navigation_home);
        mDashboardImageView = findViewById(R.id.navigation_dashboard);
        mNotificationsImageView = findViewById(R.id.navigation_notifications);

        // 为每个导航栏选项添加选中状态监听器
        mHomeImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHomeImageView.setSelected(true);
                mDashboardImageView.setSelected(false);
                mNotificationsImageView.setSelected(false);
            }
        });

        mDashboardImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDashboardImageView.setSelected(true);
                mHomeImageView.setSelected(false);
                mNotificationsImageView.setSelected(false);
            }
        });

        mNotificationsImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mNotificationsImageView.setSelected(true);
                mHomeImageView.setSelected(false);
                mDashboardImageView.setSelected(false);
            }
        });
    }
}
  1. 在这个监听器中添加让所选项目颤动的代码。可以使用 ValueAnimator 类来实现这个效果:
public class MainActivity extends AppCompatActivity {

    private ImageView mHomeImageView;
    private ImageView mDashboardImageView;
    private ImageView mNotificationsImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHomeImageView = findViewById(R.id.navigation_home);
        mDashboardImageView = findViewById(R.id.navigation_dashboard);
        mNotificationsImageView = findViewById(R.id.navigation_notifications);

        // 为每个导航栏选项添加选中状态监听器
        mHomeImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHomeImageView.setSelected(true);
                mDashboardImageView.setSelected(false);
                mNotificationsImageView.setSelected(false);
                animateSelected(mHomeImageView);
            }
        });

        mDashboardImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDashboardImageView.setSelected(true);
                mHomeImageView.setSelected(false);
                mNotificationsImageView.setSelected(false);
                animateSelected(mDashboardImageView);
            }
        });

        mNotificationsImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mNotificationsImageView.setSelected(true);
                mHomeImageView.setSelected(false);
                mDashboardImageView.setSelected(false);
                animateSelected(mNotificationsImageView);
            }
        });
    }

    // 颤动选中的导航栏项目
    private void animateSelected(View view) {
        int duration = 100;
        ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
        animator.setInterpolator(new FastOutSlowInInterpolator());
        animator.setDuration(duration);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float progress = (float) animation.getAnimatedValue();
                float interpolation = -0.5f * (float) Math.cos(progress * Math.PI) + 0.5f;
                view.setScaleX(interpolation);
                view.setScaleY(interpolation);
            }
        });
        animator.start();
    }
}

其中,animateSelected() 方法使用了 ofFloat() 方法来创建动画,指定了动画的起始和结束值。setInterpolator() 方法则设置了动画的插值器来调整动画速度和变化率。addUpdateListener() 方法为动画添加更新监听器。在更新监听器中,我们根据动画时间计算当前的动画进度,然后使用余弦函数来计算缩放系数,最后更新所选的导航栏项目的缩放比例。start() 方法则开始运行动画。

总结

通过实现上述三个步骤,我们可以为底部导航栏的项目添加点击效果,提高用户的交互体验。这个效果在许多使用场景下非常有用,比如移动应用程序主页、菜单选项卡等。