封装Android带Lottie动画的底部导航栏
Posted ImportSUC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了封装Android带Lottie动画的底部导航栏相关的知识,希望对你有一定的参考价值。
-
什么是Lottie动画
Lottie 是Airbnb开源的一个面向 ios、android、React Native 的动画库,能分析 Adobe After Effects 导出的动画,并且能让原生 App 像使用静态素材一样使用这些动画,完美实现动画效果,动画效果比原生动画要优美很多。Lottie动画由UI提供,UI给到我们的是xxx.json文件,这个文件就是动画文件。
优点:动画效果好,灵活,导入方便,使用简单,可以从网络下载,支持多平台。
缺点:性能没有属性动画好。 -
导入Lottie动画库
github地址
在app build.gradle 中导入
implementation 'com.airbnb.android:lottie:$lottieVersion'
$lottieVersion 为版本号。
注意2.8.0及之后的版本加入了android x, 如果你的项目没有使用android x ,要使用2.8.0之前的版本,否则会编译失败
Lottie 2.8.0 and above only supports projects that have been migrated
to androidx.
- 导入动画文件
在 main文件夹下创建assets文件夹,将json文件放入assets文件夹下。需要确认json中是否包含本地文件路径,例如 img0/image1.png,如果存在,需要将本地图片按路径存储,否则运行会报错。
- 代码中实现动画播放
关键类 LottieAnimationView ,LottieDrawable 。此类实现Lottie动画的配置及控制。
LottieAnimationView继承AppCompatImageView,所以它是支持Lottie的Imageview。
mLottieView.setImageAssetsFolder("image0"); //设置本地文件路径
mLottieView.setRepeatCount(0); //设置重复次数,默认0
mLottieView.setAnimation(mAnimationPath);//mAnimationPath 是动画json文件的相对路径
mLottieView.playAnimation();//播放动画
//其他属性自行搜索
以上配置也可以在xml中配置。
app:lottie_fileName="xxx.json"
app:lottie_repeatCount="0"
app:lottie_imageAssetsFolder="image0"//其他属性自行搜索
- 导航栏实现
新建自定义控件 LottieTabView
public class LottieTabView extends FrameLayout
private int mTextNormalColor;
private int mTextSelectColor;
private float mTextSize;
private String mTabName;
private Drawable mIconNormal;
private String mAnimationPath;
private LottieAnimationView mLottieView;
private TextView mTabNameView;
private TextView mMsgView;
private boolean isSelected;
public LottieTabView(Context context)
super(context);
public LottieTabView(Context context, AttributeSet attrs)
super(context, attrs);
init(context, attrs);
public LottieTabView(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init(context, attrs);
private void init(Context context, AttributeSet attrs)
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LottieTabView);
mTextNormalColor = ta.getColor(R.styleable.LottieTabView_text_normal_color, Color.BLACK);
mTextSelectColor = ta.getColor(R.styleable.LottieTabView_text_selected_color, Color.BLUE);
mTextSize = ta.getDimension(R.styleable.LottieTabView_text_size, SizeUtils.dp2px(5));
mIconNormal = ta.getDrawable(R.styleable.LottieTabView_icon_normal);
mAnimationPath = ta.getString(R.styleable.LottieTabView_lottie_path);
mTabName = ta.getString(R.styleable.LottieTabView_tab_name);
isSelected = ta.getBoolean(R.styleable.LottieTabView_tab_selected, false);
ta.recycle();
initView(context);
private void initView(Context context)
View containView = LayoutInflater.from(context).inflate(R.layout.lottie_tab_view, null, false);
mLottieView = containView.findViewById(R.id.animation_view);
mLottieView.setRepeatCount(0);
mTabNameView = containView.findViewById(R.id.tab_name);
mTabNameView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
mTabNameView.setTextColor(mTextNormalColor);
mTabNameView.setText(mTabName);
mMsgView = containView.findViewById(R.id.msg_view);
this.addView(containView);
if (isSelected)
selected();
else
unSelected();
public void selected()
if (TextUtils.isEmpty(mAnimationPath))
throw new NullPointerException("ainmation path must be not empty");
else
mLottieView.setAnimation(mAnimationPath);
mLottieView.playAnimation();
mTabNameView.setTextColor(mTextSelectColor);
public void unSelected()
mTabNameView.setTextColor(mTextNormalColor);
mLottieView.clearAnimation();
mLottieView.setImageDrawable(mIconNormal);
//在右上角显示消息提示数量
public void showMsg(int num)
if (num > 0 && num <= 99)
mMsgView.setVisibility(VISIBLE);
mMsgView.setText(num + "");
else if (num > 99)
mMsgView.setVisibility(VISIBLE);
mMsgView.setText("99+");
else
mMsgView.setVisibility(View.GONE);
控件布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipToPadding="false"
android:clipChildren="false">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="21dp"
android:layout_height="23dp" />
<TextView
android:id="@+id/tab_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="首页"
android:textSize="9sp"
android:textColor="@color/colorMain" />
</LinearLayout>
<TextView
android:id="@+id/msg_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginBottom="30dp"
android:background="@drawable/rc_unread_count_bg"
android:gravity="center"
android:textColor="@color/white"
android:textSize="8sp"
android:visibility="gone" />
</FrameLayout>
attr.xml中
<declare-styleable name="LottieTabView">
<attr name="text_selected_color" format="color"/>
<attr name="text_normal_color" format="color"/>
<attr name="text_size" format="dimension"/>
<attr name="lottie_path" format="string"/>
<attr name="icon_normal" format="reference"></attr>
<attr name="tab_selected" format="boolean"></attr>
<attr name="tab_name" format="string"/>
</declare-styleable>
界面中使用
<com.xxx.xxxx.view.widget.LottieTabView
android:id="@+id/tab_view_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:icon_normal="@drawable/ic_main_normal"
app:lottie_path="mainpage.json"
app:tab_name="首页"
app:tab_selected="true"
app:text_normal_color="@color/color66"
app:text_selected_color="@color/colorMain"
app:text_size="9sp" />
<com.xxx.xxxx.view.widget.LottieTabView
android:id="@+id/tab_view_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:icon_normal="@drawable/ic_msg_normal"
app:lottie_path="news.json"
app:tab_name="消息"
app:tab_selected="false"
app:text_normal_color="@color/color66"
app:text_selected_color="@color/colorMain"
app:text_size="9sp" />
<com..xxx.xxxx.view.widget.LottieTabView
android:id="@+id/tab_view_deal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:icon_normal="@drawable/ic_deal_normal"
app:lottie_path="trade.json"
app:tab_name="交易"
app:tab_selected="false"
app:text_normal_color="@color/color66"
app:text_selected_color="@color/colorMain"
app:text_size="9sp" />
<com.xxx.xxxx.view.widget.LottieTabView
android:id="@+id/tab_view_mine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:icon_normal="@drawable/ic_mine_normal"
app:lottie_path="user.json"
app:tab_name="我的"
app:tab_selected="false"
app:text_normal_color="@color/color66"
app:text_selected_color="@color/colorMain"
app:text_size="9sp" />
</LinearLayout>
Mainactivity中
@OnClick(R.id.tab_view_main, R.id.tab_view_msg, R.id.tab_view_deal, R.id.tab_view_mine)
public void onClickView(View view)
switch (view.getId())
case R.id.tab_view_main:
displayFragment(0);//展示相应的fragment
mLottieMainTab.selected();
mLottieMsgTab.unSelected();
mLottieDealTab.unSelected();
mLottieMineTab.unSelected();
break;
case R.id.tab_view_msg:
displayFragment(1);
mLottieMsgTab.selected();
mLottieDealTab.unSelected();
mLottieMineTab.unSelected();
mLottieMainTab.unSelected();
break;
case R.id.tab_view_deal:
displayFragment(2);
mLottieDealTab.selected();
mLottieMsgTab.unSelected();
mLottieMineTab.unSelected();
mLottieMainTab.unSelected();
break;
case R.id.tab_view_mine:
displayFragment(3);
mLottieMineTab.selected();
mLottieMsgTab.unSelected();
mLottieDealTab.unSelected();
mLottieMainTab.unSelected();
break;
待优化:在此基础上再封装一层LottieTabLayout,动态设置每个LottieTabView的属性。在MainActivity 中直接使用LottieTabLayout。
End
以上是关于封装Android带Lottie动画的底部导航栏的主要内容,如果未能解决你的问题,请参考以下文章
Android Compose 新闻App导航动画WebView浮动按钮底部导航