1. 程式人生 > >android自定義底部Tab導航UI,專案整體介面框架

android自定義底部Tab導航UI,專案整體介面框架

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佈局檔案

<merge xmlns:android="http://schemas.android.com/apk/res/android" >
 
    <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>
 
</merge>

三、在啟動的Acitvity介面中使用自定義的Tab類

<?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:orientation="vertical" >
 
    <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" />
 
</LinearLayout>

四、自定義類處理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