android自定义底部Tab导航UI,项目整体界面框架
共享一个自己在开发过程中搭建的android项目界面框架,便于提高开发效率。
主要功能
1.使用Button自定义底部Tab和Title
2.点击底部Tab后使用Fragment切换页面
3.主页使用ViewPager滚动显示新闻图片
4.自定义类处理Fragment重叠回退问题
一、自定义底部Tab类
/*******************************************************************************
*
* Copyright (c) Weaver Info Tech Co. Ltd
*
* TabView
*
* app.ui.widget.TabView.java
* TODO: File description or class description.
*
* @author: Administrator
* @changeLogs:
* 1.0.0: First created this class.
*
******************************************************************************/
package app.ui.widget;
import mobi.kuaidian.qunakao.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
/**
* @author Administrator
*
*/
public class TabView extends LinearLayout implements OnClickListener {
private OnTabChangeListener mOnTabChangedListener;
private int mState = 0;
private final Button mStateButton1;
private final Button mStateButton2;
private final Button mStateButton3;
private final Button mStateButton4;
public TabView(Context context) {
this(context, null);
}
public TabView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* @param context
* @param attrs
* @param defStyle
*/
public TabView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflate(context, R.layout.view_tab, this);
mStateButton1 = (Button) findViewById(R.id.button_state1);
mStateButton2 = (Button) findViewById(R.id.button_state2);
mStateButton3 = (Button) findViewById(R.id.button_state3);
mStateButton4 = (Button) findViewById(R.id.button_state4);
mStateButton1.setOnClickListener(this);
mStateButton2.setOnClickListener(this);
mStateButton3.setOnClickListener(this);
mStateButton4.setOnClickListener(this);
}
public void setOnTabChangeListener(OnTabChangeListener listener) {
mOnTabChangedListener = listener;
}
public void setCurrentTab(int index) {
switchState(index);
}
private void switchState(int state) {
if (mState == state) {
return;
} // else continue
mState = state;
mStateButton1.setSelected(false);
mStateButton2.setSelected(false);
mStateButton3.setSelected(false);
mStateButton4.setSelected(false);
Object tag = null;
switch (mState) {
case 0:
mStateButton1.setSelected(true);
tag = mStateButton1.getTag();
break;
case 1:
mStateButton2.setSelected(true);
tag = mStateButton2.getTag();
break;
case 2:
mStateButton3.setSelected(true);
tag = mStateButton3.getTag();
break;
case 3:
mStateButton4.setSelected(true);
tag = mStateButton4.getTag();
break;
default:
break;
}
if (mOnTabChangedListener != null) {
if (tag != null && mOnTabChangedListener != null) {
mOnTabChangedListener.onTabChange(tag.toString());
} else {
mOnTabChangedListener.onTabChange(null);
}
} // else ignored
}
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button_state1:
switchState(0);
break;
case R.id.button_state2:
switchState(1);
break;
case R.id.button_state3:
switchState(2);
break;
case R.id.button_state4:
switchState(3);
break;
default:
break;
}
}
public static interface OnTabChangeListener {
public void onTabChange(String tag);
}
}
二、对应底部Tab的XML布局文件
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0" >
<Button
android:id="@+id/button_state1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:button="@null"
android:drawableTop="@drawable/ic_message_selector"
android:gravity="center"
android:singleLine="true"
android:tag="message"
android:text="@string/text_tab_message"
android:textColor="@color/text_service_color"
android:textSize="14dp" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0" >
<Button
android:id="@+id/button_state2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:button="@null"
android:drawableTop="@drawable/ic_service_selector"
android:gravity="center"
android:singleLine="true"
android:tag="service"
android:text="@string/text_tab_service"
android:textColor="@color/text_service_color"
android:textSize="14dp" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0" >
<Button
android:id="@+id/button_state3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:button="@null"
android:drawableTop="@drawable/ic_profile_selector"
android:gravity="center"
android:singleLine="true"
android:tag="personal"
android:text="@string/text_tab_profile"
android:textColor="@color/text_service_color"
android:textSize="14dp" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0" >
<Button
android:id="@+id/button_state4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:button="@null"
android:drawableTop="@drawable/ic_setting_selector"
android:gravity="center"
android:singleLine="true"
android:tag="settings"
android:text="@string/text_tab_setting"
android:textColor="@color/text_service_color"
android:textSize="14dp" />
</FrameLayout>
三、在启动的Acitvity界面中使用自定义的Tab类
<?xml version="1.0" encoding="utf-8"?><include layout="@layout/layout_titlebar" />
<FrameLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0" />
<app.ui.widget.TabView
android:id="@+id/view_tab"
android:layout_width="match_parent"
android:layout_height="@dimen/header_height"
android:background="@color/tab_main_color" />
四、自定义类处理Fragment返回重叠的问题
/*******************************************************************************
*
* Copyright (c) Baina Info Tech Co. Ltd
*
* FragmentUtils
*
* app.util.FragmentUtils.java
* TODO: File description or class description.
*
* @changeLogs:
* 1.0.0: First created this class.
*
******************************************************************************/
package app.util;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
/**
* FragmentUtils of MyHealth
*
* @author qixiao
*/
public class FragmentUtils {
private FragmentUtils() {
}
public static Fragment replaceFragment(FragmentManager fragmentManager, int container,
Class<? extends Fragment> newFragment, Bundle args) {
return replaceFragment(fragmentManager, container, newFragment, args, false);
}
public static Fragment replaceFragment(FragmentManager fragmentManager, int container,
Fragment newFragment) {
return replaceFragment(fragmentManager, container, newFragment, false);
}
public static Fragment replaceFragment(FragmentManager fragmentManager, int container,
Class<? extends Fragment> newFragment, Bundle args, boolean addToBackStack) {
Fragment fragment = null;
// 构造新的Fragment
try {
fragment = newFragment.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (fragment != null) {
// 设置参数
if (args != null && !args.isEmpty()) {
final Bundle bundle = fragment.getArguments();
if (bundle != null) {
bundle.putAll(args);
} else {
fragment.setArguments(args);
}
}
// 替换
return replaceFragment(fragmentManager, container, fragment, addToBackStack);
} else {
return null;
}
}
public static Fragment replaceFragment(FragmentManager fragmentManager, int container,
Fragment newFragment, boolean addToBackStack) {
final FragmentTransaction transaction = fragmentManager.beginTransaction();
final String tag = newFragment.getClass().getSimpleName();
if (newFragment != null) {
transaction.replace(container, newFragment, tag);
}
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.commitAllowingStateLoss();
return newFragment;
}
public static Fragment switchFragment(FragmentManager fragmentManager, int container,
Fragment currentFragment, Class<? extends Fragment> newFragment, Bundle args) {
return switchFragment(fragmentManager, container, currentFragment, newFragment, args, false);
}
/**
*
* @param fragmentManager
* @param container
* @param currentFragment
* @param newFragment
* @param args 新Fragment的参数
* @param addToBackStack 这个操作是否加入栈中,如果要实现类似返回效果,则需要。
* @return 新显示的Fragment
*/
public static Fragment switchFragment(FragmentManager fragmentManager, int container,
Fragment currentFragment, Class<? extends Fragment> newFragment, Bundle args,
boolean addToBackStack) {
final FragmentTransaction transaction = fragmentManager.beginTransaction();
final String tag = newFragment.getSimpleName();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
// 如果在栈中找到相应的Fragment,则显示,否则重新生成一个
if (fragment != null) {
if (fragment != currentFragment) {
if (currentFragment != null) {
transaction.hide(currentFragment);
}
transaction.show(fragment);
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.commitAllowingStateLoss();
} else {
fragment.getArguments().putAll(args);
}
return fragment;
} else {
try {
fragment = newFragment.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
// 为新的Fragment添加参数
if (fragment != null) {
if (args != null && !args.isEmpty()) {
final Bundle bundle = fragment.getArguments();
if (bundle != null) {
bundle.putAll(args);
} else {
fragment.setArguments(args);
}
}
}
// 显示新的Fragment
if (currentFragment != null) {
transaction.hide(currentFragment);
}
transaction.add(container, fragment, tag);
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.commitAllowingStateLoss();
return fragment;
}
}
源码下载地址:https://download.csdn.net/download/wo0123456789wo/10847244