上篇博文【android开发之Fragment利用Bundle保存状态】用到滑动切换底部Tab,由于上篇博文的重点是保存Fragment状态,并没有说明,今天来解释一下。
关于高仿微信6.0滑动Tab网上有很多,大部分情况下是自定义View,在OnDraw()进行绘制,本博客的Tab没有自定义View,只是android官方提供的控件进行组合【查看微信布局源码也是这样做的】,性能和实用性请各位同学自测。
微信布局如下图:
按着微信布局进行分析,每个Tab就是一个RelativeLayout,那么我们就可以继承RelativeLayout,添加子控件ImageView和Textview;由于需要实现滑动变色,所以实现双层ImageView和TextView,分别设置绿色图标和灰色图标;
自定义属性attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WeiXinTabLayoutStyleable">
<attr name="tabChecked" format="boolean" />
<attr name="tabTitle" format="string" />
<attr name="tabTitleSize" format="dimension" />
<attr name="tabTitleColor" format="color" />
<attr name="tabIcon" format="reference" />
<attr name="tabIconOver" format="reference" />
<attr name="tabLableColor" format="color" />
<attr name="tabLableText" format="string" />
<attr name="tabLableTextSize" format="dimension" />
<attr name="tabLablebackground" format="color"/>
</declare-styleable>
</resources>
代码以及讲解如下:
package cc.mn.tab;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* User: 山野书生(1203596603@qq.com)
* Date: 2015-11-27
* Time: 19:32
* Version 1.0
*/
public class TabView extends RelativeLayout{
private Context mContext;
//标题
private TextView titleTextView;
private String titleText;
private int titleColor;
private static final int titleTextViewID = 10001;
private int titleNolColor = Color.GRAY;
//第二层标题
private TextView titleOverTextView;
private static final int titleOverTextViewID = 100011;
//图标
private ImageView iconImageView;
private static final int iconImageViewID = 10002;
private Drawable tabIcon;
//第二层图标
private ImageView iconOverImageView;
private static final int iconOverImageViewID = 100022;
private Drawable tabIconOver;
//是否已经被选中
private boolean isChecked = true;
//透明度
private float mAlpha = 1f;
private String tag = TabView.class.getSimpleName();
public TabView(Context context) {
this(context, null);
}
public TabView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TabView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取自定义属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WeiXinTabLayoutStyleable);
//是否是选中状态
isChecked = ta.getBoolean(R.styleable.WeiXinTabLayoutStyleable_tabChecked, false);
//标题的颜色,内容
titleColor = ta.getColor(R.styleable.WeiXinTabLayoutStyleable_tabTitleColor, Color.GRAY);
titleText = ta.getString(R.styleable.WeiXinTabLayoutStyleable_tabTitle);
//图标图片
tabIcon = ta.getDrawable(R.styleable.WeiXinTabLayoutStyleable_tabIcon);
tabIconOver = ta.getDrawable(R.styleable.WeiXinTabLayoutStyleable_tabIconOver);
ta.recycle();
mContext = context;
initViews();
}
/**
* 初始化控件
* */
private void initViews(){
RelativeLayout.LayoutParams titleLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
titleLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
titleLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
//第二层标题
titleOverTextView = new TextView(mContext);
titleOverTextView.setId(titleOverTextViewID);
titleOverTextView.setLayoutParams(titleLayoutParams);
this.addView(titleOverTextView);
//标题
titleTextView = new TextView(mContext);
titleTextView.setId(titleTextViewID);
titleTextView.setLayoutParams(titleLayoutParams);
this.addView(titleTextView);
//图标LayoutParams
RelativeLayout.LayoutParams iconLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
iconLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
iconLayoutParams.addRule(RelativeLayout.ABOVE, titleTextViewID);
//第二层图标
iconOverImageView = new ImageView(mContext);
iconOverImageView.setId(iconOverImageViewID);
iconOverImageView.setLayoutParams(iconLayoutParams);
this.addView(iconOverImageView);
//图标
iconImageView = new ImageView(mContext);
iconImageView.setId(iconImageViewID);
iconImageView.setLayoutParams(iconLayoutParams);
this.addView(iconImageView);
//设置数据,并刷新
refreshData();
}
/**
* 设置选中状态
* */
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
setCheckedData();
}
/**
* 滑动时改变颜色
* */
public void onScrolling(float alpha){
mAlpha = alpha;
onScrollSetData();
}
/**
* 设置图标
* */
private void setTabIconData(){
iconImageView.setImageDrawable(tabIcon);
if(isChecked){
iconImageView.setAlpha(1-mAlpha);
} else {
iconImageView.setAlpha(mAlpha);
}
}
/**
* 设置第二层图标
* */
private void setTabIconOverData(){
iconOverImageView.setImageDrawable(tabIconOver);
if(isChecked){
iconOverImageView.setAlpha(mAlpha);
} else {
iconOverImageView.setAlpha(1-mAlpha);
}
}
/**
* 滑动时设置图标透明度以及文字透明度
* */
private void onScrollSetData(){
//设置图标透明度
iconImageView.setAlpha(1-mAlpha);
iconOverImageView.setAlpha(mAlpha);
//设置标题透明度
titleTextView.setAlpha(1-mAlpha);
titleOverTextView.setAlpha(mAlpha);
}
/**
* 设置标题数据
* */
private void setTitleData(){
titleTextView.setText(titleText);
titleTextView.setTextColor(titleNolColor);
if(isChecked){
titleTextView.setAlpha(1-mAlpha);
} else {
titleTextView.setAlpha(mAlpha);
}
}
/**
* 设置第二层标题数据
* */
private void setTitleOverData(){
titleOverTextView.setText(titleText);
titleOverTextView.setTextColor(titleColor);
if(isChecked){
titleOverTextView.setAlpha(mAlpha);
} else {
titleOverTextView.setAlpha(1-mAlpha);
}
}
/**
* 选中之后重新设置数据
* */
private void setCheckedData(){
refreshData();
}
/**
* 设置完数据之后刷新
* */
private void refreshData(){
mAlpha = 1.0f;
setTitleData();
setTitleOverData();
setTabIconData();
setTabIconOverData();
}
public String getTitleText() {
return titleText;
}
public void setTitleText(String titleText) {
this.titleText = titleText;
}
public Drawable getTabIcon() {
return tabIcon;
}
public void setTabIcon(Drawable tabIcon) {
this.tabIcon = tabIcon;
}
public boolean isChecked() {
return isChecked;
}
public ImageView getIconImageView() {
return iconImageView;
}
}
关键代码:
/**
* 设置图标
* */
private void setTabIconData(){
iconImageView.setImageDrawable(tabIcon);
if(isChecked){
iconImageView.setAlpha(1-mAlpha);
} else {
iconImageView.setAlpha(mAlpha);
}
}
/**
* 设置第二层图标
* */
private void setTabIconOverData(){
iconOverImageView.setImageDrawable(tabIconOver);
if(isChecked){
iconOverImageView.setAlpha(mAlpha);
} else {
iconOverImageView.setAlpha(1-mAlpha);
}
}
/**
* 滑动时设置图标透明度以及文字透明度
* */
private void onScrollSetData(){
//设置图标透明度
iconImageView.setAlpha(1-mAlpha);
iconOverImageView.setAlpha(mAlpha);
//设置标题透明度
titleTextView.setAlpha(1-mAlpha);
titleOverTextView.setAlpha(mAlpha);
}
滑动的时候会调用ViewPager.OnPageChangeListener()里的方法
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
//positionOffset滑动的百分比;
根据百分比设置Alpha值,完成颜色渐变
Ok,这样我们就初步完成了TabView,按着微信的布局,我们还需要一个Linearlayout,接下来,我们继续实现,新建TabGroupView继承LinearLayout,代码以及讲解如下:
package cc.mn.tab;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
/**
* User: 山野书生(1203596603@qq.com)
* Date: 2015-11-27
* Time: 20:35
* Version 1.0
*/
public class TabGroupView extends LinearLayout {
private OnItemClickListener onItemClickListener;
private List<TabView> tabLayouts;
private String tag = TabGroupView.class.getSimpleName();
public TabGroupView(Context context) {
this(context, null);
}
public TabGroupView(Context context, AttributeSet attrs) {
super(context, attrs);
tabLayouts = new ArrayList<>();
this.setOrientation(HORIZONTAL); //设置默认为水平布局
}
/**
* 选中某一个
* */
public void setCurrentItem(int item){
changeItem();
TabView tabLayout = tabLayouts.get(item);
tabLayout.setChecked(true);
}
/**
* @param position 当前界面索引
* @param positionOffset 滑动的百分比
* */
public void onPageScrolling(int position, float positionOffset) {
if(positionOffset>0){
TabView tabLayout = tabLayouts.get(position);
tabLayout.onScrolling(1-positionOffset);
if(position+1 < tabLayouts.size()){
TabView nextTabLayout = tabLayouts.get(position+1);
nextTabLayout.onScrolling(positionOffset);
}
}
}
/**
* 设置监听器
* */
private void initListener(){
int count = this.getChildCount();
for(int i=0; i<count; i++){
final TabView tabLayout = (TabView)this.getChildAt(i);
tabLayouts.add(tabLayout);
final int finalI = i;
tabLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
changeItem(); //清除选中状态
tabLayout.setChecked(true);
if(onItemClickListener!=null){
onItemClickListener.onClick(finalI, tabLayout);
}
}
});
}
}
/**
* 清除选中状态
* */
private void changeItem(){
for(TabView tabLayout:tabLayouts){
tabLayout.setChecked(false);
}
}
/**
* 设置每个Item的监听事件
* */
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
initListener();
}
/**
* 点击事件
* */
public interface OnItemClickListener{
void onClick(int position, TabView tabLayout);
}
/**
* 设置只能水平布局
* */
@Override
public void setOrientation(int orientation) {
super.setOrientation(HORIZONTAL);
}
}
Ok,高仿微信滑动Tab完成,开始应用;
首先布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<cc.mn.tab.TabGroupView
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="@color/text"
android:layout_alignParentBottom="true"
android:id="@+id/group_tab_layout"
android:paddingTop="5dp"
android:paddingBottom="5dp"
>
<cc.mn.tab.TabView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/tab_main"
app:tabTitle="微信"
app:tabTitleColor="@color/tab_bg_green"
app:tabIcon="@mipmap/chats"
app:tabIconOver="@mipmap/chats_green"
app:tabLablebackground="@color/item_tab_bg"
app:tabChecked="true"
/>
<cc.mn.tab.TabView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:tabTitle="通讯录"
app:tabTitleColor="@color/tab_bg_green"
app:tabLableColor="@color/text"
app:tabIcon="@mipmap/contacts"
app:tabIconOver="@mipmap/contacts_green"
/>
<cc.mn.tab.TabView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/tab_friedns"
app:tabTitle="发现"
app:tabTitleColor="@color/tab_bg_green"
app:tabIcon="@mipmap/discover"
app:tabIconOver="@mipmap/discover_green"
/>
<cc.mn.tab.TabView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
app:tabTitle="我"
app:tabTitleColor="@color/tab_bg_green"
app:tabIcon="@mipmap/about_me"
app:tabIconOver="@mipmap/about_me_green"
/>
</cc.mn.tab.TabGroupView>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/group_tab_layout"
android:id="@+id/view_pager"
/>
</RelativeLayout>
在Activity应用:
package cc.mntabdemo;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.List;
import cc.mn.tab.TabGroupView;
import cc.mn.tab.TabView;
public class MainActivity extends AppCompatActivity implements TabGroupView.OnItemClickListener{
private TabGroupView group_tab_layout;
private ViewPager view_pager;
private List<ContentFragment> list = new ArrayList<>();
private int mPosition = 0;
private String tag = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list.add(new ContentFragment("微信"));
list.add(new ContentFragment("通讯录"));
list.add(new ContentFragment("发现"));
list.add(new ContentFragment("我"));
view_pager = (ViewPager)findViewById(R.id.view_pager);
group_tab_layout = (TabGroupView)findViewById(R.id.group_tab_layout);
group_tab_layout.setOnItemClickListener(this);
view_pager.setAdapter(pagerAdapter);
view_pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
group_tab_layout.onPageScrolling(position, positionOffset);
}
@Override
public void onPageSelected(int position) {
mPosition = position;
group_tab_layout.setCurrentItem(mPosition);
}
@Override
public void onPageScrollStateChanged(int state) { //状态
}
});
}
//创建适配器
private FragmentPagerAdapter pagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
};
@Override
public void onClick(int position, TabView tabLayout) {
Log.i(tag, "选中的tablayout=" + position);
view_pager.setCurrentItem(position, false); //取消动画
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
运行截图:
OK,基本与微信一样,性能和实用性请同学们自测,代码;最新代码添加了BadgeView,下篇博文进行讲解!
关于TabView也可以通过代码进行添加,像Tabhost的一样使用。