Android水波纹底部导航
写的都是BUG 人气:0今天给大家带来一个自定义的底部导航,我不会做动图,只能搞一张图片给大家看看,大家见谅
这个就是自定义的tablayout底部搞好的样式了
TabLayout提供了一个水平布局用于展示tabs,继承自HorizontalScrollView。一般与Viewpager结合使用实现页面和标签联动的效果,是时下APP中非常常用的一个控件
首先我们需要创建一个类或者是模块都可以
package com.example.map.tab; import android.content.Context; import android.os.Bundle; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentTabHost; import com.example.map.R; import java.util.ArrayList; import java.util.List; /** * Created by long on 2022/5/10. * 扩展TabHost */ public class XFragmentTabHost extends FragmentTabHost { private Context mContext; private List<View> mTabViews; private List<TabItem> mTabItems; // 字体激活颜色 private int mTextActiveColor; private int mTextInactiveColor; // 字体激活大小 private float mTextActiveSize; private float mTextInactiveSize; // 视图激活对顶部的偏移 private int mViewActivePaddingTop; private int mViewInactivePaddingTop; // 波纹模式的前景颜色和后景颜色 private int mFrontColor; private int mBehindColor; // TabHost模式 private TabMode mTabMode; public XFragmentTabHost(Context context) { super(context); _init(context); } public XFragmentTabHost(Context context, AttributeSet attrs) { super(context, attrs); _init(context); } private void _init(Context context) { mTabViews = new ArrayList<>(); mTabItems = new ArrayList<>(); mContext = context; mTextActiveColor = ContextCompat.getColor(mContext, R.color.colorActive); mTextInactiveColor = ContextCompat.getColor(mContext, R.color.colorInactive); mFrontColor = ContextCompat.getColor(mContext, R.color.colorFront); mBehindColor = ContextCompat.getColor(mContext, R.color.colorBehind); mTextActiveSize = getResources().getDimension(R.dimen.tab_text_size_active); mTextInactiveSize = getResources().getDimension(R.dimen.tab_text_size_inactive); mViewActivePaddingTop = (int) getResources().getDimension(R.dimen.tab_padding_top_active); mViewInactivePaddingTop = (int) getResources().getDimension(R.dimen.tab_padding_top_inactive); mTabMode = TabMode.MoveToTop; } /** * 覆写父类接口,并在这里做些动画特效 * @param index 当前选中的Tab项 */ @Override public void setCurrentTab(int index) { // 获取之前选中的index int lastIndex = getCurrentTab(); super.setCurrentTab(index); // 选中不同的Tab项才做切换处理 if (lastIndex != index) { _switchTab(lastIndex, index); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // 部分机型TabHost带有分割线,同一将分割线设为透明 getTabWidget().setDividerDrawable(android.R.color.transparent); } /** * 添加TabItem * @param item TabItem * @param fragClass fragment类名 * @param bundle 传给fragment的参数 */ public void addTabItem(TabItem item, Class<?> fragClass, Bundle bundle) { mTabItems.add(item); View view = _getIndicator(item); mTabViews.add(view); this.addTab(newTabSpec(item.getTitle()).setIndicator(view), fragClass, bundle); } /** * 获取TabItem视图 * @param item TabItem * @return */ private View _getIndicator(TabItem item) { View view = LayoutInflater.from(mContext).inflate(R.layout.tab_indicator, null); ImageView imageView = (ImageView) view.findViewById(R.id.tab_icon); TextView title = (TextView) view.findViewById(R.id.tab_title); imageView.setImageResource(item.getImageRes()); title.setText(item.getTitle()); title.setTextColor(mTextInactiveColor); return view; } /** * 切换Tab * @param lastIndex 上一个选中索引 * @param nextIndex 下一个选中索引 */ private void _switchTab(int lastIndex, int nextIndex) { for (int i = 0; i < mTabViews.size(); i++) { if (i == lastIndex) { _switchView(i, false); } else if (i == nextIndex) { _switchView(i, true); } } } /** * 切换视图 * @param index 索引 * @param isActivated 是否激活 */ private void _switchView(int index, boolean isActivated) { switch (mTabMode) { case MoveToTop: _doMoveToTop(index, isActivated); break; case ClipDrawable: _doClipDrawable(index, isActivated); break; case Ripple: _doRipple(index, isActivated); break; } } /** * 背景展开处理 * @param index 索引 * @param isActivated 是否激活 */ private void _doClipDrawable(int index, boolean isActivated) { View view = mTabViews.get(index); View tabView = view.findViewById(R.id.tab_layout); if (isActivated) { TabAnimHelper.clipDrawable(tabView, mTabItems.get(index).getDrawable(), true); } else { TabAnimHelper.clipDrawable(tabView, mTabItems.get(index).getDrawable(), false); } } /** * 波纹处理 * @param index 索引 * @param isActivated 是否激活 */ private void _doRipple(int index, boolean isActivated) { View view = mTabViews.get(index); View tabView = view.findViewById(R.id.tab_layout); TextView title = (TextView) view.findViewById(R.id.tab_title); if (index == 0) { TabAnimHelper.rippleDrawable(tabView, mFrontColor, mBehindColor, RippleDrawable.MODE_LEFT, isActivated); } else if (index == (mTabViews.size() - 1)){ TabAnimHelper.rippleDrawable(tabView, mFrontColor, mBehindColor, RippleDrawable.MODE_RIGHT, isActivated); } else { TabAnimHelper.rippleDrawable(tabView, mFrontColor, mBehindColor, RippleDrawable.MODE_MIDDLE, isActivated); } if (isActivated) { title.setTextColor(mTextActiveColor); } else { title.setTextColor(mTextInactiveColor); } } /** * 上移动画处理 * @param index 索引 * @param isActivated 是否激活 */ private void _doMoveToTop(int index, boolean isActivated) { View view = mTabViews.get(index); TextView title = (TextView) view.findViewById(R.id.tab_title); ImageView icon = (ImageView) view.findViewById(R.id.tab_icon); if (isActivated) { TabAnimHelper.changeTextColor(title, mTextInactiveColor, mTextActiveColor); TabAnimHelper.changeTextSize(title, mTextInactiveSize, mTextActiveSize); TabAnimHelper.changeTopPadding(view, mViewInactivePaddingTop, mViewActivePaddingTop); TabAnimHelper.changeImageSize(icon, 1.0f, 1.1f); } else { TabAnimHelper.changeTextColor(title, mTextActiveColor, mTextInactiveColor); TabAnimHelper.changeTextSize(title, mTextActiveSize, mTextInactiveSize); TabAnimHelper.changeTopPadding(view, mViewActivePaddingTop, mViewInactivePaddingTop); TabAnimHelper.changeImageSize(icon, 1.1f, 1.0f); } } /** * 属性设置 * @return */ public int getTextActiveColor() { return mTextActiveColor; } public void setTextActiveColor(int textActiveColor) { mTextActiveColor = textActiveColor; } public int getTextInactiveColor() { return mTextInactiveColor; } public void setTextInactiveColor(int textInactiveColor) { mTextInactiveColor = textInactiveColor; } public int getFrontColor() { return mFrontColor; } public void setFrontColor(int frontColor) { mFrontColor = frontColor; } public int getBehindColor() { return mBehindColor; } public void setBehindColor(int behindColor) { mBehindColor = behindColor; } public TabMode getTabMode() { return mTabMode; } public void setTabMode(TabMode tabMode) { mTabMode = tabMode; } /** * Tab的模式 * MoveToTop:向上偏移 * Ripple:波纹 * ClipDrawable:逐步展示背景 */ public enum TabMode { MoveToTop(1), Ripple(2), ClipDrawable(3); private int tabMode; TabMode(int tabMode) { this.tabMode = tabMode; } public int getTabMode() { return tabMode; } } }
然后在res下的value中的color中加入以下颜色
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="black">#000000</color> <color name="white">#FFFFFF</color> <color name="custcolor">#FBD794</color> <color name="translate">#00000000</color> <color name="trans">#70000000</color> <color name="white_trans">#99ffffff</color> <color name="ef">#efefef</color> <color name="c4">#333333</color> <color name="c9">#999999</color> <color name="coloritem">#cccccc</color> <color name="black_bg">#66333333</color> <color name="c1">#111111</color> <color name="c6">#666666</color> <color name="c5">#eeeeee</color> <color name="c2">#ff6700</color> <color name="cfcc">#cccccc</color> <color name="app_color_f6">#f6f6f6</color> <color name="btn_not_click_color">#a8a8a8</color> <color name="btn_click_color">#dc5900</color> <color name="c7">#171717</color> <color name="c3">#cccccc</color> <color name="c33">#333333</color> <color name="test_blue">#338BFF</color> <color name="red1">#f94244</color> <color name="green1">#45cdd5</color> <color name="blue">#5e8cef</color> <color name="blue1">#4980f6</color> <color name="c_c1e4ff">#c1e4ff</color> <color name="c_eff4f8">#eff4f8</color> <color name="e5">#e5e5e5</color> <color name="f6">#f6f6f6</color> <color name="red_normal">#FF0000</color> <color name="red_pressed">#FF6666</color> <color name="blue_bg">#e6fffe</color> <color name="blue_text">#00e8df</color> <color name="org_bg">#ffefe5</color> <color name="green_bg">#e6fff2</color> <color name="green_text">#01e48c</color> <color name="red_bg">#ffeeee</color> <color name="red_text">#ff1901</color> <color name="org1">#fff4ea</color> <color name="org2">#ffa96e</color> <color name="org3">#ff8430</color> <color name="org4">#ff9d5c</color> <color name="org5">#ff802c</color> <color name="org6">#f2c279</color> <color name="org7">#fcf1ea</color> <color name="org8">#fed2c0</color> <color name="org9">#ffece5</color> <color name="green2">#68ffc4</color> <color name="green">#31c088</color> <color name="blue2_trans">#587ed6ff</color> <color name="blue2">#7ed6ff</color> <color name="blue3">#75fff7</color> <color name="blue5">#2d9ef5</color> <color name="photopicker_background">#181819</color> <color name="color1">#00a6b6</color> <color name="c99">#282e35</color> <!-- QR_Code --> <color name="viewfinder_mask">#60000000</color> <color name="result_view">#b0000000</color> <color name="possible_result_points">#c0ffff00</color> <color name="result_image_border">#ffffffff</color> <color name="result_minor_text">#ffc0c0c0</color> <color name="result_points">#c000ff00</color> <color name="system_bar_color">#fed952</color> <color name="red">#eb2127</color> <color name="c_red">#ff4200</color> <color name="red3">#f03030</color> <color name="c_f8">#f8f8f8</color> <color name="c_yellow">#daba7f</color> <color name="c_85">#858585</color> <color name="c_b2">#b2b2b2</color> <color name="c_light_purple">#58ffc8d1</color> <color name="c_purple">#ff6e6b</color> <color name="c_agent_position">#97a8bc</color> <color name="c_agent_name">#143660</color> <color name="c_44db09">#44db09</color> <color name="c_75">#757575</color> <color name="c_f5">#f5f5f5</color> <color name="c_76">#767676</color> <color name="c_d1">#d1d1d1</color> <color name="c_d2">#d2d2d2</color> <color name="c_d3">#d3d3d3</color> <color name="c_yellow3">#ffba16</color> <color name="c_mei_red">#f73954</color> <color name="yellow">#ffbd0a</color> <color name="org">#ff6600</color> <color name="org_trans">#fff6f3</color> <color name="c_d">#dddddd</color> <color name="c_e0">#e0e0e0</color> <color name="red7">#f70c38</color> <color name="green7">#47b81b</color> <color name="deal_bg">#38c595</color> <color name="f1">#f1f1f1</color> <color name="f5">#f5f5f5</color> <color name="c_3c5c8c">#3c5c8c</color> <color name="cus_phone_color">#094691</color> <color name="cus_follow_record_item_name_color">#002553</color> <color name="praise_item_default">#333333</color> <color name="praise_item_selector_default">#cccccc</color> <color name="default_clickable_color">#cccccc</color> <color name="praise_item">#8290AF</color> <color name="im_font_color_text_hint">#abb1b6</color> <color name="ffd1c0">#ffd1c0</color> <color name="fdf0eb">#fdf0eb</color> <color name="e4e9ec">#e4e9ec</color> <color name="d3">#d3d3d3</color> <color name="ffae00">#ffae00</color> <color name="e9eef3">#e9eef3</color> <color name="ecf0f4">#ECF0F4</color> <color name="ac677">#1ac677</color> <color name="ecf1f7">#ECF1F7</color> <color name="cace6">#3cace6</color> <color name="d282">#35d282</color> <color name="ff2a00">#ff2a00</color> <!-- 其它背景色或分割线相关 --> <color name="bg_content">#f3f3f3</color> <color name="divider_line">#d9d9d9</color> <!-- 字体色 --> <color name="text_title">#1b1b1b</color> <color name="text_content">#818181</color> <color name="text_sub">#919191</color> <color name="text_hint">#c7c7c7</color> <color name="text_black">#404040</color> <color name="main_tab_bg">#fcfcfc</color> <color name="black_need">#333333</color> <color name="orange_need">#f0420c</color> <color name="gray_need">#BEC0C1</color> <color name="dialog_content_textcolor">#909090</color> <color name="reply_text_color">#666666</color> <color name="contents_text">#ff000000</color> <color name="encode_view">#ffffffff</color> <color name="help_button_view">#ffcccccc</color> <color name="help_view">#ff404040</color> <color name="result_text">#ffffffff</color> <color name="sbc_header_text">#ff808080</color> <color name="sbc_header_view">#ffffffff</color> <color name="sbc_list_item">#fffff0e0</color> <color name="sbc_layout_view">#ffffffff</color> <color name="sbc_page_number_text">#ff000000</color> <color name="sbc_snippet_text">#ff4b4b4b</color> <color name="share_text">#ff000000</color> <color name="share_view">#ffffffff</color> <color name="status_view">#50000000</color> <color name="status_text">#ffffffff</color> <color name="transparent">#00000000</color> <color name="viewfinder_frame">#ff000000</color> <color name="viewfinder_laser">#ffff0000</color> <!-- 画TextView横线颜色 --> <color name="draw_line_color">#D4D4D4</color> <!-- 侧边仿通讯录26字母列表颜色 --> <color name="addresslist_textcolor">#A9A9A9</color> <color name="car_select_second_child">#999999</color> <color name="car_select_second_group_child_bg">#e1e1e1</color> <color name="map_poi_list_bg">#d3d3d3</color> <!-- 下拉PopupWindow --> <color name="pulldown_popupwindow_bg">#5191F2</color> <color name="butten_green">#1AAC19</color> <color name="check_butten_green">#19ad19</color> <color name="title1">#4a4a4a</color> <color name="title2">#a2a2a2</color> <color name="line">#d1d1d1</color> <color name="c_00c679">#00c679</color> <color name="F5F6F8">#F5F6F8</color> <color name="c65">#656565</color> <color name="fff0e5">#FFF0E5</color> <color name="f0f1f2">#F0F1F2</color> <color name="c7c9d1">#C7C9D1</color> <color name="f5f6f8">#f5f6f8</color> <color name="fd3341">#fd3341</color> <color name="dce1e5">#dce1e5</color> <color name="c_9498a4">#9498a4</color> <color name="c_202741">#202741</color> <color name="c_444861">#444861</color> <color name="c_e8">#e8e8e8</color> <color name="ff8963">#FF8963</color> <color name="c_2a3038">#2a3038</color> <color name="c_939">#9398AE</color> <color name="c_00a">#00A7FF</color> <color name="c_5c6166">#5c6166</color> <color name="c_e4e5e6">#e4e5e6</color> <color name="c_ffb452">#ffb452</color> <color name="c_ff7252">#ff7252</color> <color name="c8898A6">#8898A6</color> <color name="acb0b9">#ACB0B9</color> <color name="caccd0">#CACCD0</color> <color name="c_f0f1f3">#f0f1f3</color> <color name="eda95b40">#eda95b40</color> <color name="c_3257c5">#3257c5</color> <color name="c_9d9da3">#9d9da3</color> <color name="c_d7d8dc">#d7d8dc</color> <color name="c4c6cc">#c4c6cc</color> <color name="cdcfd5">#cdcfd5</color> <color name="d2d4d9">#d2d4d9</color> <color name="c_939499">#939499</color> <color name="c_616366">#616366</color> <color name="dc">#dcdcdc</color> <color name="cc0042ff">#cc0042ff</color> <color name="c_97a0ab">#97a0ab</color> <color name="ebba8f">#ebba8f</color> <color name="a86010">#a86010</color> <color name="colorActive">#00BCD4</color> <color name="colorInactive">#d2d0d1</color> <color name="colorFront">#4db6ac</color> <color name="colorBehind">#84ffff</color> </resources>
然后是我们的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="@dimen/tab_height" android:minWidth="@dimen/tab_min_width" android:paddingTop="@dimen/tab_padding_top_inactive" android:paddingBottom="@dimen/tab_padding_bottom" android:background="?selectableItemBackgroundBorderless"> <ImageView android:id="@+id/tab_icon" android:layout_width="@dimen/tab_icon" android:layout_height="@dimen/tab_icon" android:layout_gravity="center_horizontal"/> <TextView android:id="@+id/tab_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:lines="1" android:text="首页" android:textColor="@color/colorInactive" android:textSize="@dimen/tab_text_size_inactive"/> </LinearLayout>
布局中呢会有一些图片这个图片的话就自己搞吧然后在res文件下创建一个dimen
<?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="tab_elevation">8dp</dimen> <dimen name="tab_shadow_height">3dp</dimen> <dimen name="tab_shadow_height_without_colored_background">4dp</dimen> <dimen name="tab_min_width">104dp</dimen> <dimen name="tab_max_width">168dp</dimen> <dimen name="tab_height">56dp</dimen> <dimen name="tab_line_width">1dp</dimen> <dimen name="tab_icon">24dp</dimen> <dimen name="tab_padding_top_active">3dp</dimen> <dimen name="tab_padding_top_inactive">6dp</dimen> <dimen name="tab_padding_top_inactive_without_text">16dp</dimen> <dimen name="tab_padding_bottom">3dp</dimen> <dimen name="tab_padding_left">12dp</dimen> <dimen name="tab_padding_right">12dp</dimen> <dimen name="tab_text_size_active">14sp</dimen> <dimen name="tab_text_size_inactive">12sp</dimen> </resources>
我们的底部导航的样式就搞完了,接下里就是我们的动画效果写一个自定义Drawable
package com.example.map.tab; import android.animation.ValueAnimator; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; /** * Created by long on 2022/5/10. * 波纹Drawable */ public class RippleDrawable extends Drawable implements Animatable { /** * 3种模式:左边、中间和右边波纹 */ public static final int MODE_LEFT = 1; public static final int MODE_MIDDLE = 2; public static final int MODE_RIGHT = 3; private int mMode = MODE_MIDDLE; // 前景色和后景色画笔 private Paint mPaintFront; private Paint mPaintBehind; // 用来绘制扇形的矩形框 private RectF mRect; // 目标View的宽高的一半 private int mHalfWidth; private int mHalfHeight; // 扩散半径 private int mRadius; // 前景色和背景色的分割距离 private int mDivideSpace; // 扩散满视图需要的距离,中点到斜角的距离 private int mFullSpace; // 动画控制 private ValueAnimator mValueAnimator; public RippleDrawable(int frontColor, int behindColor, int mode) { mPaintFront = new Paint(Paint.ANTI_ALIAS_FLAG); mPaintFront.setColor(frontColor); mPaintBehind = new Paint(Paint.ANTI_ALIAS_FLAG); mPaintBehind.setColor(behindColor); mRect = new RectF(); mMode = mode; } @Override public void draw(Canvas canvas) { if (mRadius > mHalfWidth) { int count = canvas.save(); canvas.drawCircle(mHalfWidth, mHalfHeight, mHalfWidth, mPaintBehind); canvas.restoreToCount(count); count = canvas.save(); canvas.drawCircle(mHalfWidth, mHalfHeight, mDivideSpace, mPaintFront); canvas.restoreToCount(count); } else if (mRadius > mDivideSpace) { int count = canvas.save(); canvas.drawCircle(mHalfWidth, mHalfHeight, mRadius, mPaintBehind); canvas.restoreToCount(count); count = canvas.save(); canvas.drawCircle(mHalfWidth, mHalfHeight, mDivideSpace, mPaintFront); canvas.restoreToCount(count); } else { canvas.drawCircle(mHalfWidth, mHalfHeight, mRadius, mPaintFront); } // 左右两边才进行扇形绘制 if (mMode != MODE_MIDDLE) { mRect.left = mHalfWidth - mRadius; mRect.right = mHalfWidth + mRadius; mRect.top = mHalfHeight - mRadius; mRect.bottom = mHalfHeight + mRadius; } if (mMode == MODE_LEFT) { canvas.drawArc(mRect, 90, 180, true, mPaintFront); } else if (mMode == MODE_RIGHT) { canvas.drawArc(mRect, -90, 180, true, mPaintFront); } } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter colorFilter) { } @Override public int getOpacity() { return PixelFormat.RGBA_8888; } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mHalfHeight = (bounds.bottom - bounds.top) / 2; mHalfWidth = (bounds.right - bounds.left) / 2; mDivideSpace = Math.max(mHalfHeight, mHalfWidth) * 3 / 4; mFullSpace = (int) Math.sqrt(mHalfWidth * mHalfWidth + mHalfHeight * mHalfHeight); // 属性动画 mValueAnimator = ValueAnimator.ofInt(0, mFullSpace); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mRadius = (int) animation.getAnimatedValue(); invalidateSelf(); } }); mValueAnimator.setDuration(200); start(); } @Override public void start() { mValueAnimator.start(); } @Override public void stop() { mValueAnimator.end(); } @Override public boolean isRunning() { return mValueAnimator != null && mValueAnimator.isRunning(); } }
然后创建我们的TabFragment
package com.example.map.tab; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.example.map.R; /** * Created by long on 2022/5/10. */ public class TabFragment extends Fragment { public static final String FRAG_KEY = "FragKey"; private TextView mFragTabText; private void assignViews(View view) { mFragTabText = (TextView) view.findViewById(R.id.frag_tab_text); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_tab, null); assignViews(view); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (getArguments() != null) { String title = getArguments().getString(FRAG_KEY); mFragTabText.setText(title); } } }
然后创建一个动画的帮助类
package com.example.map.tab; import android.animation.AnimatorSet; import android.animation.ArgbEvaluator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.graphics.drawable.ClipDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.widget.ImageView; import android.widget.TextView; /** * Created by long on 2022/5/10. * Tab动画帮助类 */ public class TabAnimHelper { /** * 改变Tab的顶部偏移 * @param view * @param fromPadding * @param toPadding */ public static void changeTopPadding(final View view, int fromPadding, int toPadding) { ValueAnimator animator = ValueAnimator.ofFloat(fromPadding, toPadding); animator.setDuration(150); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float animatedValue = (float) valueAnimator.getAnimatedValue(); view.setPadding(view.getPaddingLeft(), (int) animatedValue, view.getPaddingRight(), view.getPaddingBottom()); } }); animator.start(); } /** * 改变字体大小 * @param textView * @param from * @param to */ public static void changeTextSize(final TextView textView, float from, float to) { ValueAnimator textSizeChangeAnimator = ValueAnimator.ofFloat(from, to); textSizeChangeAnimator.setDuration(150); textSizeChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) valueAnimator.getAnimatedValue()); } }); textSizeChangeAnimator.start(); } /** * 改变字体颜色 * @param textView * @param fromColor * @param toColor */ public static void changeTextColor(final TextView textView, int fromColor, int toColor) { ValueAnimator changeTextColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), fromColor, toColor); changeTextColorAnimation.setDuration(150); changeTextColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { textView.setTextColor((Integer) animator.getAnimatedValue()); } }); changeTextColorAnimation.start(); } /** * 改变视图大小 * @param image * @param fromScale * @param toScale */ public static void changeImageSize(ImageView image, float fromScale, float toScale) { ObjectAnimator scaleX; ObjectAnimator scaleY; scaleX = ObjectAnimator.ofFloat(image, "scaleX", fromScale, toScale); scaleY = ObjectAnimator.ofFloat(image, "scaleY", fromScale, toScale); AnimatorSet set = new AnimatorSet(); set.setDuration(150); set.playTogether(scaleX, scaleY); set.start(); } /** * 从中心展开Drawable * @param image * @param drawable * @param isActivated */ @SuppressWarnings("deprecation") public static void clipDrawable(final View image, Drawable drawable, boolean isActivated) { if (drawable == null) { return; } if (isActivated) { final ClipDrawable scaleDrawable = new ClipDrawable(drawable, Gravity.CENTER, ClipDrawable.HORIZONTAL | ClipDrawable.VERTICAL); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { image.setBackground(scaleDrawable); } else { image.setBackgroundDrawable(scaleDrawable); } image.setBackgroundDrawable(scaleDrawable); ValueAnimator animator = ValueAnimator.ofInt(0, 10000); animator.setDuration(200); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { scaleDrawable.setLevel((Integer) animation.getAnimatedValue()); } }); animator.start(); } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { image.setBackground(null); } else { image.setBackgroundDrawable(null); } } } /** * 波纹动画 * @param view * @param frontColor * @param behindColor * @param mode * @param isActivated */ @SuppressWarnings("deprecation") public static void rippleDrawable(final View view, int frontColor, int behindColor, int mode, boolean isActivated) { if (isActivated) { RippleDrawable rippleDrawable = new RippleDrawable(frontColor, behindColor, mode); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(rippleDrawable); } else { view.setBackgroundDrawable(rippleDrawable); } } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(null); } else { view.setBackgroundDrawable(null); } } } }
还有一个item的实体类
package com.example.map.tab; import android.graphics.drawable.Drawable; /** * Created by long on 2022/5/10. * Tab项 */ public class TabItem { private String title; private Drawable drawable; private int imageRes; public TabItem(String title, Drawable drawable, int imageRes) { this.title = title; this.drawable = drawable; this.imageRes = imageRes; } public TabItem(String title, int imageRes) { this.title = title; this.drawable = null; this.imageRes = imageRes; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Drawable getDrawable() { return drawable; } public void setDrawable(Drawable drawable) { this.drawable = drawable; } public int getImageRes() { return imageRes; } public void setImageRes(int imageRes) { this.imageRes = imageRes; } }
然后在我们的Activity中进行一个引用,首先在是我们Activity的一个布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical"> <FrameLayout android:id="@+id/relate_tab_content" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <TextView android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/shadow" /> <com.example.map.tab.XFragmentTabHost android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="wrap_content"> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="0dp" android:layout_height="0dp" /> </com.example.map.tab.XFragmentTabHost> </LinearLayout>
然后在我们的Activity中进行一个应用控件
package com.example.map.ui.activity; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; import com.example.map.api.ApiService; import com.example.map.base.GlideImageLoader; import com.example.map.bean.WallPaperResponse; import com.example.map.ui.fragment.Fragment1; import com.example.map.ui.fragment.Fragment2; import com.example.map.ui.fragment.Fragment3; import com.example.map.ui.fragment.Fragment4; import com.example.map.ui.fragment.Fragment5; import com.example.map.R; import com.example.map.tab.TabFragment; import com.example.map.tab.TabItem; import com.example.map.tab.XFragmentTabHost; import com.llw.network.NetworkApi; import com.llw.network.observer.BaseObserver; import com.llw.network.utils.KLog; import com.youth.banner.Banner; import com.youth.banner.BannerConfig; import com.youth.banner.Transformer; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class QihooActivity extends AppCompatActivity { private XFragmentTabHost mTabHost; //底部导航的名称 String[] mTabTitle = new String[]{"首页", "游戏", "软件", "应用圈", "管理"}; //文字上的图片 int[] mImageResId = new int[]{R.drawable.sel_360_home, R.drawable.sel_360_game, R.drawable.sel_360_software, R.drawable.sel_360_app, R.drawable.sel_360_mag}; //创建的几个fragment Class[] mFragClass = new Class[]{Fragment1.class, Fragment2.class, Fragment3.class, Fragment4.class, Fragment5.class}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_qihoo); initTabHost(); } private void initTabHost() { mTabHost = (XFragmentTabHost) findViewById(android.R.id.tabhost); mTabHost.setup(this, getSupportFragmentManager(), R.id.relate_tab_content); mTabHost.setTabMode(XFragmentTabHost.TabMode.Ripple); mTabHost.setTextActiveColor(Color.WHITE); mTabHost.setTextInactiveColor(Color.GRAY); // mTabHost.setFrontColor(Color.RED); // mTabHost.setBehindColor(Color.GREEN); for (int i = 0; i < mFragClass.length; i++) { Bundle bundle = new Bundle(); bundle.putString(TabFragment.FRAG_KEY, mTabTitle[i]); mTabHost.addTabItem(new TabItem(mTabTitle[i], mImageResId[i]), mFragClass[i], bundle); } } }
这样我们的一个自定义的水波纹动画的底部导航就完成了
加载全部内容