zoukankan      html  css  js  c++  java
  • Android UI设计框架[1]: ViewPager+Fragment实现底部图标文字的导航栏(IconTabPageIndicator)

    版权声明:

    本文参考“Android开发技巧——实现底部图标文字的导航栏”一文,地址为:http://blog.csdn.net/maosidiaoxian/article/details/38864679

    基础知识:

    1) Fragment是在Android 3.0(API 11)版本引入的,如果使用的是3.0之前的系统,需要先导入android-support-v4的jar包才能使用Fragment功能。

    实现思路:

    1) 先定义两个接口:

    IconPagerAdapter

    public interface IconPagerAdapter {
        int getIconResId(int index);
        int getCount();
    }

    PageIndicator

    import android.support.v4.view.ViewPager;
     
    public interface PageIndicator extends ViewPager.OnPageChangeListener {
        void setViewPager(ViewPager view);
        void setViewPager(ViewPager view, int initialPosition);
        void setCurrentItem(int item);
        void setOnPageChangeListener(ViewPager.OnPageChangeListener listener);
        void notifyDataSetChanged();
    }

    2) 新建一个类IconTabPageIndicator,继承LinearLayout并实现PageIndicator接口:

    import android.content.Context;
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import com.localbuyapp.R;
    
    import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
    
    /**
     * User: Geek_Soledad(msdx.android@qq.com)
     * Date: 2014-08-27
     * Time: 09:20
     * FIXME
     */
    public class IconTabPageIndicator extends LinearLayout implements PageIndicator {
        /**
         * Title text used when no title is provided by the adapter.
         */
        private static final CharSequence EMPTY_TITLE = "";
    
        /**
         * Interface for a callback when the selected tab has been reselected.
         */
        public interface OnTabReselectedListener {
            /**
             * Callback when the selected tab has been reselected.
             *
             * @param position Position of the current center item.
             */
            void onTabReselected(int position);
        }
    
        private Runnable mTabSelector;
    
        private final View.OnClickListener mTabClickListener = new View.OnClickListener() {
            public void onClick(View view) {
                TabView tabView = (TabView) view;
                final int oldSelected = mViewPager.getCurrentItem();
                final int newSelected = tabView.getIndex();
                mViewPager.setCurrentItem(newSelected);
                if (oldSelected == newSelected && mTabReselectedListener != null) {
                    mTabReselectedListener.onTabReselected(newSelected);
                }
            }
        };
    
        private final LinearLayout mTabLayout;
    
        private ViewPager mViewPager;
        private ViewPager.OnPageChangeListener mListener;
    
        private int mSelectedTabIndex;
    
        private OnTabReselectedListener mTabReselectedListener;
    
        private int mTabWidth;
    
        public IconTabPageIndicator(Context context) {
            this(context, null);
        }
    
        public IconTabPageIndicator(Context context, AttributeSet attrs) {
            super(context, attrs);
            setHorizontalScrollBarEnabled(false);
    
            mTabLayout = new LinearLayout(context, null, R.attr.tabPageIndicator);
            addView(mTabLayout, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        }
    
        public void setOnTabReselectedListener(OnTabReselectedListener listener) {
            mTabReselectedListener = listener;
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            final int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
            final boolean lockedExpanded = widthMode == View.MeasureSpec.EXACTLY;
    
            final int childCount = mTabLayout.getChildCount();
    
            if (childCount > 1 && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
                mTabWidth = MeasureSpec.getSize(widthMeasureSpec) / childCount;
            } else {
                mTabWidth = -1;
            }
    
            final int oldWidth = getMeasuredWidth();
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            final int newWidth = getMeasuredWidth();
    
            if (lockedExpanded && oldWidth != newWidth) {
                // Recenter the tab display if we're at a new (scrollable) size.
                setCurrentItem(mSelectedTabIndex);
            }
        }
    
        private void animateToTab(final int position) {
            final View tabView = mTabLayout.getChildAt(position);
            if (mTabSelector != null) {
                removeCallbacks(mTabSelector);
            }
            mTabSelector = new Runnable() {
                public void run() {
                    final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
                    mTabSelector = null;
                }
            };
            post(mTabSelector);
        }
    
        @Override
        public void onAttachedToWindow() {
            super.onAttachedToWindow();
            if (mTabSelector != null) {
                // Re-post the selector we saved
                post(mTabSelector);
            }
        }
    
        @Override
        public void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            if (mTabSelector != null) {
                removeCallbacks(mTabSelector);
            }
        }
    
        private void addTab(int index, CharSequence text, int iconResId) {
            final TabView tabView = new TabView(getContext());
            tabView.mIndex = index;
            tabView.setOnClickListener(mTabClickListener);
            tabView.setText(text);
    
            if (iconResId > 0) {
                tabView.setIcon(iconResId);
            }
    
            mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, MATCH_PARENT, 1));
        }
    
        @Override
        public void onPageScrollStateChanged(int arg0) {
            if (mListener != null) {
                mListener.onPageScrollStateChanged(arg0);
            }
        }
    
        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
            if (mListener != null) {
                mListener.onPageScrolled(arg0, arg1, arg2);
            }
        }
    
        @Override
        public void onPageSelected(int arg0) {
            setCurrentItem(arg0);
            if (mListener != null) {
                mListener.onPageSelected(arg0);
            }
        }
    
        @Override
        public void setViewPager(ViewPager view) {
            if (mViewPager == view) {
                return;
            }
            if (mViewPager != null) {
                mViewPager.setOnPageChangeListener(null);
            }
            final PagerAdapter adapter = view.getAdapter();
            if (adapter == null) {
                throw new IllegalStateException("ViewPager does not have adapter instance.");
            }
            mViewPager = view;
            view.setOnPageChangeListener(this);
            notifyDataSetChanged();
        }
    
        public void notifyDataSetChanged() {
            mTabLayout.removeAllViews();
            PagerAdapter adapter = mViewPager.getAdapter();
            IconPagerAdapter iconAdapter = null;
            if (adapter instanceof IconPagerAdapter) {
                iconAdapter = (IconPagerAdapter) adapter;
            }
            final int count = adapter.getCount();
            for (int i = 0; i < count; i++) {
                CharSequence title = adapter.getPageTitle(i);
                if (title == null) {
                    title = EMPTY_TITLE;
                }
                int iconResId = 0;
                if (iconAdapter != null) {
                    iconResId = iconAdapter.getIconResId(i);
                }
                addTab(i, title, iconResId);
            }
            if (mSelectedTabIndex > count) {
                mSelectedTabIndex = count - 1;
            }
            setCurrentItem(mSelectedTabIndex);
            requestLayout();
        }
    
        @Override
        public void setViewPager(ViewPager view, int initialPosition) {
            setViewPager(view);
            setCurrentItem(initialPosition);
        }
    
        @Override
        public void setCurrentItem(int item) {
            if (mViewPager == null) {
                throw new IllegalStateException("ViewPager has not been bound.");
            }
            mSelectedTabIndex = item;
            mViewPager.setCurrentItem(item);
    
            final int tabCount = mTabLayout.getChildCount();
            for (int i = 0; i < tabCount; i++) {
                final View child = mTabLayout.getChildAt(i);
                final boolean isSelected = (i == item);
                child.setSelected(isSelected);
                if (isSelected) {
                    animateToTab(item);
                }
            }
        }
        
        /**
         * For fragment slide
         */
        @Override
        public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
            mListener = listener;
        }
    
        private class TabView extends LinearLayout {
            private int mIndex;
            private ImageView mImageView;
            private TextView mTextView;
    
            public TabView(Context context) {
                super(context, null, R.attr.tabView);
                View view = View.inflate(context, R.layout.tab_view, null);
                mImageView = (ImageView) view.findViewById(R.id.tab_image);
                mTextView = (TextView) view.findViewById(R.id.tab_text);
    //            this.addView(view);
                this.addView(view, MATCH_PARENT, MATCH_PARENT);
            }
    
            @Override
            public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
                // Re-measure if we went beyond our maximum size.
                if (mTabWidth > 0) {
                    super.onMeasure(MeasureSpec.makeMeasureSpec(mTabWidth, MeasureSpec.EXACTLY),
                            heightMeasureSpec);
                }
            }
    
            public void setText(CharSequence text) {
                mTextView.setText(text);
            }
    
            public void setIcon(int resId) {
                if (resId > 0) {
                    mImageView.setImageResource(resId);
                }
            }
    
            public int getIndex() {
                return mIndex;
            }
        }
    }

    这里内部类TabView直接使用布局文件来实现(tab_view.xml代码这里未贴出)。

    3) 在Activity中使用IconTabPageIndicator(直接包含在Activity的布局文件中):

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        xmlns:tools="http://schemas.android.com/tools"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        tools:context=".MyActivity">  
      
        <xxx.IconTabPageIndicator  
            android:id="@+id/indicator"  
            android:layout_alignParentBottom="true"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"/>  
        <android.support.v4.view.ViewPager  
            android:layout_above="@id/indicator"  
            android:id="@+id/view_pager"  
            android:layout_width="match_parent"  
            android:layout_height="match_parent"/>  
    </RelativeLayout>
    import android.app.ActionBar;
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.ViewConfiguration;
    import android.widget.SearchView;
    import android.widget.SearchView.OnQueryTextListener;
    import android.widget.ShareActionProvider;
    import android.widget.Toast;
    
    import com.xxx.R;
    import com.viewpagerindicator.IconPagerAdapter;
    import com.viewpagerindicator.IconTabPageIndicator;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class MainActivity extends FragmentActivity{
        // Debugging
        private static final String TAG = "MainActivity";
        private static final boolean D = true;
        
        // Member fields
        private ViewPager mViewPager;
        private IconTabPageIndicator mIndicator;
        private FragmentPagerAdapter mAdapter;  
        private List<BaseFragment> mFragments = new ArrayList<BaseFragment>(); 
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            // 隐藏ActionBar
            ActionBar actionBar = getActionBar();  
            actionBar.hide();
            
            // 控件初始化
            initViews();
        }
    
        private void initViews() {
            // 实例化ViewPager
            mViewPager = (ViewPager) findViewById(R.id.view_pager);
            
            // 实例化TabPageIndicator
            mIndicator = (IconTabPageIndicator) findViewById(R.id.indicator);
            
            // 初始化Fragments
            mFragments = initFragments();
            
            // 实例化FragmentPageAdapter
            mAdapter = new FragmentAdapter(mFragments, getSupportFragmentManager());
            
            // ViewPager的adapter,使得fragments与ViewPager关联 
            mViewPager.setAdapter(mAdapter); 
            
            // 设置ViewPager与TabPageIndicator关联
            mIndicator.setViewPager(mViewPager);
        }
        
        private List<BaseFragment> initFragments() {
            List<BaseFragment> fragments = new ArrayList<BaseFragment>();
            
            // 添加Fragments到存放Fragment的List
            IndexFragment indexFragment = new IndexFragment();
            indexFragment.setTitle("首页");
            indexFragment.setIconId(R.drawable.tab_user_selector);
            fragments.add(indexFragment);
    
            NearbyFragment nearbyFragment = new NearbyFragment();
            nearbyFragment.setTitle("附近");
            nearbyFragment.setIconId(R.drawable.tab_record_selector);
            fragments.add(nearbyFragment);
    
            MyinfoFragment myFragment = new MyinfoFragment();
            myFragment.setTitle("我的");
            myFragment.setIconId(R.drawable.tab_user_selector);
            fragments.add(myFragment);
            
            return fragments;
        }
        
        class FragmentAdapter extends FragmentPagerAdapter implements IconPagerAdapter {    
            private List<BaseFragment> mFragments;
    
            public FragmentAdapter(List<BaseFragment> fragments, FragmentManager fm) {
                super(fm);
                mFragments = fragments;
            }
    
            @Override
            public Fragment getItem(int i) {
                return mFragments.get(i);
            }
    
            @Override
            public int getIconResId(int index) {
                return mFragments.get(index).getIconId();
            }
    
            @Override
            public int getCount() {
                return mFragments.size();
            }
    
            @Override
            public CharSequence getPageTitle(int position) {
                return mFragments.get(position).getTitle();
            }
        }
    
    }

    4) 可以看到MainActivity中,与ViewPager关联的Fragment List不是Fragment类型的,而是BaseFragment(继承自Fragment),是因为

    BaseFragment需要多加两个属性title和iconId,title对应TabView的文字,iconId对应TabView的图片索引:

    import com.xxx.R;
    
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    /**
     * User: Geek_Soledad(msdx.android@qq.com)
     * Date: 2014-08-27
     * Time: 09:01
     * FIXME
     */
    public class BaseFragment extends Fragment {
        private String title;
        private int iconId;
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public int getIconId() {
            return iconId;
        }
    
        public void setIconId(int iconId) {
            this.iconId = iconId;
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment, null, false);
            TextView textView = (TextView) view.findViewById(R.id.text);
            textView.setText(getTitle());
            return view;
        }
    }

    5) 再定义每个ViewPager对应的Fragment(继承自BaseFragment),如:

    import android.content.Intent;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    
    /**
     * User: Jay(jayhust@gmail.com)
     * Date: 2015-01-29
     * Time: 11:40
     * Notes: Extentable fragments: Fragment/DialogFragment/ListFragment/PreferenceFragment
     * FIXME
     */
    public class IndexFragment extends BaseFragment {
        // Member field
        private Button btn_index_test;
        
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_index, null, false); 
            return view;
        }
        
        @Override  
        public void onActivityCreated(Bundle savedInstanceState) {  
            super.onActivityCreated(savedInstanceState);  
            Button btn_index_test = (Button) getActivity().findViewById(R.id.btn_index_test);  
            btn_index_test.setOnClickListener(new OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    TextView textView = (TextView) getActivity().findViewById(R.id.text_index_hint);  
                    Toast.makeText(getActivity(), textView.getText(), Toast.LENGTH_LONG).show();  
                }  
            });  
        } 
    }

    其对应的布局文件fragment_index.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:background="#eee"
        tools:context=".MainActivity"> 
        
        <TextView
            android:id="@+id/text_index_hint"
            android:textAppearance="@android:style/TextAppearance.Large"
            android:text="Index Fragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        
        <Button 
            android:id="@+id/btn_index_test"
            android:layout_below="@id/text_index_hint"
            android:layout_alignRight="@id/text_index_hint"
            android:paddingTop="10dp"
            android:text="index test"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        
    </RelativeLayout>
  • 相关阅读:
    0314:翻车总结
    机器人系统仿真(十一)——URDF集成Gazebo
    机器人系统仿真(十)——arbotix控制机器人运动
    机器人系统仿真(九)——xacro+摄像头+雷达传感器
    机器人系统仿真(八)——xacro小车底盘模型案例
    机器人系统仿真(七)——xacro语法详解
    机器人系统仿真(六)——xacro基本语法
    机器人系统仿真(五)——URDF工具
    机器人系统仿真(四)——四轮圆柱状机器人模型
    C++去除字符串空格和tab
  • 原文地址:https://www.cnblogs.com/jayhust/p/4261553.html
Copyright © 2011-2022 走看看