Android底部Tab+ViewPager(微信界面)
2016-12-07 11:12
513 查看
Android底部Tab+ViewPager(微信界面)
http://www.imooc.com/article/14678 原创
2016-11-20 22:14:4781浏览0评论感谢 github的作者:wuyexiong
效果图(图片和文字都有渐变效果)
实现
<br>主要用到自定义一个LinearLayout和ImageView<br><br>
1.BottomIconView继承自ImageView
BottomIconView的作用是现在Tab中的图标,有根据滑动的偏移值显示渐变的图标。
package jfsl.view.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.ImageView; /** * 底部Tab图标类, * 分正常的状态和选中的状态 * 根据滑动的偏移量改变alpha值 * 然后显示出来 * <p> * 感谢 wuyexiong * Created by wuyexiong on 4/25/15. * Modify by JFSL on 2016-11-20 20:05 */ public class BottomIconView extends ImageView { public static final int START_POSITION = 0; public static final int ALPHA_MAX = 255; //画笔 private Paint mPaint; //选中时的图标 private Bitmap mIconSelected; //未选中时的图标 private Bitmap mIconNormal; //选中时的矩形(限制绘制范围) private Rect mRectSelected; //未选中时的矩形(限制绘制范围) private Rect mRectNormal; //当前的alpha值 private int mAlphaCurrent = 0; public BottomIconView(Context context) { super(context); } public BottomIconView(Context context,AttributeSet attrs) { super(context,attrs); } public BottomIconView(Context context,AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr); } /** * 初始化 * * @param normal 正常图标的id * @param selected 选中的图标的id */ public final void init(int normal,int selected) throws Exception { mIconNormal = createBitmap(normal); mIconSelected = createBitmap(selected); //创建不了图片 if(mIconNormal == null || mIconSelected == null) throw new Exception("icon id can not create1 bitmap"); //根据创建的位图创建对应的矩形 mRectNormal = new Rect(START_POSITION,START_POSITION,mIconNormal.getWidth(),mIconNormal.getHeight()); mRectSelected = new Rect(START_POSITION,START_POSITION,mIconSelected.getWidth(),mIconSelected.getHeight()); //画笔只要实例化就行,没有什么要求 mPaint = new Paint(1); } /** * 根据资源id创建的位图 * * @param resId 资源id * @return 创建的位图 */ private Bitmap createBitmap(int resId) { return BitmapFactory.decodeResource(getResources(),resId); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画笔为空,直接返回 if(mPaint == null) return; //设置当前选中图标的alpha值(逐渐减少) mPaint.setAlpha(ALPHA_MAX - mAlphaCurrent); canvas.drawBitmap(mIconNormal,null,mRectNormal,mPaint); //设置目标图标的alpha值(逐渐减增大) mPaint.setAlpha(mAlphaCurrent); canvas.drawBitmap(mIconSelected,null,mRectSelected,mPaint); } /** * 改变alpha值 * * @param alpha */ public final void changeSelectedAlpha(int alpha) { mAlphaCurrent = alpha; invalidate(); } /** * ViewPager切换时用到 * * @param offset 偏移量 */ public final void transformPage(float offset) { changeSelectedAlpha((int)(ALPHA_MAX * (1 - offset))); } }
2.底部Tab(BottomIndicator继承自LinearLayout)
package jfsl.view.view; import android.animation.ArgbEvaluator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import jfsl.view.R; /** * 底部指示器 * Github上的例子,拿来修改了下 * Created by wuyexiong on 4/25/15. * @version 1.0 * @aduthor JFSL * @date 2016/11/14 */ public class BottomIndicator extends LinearLayout { public static final int ICON_INDEX_NORMAL = 0; public static final int ICON_INDEX_SELECTED = 1; public static final int DEFALUT_SELECTED_ITEM = 0; public static final String COLOR_TEXT_NORMAL = "#FF999999"; public static final String COLOR_TEXT_SELECTED = "#FF46C01B"; //文字颜色渐变类 private ArgbEvaluator mColorEvaluator; //正常文本的颜色 private int mTextNormalColor; //选中时文本的颜色 private int mTextSelectedColor; //最后的位置 private int mLastPosition; //选中的位置 private int mSelectedPosition; //选择的偏移量 private float mSelectionOffset; //底部tab文本 private String mTitles[] = {"微信","通讯录","发现","我"}; //对应的图标 private int mIconRes[][] = { {R.drawable.icon_main_home_normal,R.drawable.icon_main_home_selected}, {R.drawable.icon_main_category_normal,R.drawable.icon_main_category_selected}, {R.drawable.icon_main_service_normal,R.drawable.icon_main_service_selected}, {R.drawable.icon_main_mine_normal,R.drawable.icon_main_mine_selected}}; //Item数组 private View[] mItemLayout; //关联的ViewPager private ViewPager mViewPager; public BottomIndicator(Context context) { this(context,null); } public BottomIndicator(Context context,AttributeSet attrs) { this(context,attrs,0); } public BottomIndicator(Context context,AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr); //初始化 init(); } /** * 初始化 */ private void init() { //实例化颜色渐变类 mColorEvaluator = new ArgbEvaluator(); //选中和未选中的文本的颜色 mTextNormalColor = Color.parseColor(COLOR_TEXT_NORMAL); mTextSelectedColor = Color.parseColor(COLOR_TEXT_SELECTED); } public void setViewPager(ViewPager viewPager) { //清空所有的view removeAllViews(); mViewPager = viewPager; //viewapger数据不为空 if(viewPager != null && viewPager.getAdapter() != null) { //设置监听 viewPager.addOnPageChangeListener(new ViewPagerListener()); try { populateTabLayout(); }catch(Exception e) { e.printStackTrace(); } } } /** * 生成底部tab */ private void populateTabLayout() throws Exception { final PagerAdapter adapter = mViewPager.getAdapter(); final OnClickListener tabClickListener = new TabClickListener(); //根据adapter中item 的数量生成数组 mItemLayout = new View[ adapter.getCount() ]; //遍历 for(int i = 0;i < adapter.getCount();i++) { final View tabView = LayoutInflater.from(getContext()).inflate(R.layout.item_bottom_tab,this,false); //找不到对应的布局 if(tabView == null) throw new IllegalStateException("tabView is null."); mItemLayout[ i ] = tabView; //图标 BottomIconView iconView = (BottomIconView)tabView.findViewById(R.id.bottom_tab_icon); iconView.init(mIconRes[ i ][ ICON_INDEX_NORMAL ],mIconRes[ i ][ ICON_INDEX_SELECTED ]); //文字 TextView textView = (TextView)tabView.findViewById(R.id.bottom_tab_text); textView.setText(mTitles[ i ]); //改变宽度和权重 item平分屏幕 LayoutParams lp = (LayoutParams)tabView.getLayoutParams(); lp.width = 0; lp.weight = 1; tabView.setOnClickListener(tabClickListener); addView(tabView); if(i == mViewPager.getCurrentItem()) { iconView.transformPage(DEFALUT_SELECTED_ITEM); tabView.setSelected(true); textView.setTextColor(mTextSelectedColor); } } } /** * 内部ViewPager监听 * 外面想监听,自定义一个 */ private class ViewPagerListener implements ViewPager.OnPageChangeListener { //状态 private int mScrollState; @Override public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) { onViewPagerPageChanged(position,positionOffset); } @Override public void onPageSelected(int position) { for(int i = 0;i < getChildCount();i++) { //图标 BottomIconView bottomIcon = ((BottomIconView)mItemLayout[ i ].findViewById(R.id.bottom_tab_icon)); bottomIcon.transformPage(position == i ? 0 : 1); //文本 TextView bottomText = ((TextView)mItemLayout[ i ].findViewById(R.id.bottom_tab_text)); bottomText.setTextColor(position == i ? mTextSelectedColor : mTextNormalColor); } if(mScrollState == ViewPager.SCROLL_STATE_IDLE) { onViewPagerPageChanged(position,0f); } //设置选中项 for(int i = 0, size = getChildCount();i < size;i++) { getChildAt(i).setSelected(position == i); } } @Override public void onPageScrollStateChanged(int state) { mScrollState = state; } } /** * ViewPager的item改变 * * @param position * @param positionOffset */ private void onViewPagerPageChanged(int position,float positionOffset) { mSelectedPosition = position; mSelectionOffset = positionOffset; if(positionOffset == 0f && mLastPosition != mSelectedPosition) { mLastPosition = mSelectedPosition; } invalidate(); } /** * 绘制方法 * * @param canvas */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); final int childCount = getChildCount(); if(childCount > 0) { if(mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { View selectedTab = getChildAt(mSelectedPosition); View nextTab = getChildAt(mSelectedPosition + 1); View selectedIconView = ((LinearLayout)selectedTab).getChildAt(0); View nextIconView = ((LinearLayout)nextTab).getChildAt(0); View selectedTextView = ((LinearLayout)selectedTab).getChildAt(1); View nextTextView = ((LinearLayout)nextTab).getChildAt(1); //draw icon alpha if(selectedIconView instanceof BottomIconView && nextIconView instanceof BottomIconView) { ((BottomIconView)selectedIconView).transformPage(mSelectionOffset); ((BottomIconView)nextIconView).transformPage(1 - mSelectionOffset); } /** * 使用ArgbEvaluator类来控制文本的颜色渐变 */ //draw text color Integer selectedColor = (Integer)mColorEvaluator.evaluate(mSelectionOffset, mTextSelectedColor, mTextNormalColor); Integer nextColor = (Integer)mColorEvaluator.evaluate(1 - mSelectionOffset, mTextSelectedColor, mTextNormalColor); if(selectedTextView instanceof TextView && nextTextView instanceof TextView) { ((TextView)selectedTextView).setTextColor(selectedColor); ((TextView)nextTextView).setTextColor(nextColor); } } } } /** * Tab的Item点击 */ private class TabClickListener implements OnClickListener { @Override public void onClick(View v) { for(int i = 0;i < getChildCount();i++) { if(v == getChildAt(i)) { mViewPager.setCurrentItem(i,false); return; } } } } }
3.主布局(ViewPager+BottomIndicator)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.ViewPager android:id="@+id/id_viewPager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> </android.support.v4.view.ViewPager> <!--一定要加背景 android:background="@drawable/bg_tab_bottom"--> <jfsl.view.view.BottomIndicator android:id="@+id/id_bottom_indicator" android:layout_width="match_parent" android:layout_height="56dp" android:background="@drawable/bg_tab_bottom"> </jfsl.view.view.BottomIndicator> </LinearLayout>
4.tab item的布局(BottomIconView+TextView)
<?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" android:gravity="center" android:background="@null" android:orientation="vertical"> <jfsl.view.view.BottomIconView android:id="@+id/bottom_tab_icon" android:layout_width="32dp" android:layout_height="28dp" android:layout_gravity="center_horizontal" android:scaleType="fitCenter" /> <TextView android:id="@+id/bottom_tab_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textSize="12sp" /> </LinearLayout>
5.Tab的背景 layer-list可以将多个图片按照顺序层叠起来
背景不能去掉,去掉之后看不到渐变的效果
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:dither="true" android:shape="rectangle"> <solid android:color="#FFDADADA" /> </shape> </item> <item android:top="1px"> <shape android:dither="true" android:shape="rectangle"> <solid android:color="#FFFFFFFF" /> <padding android:top="1px" /> </shape> </item> </layer-list>
6.测试的Activity
package jfsl.view; import android.os.Bundle; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import jfsl.view.adapter.TopViewPagerAdapter; import jfsl.view.fragment.SimpleFragment; import jfsl.view.view.BottomIndicator; public class MainActivity extends AppCompatActivity { private ViewPager mViewPager; private List<String> mTitles = Arrays.asList("Fragment-->微信","Fragment-->通讯录","Fragment-->发现","Fragment-->我"); private List<SimpleFragment> mFragments = new ArrayList<>(); private FragmentPagerAdapter mPagerAdapter; private BottomIndicator mIndicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bottom_tab); initViews(); initDatas(); initEvent(); } private void initViews() { mViewPager = (ViewPager)findViewById(R.id.id_viewPager); mIndicator = (BottomIndicator)findViewById(R.id.id_bottom_indicator); } private void initDatas() { for(String title : mTitles) { mFragments.add(SimpleFragment.newInstance(title)); } mPagerAdapter = new TopViewPagerAdapter(getSupportFragmentManager(),this,mFragments); mViewPager.setAdapter(mPagerAdapter); mIndicator.setViewPager(mViewPager); } private void initEvent() { } }
7.adapter(ViewPager的Adapter)
package jfsl.view.adapter; import android.content.Context; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import java.util.List; import jfsl.view.fragment.SimpleFragment; /** * @version 1.0 * @aduthor JFSL * @date 2016/11/12 0012 */ public class TopViewPagerAdapter extends FragmentPagerAdapter { private Context mContext; private List<SimpleFragment> mFragments; public TopViewPagerAdapter(FragmentManager fm,Context context,List<SimpleFragment> fragments) { super(fm); mContext = context; mFragments = fragments; } @Override public Fragment getItem(int position) { return mFragments.get(position); } @Override public int getCount() { return mFragments.size(); } }
8.创建Fragment(根据String创建一个简单的Fragment)
package jfsl.view.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /**测试用的Fragment * @version 1.0 * @aduthor JFSL * @date 2016/11/12 0012 */ public class SimpleFragment extends Fragment { public static final String BUNDLE_TITLE = "title"; private String mTitle; @Nullable @Override public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) { Bundle bundle = getArguments(); if(bundle != null) mTitle = bundle.getString(BUNDLE_TITLE); TextView textView = new TextView(getActivity()); textView.setText(mTitle); textView.setGravity(Gravity.CENTER); return textView; } /** * 获取实例 * @param title * @return */ public static SimpleFragment newInstance(String title) { Bundle bundle = new Bundle(); bundle.putString(BUNDLE_TITLE,title); SimpleFragment fragment = new SimpleFragment(); fragment.setArguments(bundle); return fragment; } }
代码地址 http://114.215.171.206/14551100130/android_view/bottomtab.zip
图标素材( 放在xxhdpi)
本文原创发布于慕课网 ,转载请注明出处,谢谢合作!
相关标签:Android
相关文章推荐
- Android ViewPager实现滑动切换页面+底部tab点击切换页面(类微信首页)
- Android RadioGroup+ViewPager+ActionBar实现仿微信6.0界面(底部滑动菜单栏+导航栏)
- Android典型界面设计(8) ——ViewPager+PagerSlidingTabStrip实现双导航
- Android仿微信界面--使用viewpager实现(慕课网笔记)
- Android ViewPager和Fragment实现仿微信导航界面及滑动效果
- Android TabLayout、ViewPager实现顶部和底部Tab导航 点击滑动切换Tab页面
- Android底部Tab菜单栏(FragmentTabHost+ViewPager+Fragment)
- Android典型界面设计(6)——ActionBar Tab+ViewPager+Fagment实现滑动导航
- Android开发:顶部&底部Tab导航栏实现(TabLayout+ViewPager+Fragment)
- Android底部导航栏实现(四)之TabLayout+ViewPager
- ViewPager实现Tab/模仿微信界面
- Android - ViewPager + Fragment 实现仿微信界面
- 【Android界面实现】使用PagerSlidingTabStrip实现滑动标签同步的ViewPager效果
- Android三种实现Tab界面效果的方法,ViewPager + Fragment
- Android 用 TabLayout + ViewPager + Fragment 实现顶部、底部导航栏
- Android典型界面设计(6)——ActionBar Tab+ViewPager+Fagment实现滑动导航
- Android UI设计(引导界面):ViewPager之界面添加底部圆点与循环显示
- Android仿微信界面--使用FragmentPagerAdapter,viewpager实现(慕课网笔记)
- Android典型界面设计(8) ——ViewPager+PagerSlidingTabStrip实现双导航
- ViewPager+FragmentPagerAdapter实现Tab/模仿微信界面(推荐使用)