您的位置:首页 > 移动开发 > 微信开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐