Android 仿iOS的UISegmentControl标题栏以及内容切换

相信大家都见过iOS的UISegmentControl标题导航栏吧,如果没有,见到下图,你会恍然大悟,原来是这个啊:
iOS UISegmentControl效果图

我们这里要实现的就是类似这种效果,本项目实现的效果可以手指在屏幕左右滑动切换,也可以通过手动点击标题栏中的任一项进行快速切换。先上效果图:
@我
私信
评论
通知

现在来谈谈设计思路。

首先在整个布局中,上方的整个标题栏是自定义的LinearLayout,标题栏下方的内容区其实是一个ViewPager,这个ViewPager容器中容纳四个Fragment。
自定义的LinearLayout标题栏是直接继承LinearLayout,然后动态添加四个TextView,分别是tvAtMe,tvPrivateLetter,tvComment,tvNotice,样式使用自定义的drawable文件。同时这四个TextView都设置了点击监听,当某一个TextView被点击就会刷新四个TextView的选中状态,使得各个TextView切换对应选中状态下的样式,同时会通知整个标题栏下方的ViewPager切换到对应内容的Fragment,实现点击切换效果。ViewPager自身也实现了活动切换的效果。

下面是自定义标题栏的代码:

/**
 * Created by MarRn on 2016/6/25.
 */
public class SegmentView extends LinearLayout {

    //四个标题框
    private TextView tvAtMe;
    private TextView tvPrivateLetter;
    private TextView tvComment;
    private TextView tvNotice;

    //Fragment容器,容纳四个标题框各自对应的Fragment
    private ViewPager mViewPager;

    //标题栏的点击监听
    private OnSegmentViewClickListener listener;

    public SegmentView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
        setTextViewListener();
    }


    public SegmentView(Context context) {
        super(context);
        init();
        setTextViewListener();
    }

    public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
        SegmentPagerChangerListener pagerChangerListener = new SegmentPagerChangerListener();
        mViewPager.setOnPageChangeListener(pagerChangerListener);
    }

    private void init() {
        //创建四个标题框
        tvAtMe = new TextView(getContext());
        tvPrivateLetter = new TextView(getContext());
        tvComment = new TextView(getContext());
        tvNotice = new TextView(getContext());

        //设置属性
        tvAtMe.setLayoutParams(new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1));
        tvPrivateLetter.setLayoutParams(new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1));
        tvComment.setLayoutParams(new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1));
        tvNotice.setLayoutParams(new LayoutParams(0, LayoutParams.WRAP_CONTENT, 1));
        tvAtMe.setGravity(Gravity.CENTER);
        tvPrivateLetter.setGravity(Gravity.CENTER);
        tvComment.setGravity(Gravity.CENTER);
        tvNotice.setGravity(Gravity.CENTER);
        tvAtMe.setPadding(3, 6, 3, 6);
        tvPrivateLetter.setPadding(3, 6, 3, 6);
        tvComment.setPadding(3, 6, 3, 6);
        tvNotice.setPadding(3, 6, 3, 6);
        setSegmentTextSize(19);

        //从drawable中提取xml设置的颜色
        XmlPullParser xrp = 
 getResources().getXml(R.drawable.seg_text_color_selector);
        try {
            ColorStateList csl = ColorStateList.createFromXml(getResources(), xrp);
            tvAtMe.setTextColor(csl);
            tvPrivateLetter.setTextColor(csl);
            tvComment.setTextColor(csl);
            tvNotice.setTextColor(csl);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //设置四个标题框的样式
        tvAtMe.setBackgroundResource(R.drawable.seg_0);
    tvPrivateLetter.setBackgroundResource(R.drawable.seg_1);
        tvComment.setBackgroundResource(R.drawable.2);
        tvNotice.setBackgroundResource(R.drawable.3);
        tvAtMe.setSelected(true);

        //将四个标题框加入RelativeLayout容器中
        this.addView(tvAtMe);
        this.addView(tvPrivateLetter);
        this.addView(tvComment);
        this.addView(tvNotice);
    }

    /**
     * 设置四个标题框的点击监听
     */
    private void setTextViewListener(){

        tvAtMe.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //设置四个标题框的选中状态
                if (tvAtMe.isSelected()) {
                    return;
                }
                tvAtMe.setSelected(true);
                tvPrivateLetter.setSelected(false);
                tvComment.setSelected(false);
                tvNotice.setSelected(false);
                if (listener != null) {
                    listener.onSegmentViewClick(tvAtMe, 0);
                }
            }
        });
        tvPrivateLetter.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (tvPrivateLetter.isSelected()) {
                    return;
                }
                tvPrivateLetter.setSelected(true);
                tvComment.setSelected(false);
                tvNotice.setSelected(false);
                tvAtMe.setSelected(false);
                if (listener != null) {
               listener.onSegmentViewClick(tvPrivateLetter, 1);
                }
            }
        });

        tvComment.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (tvComment.isSelected()) {
                    return;
                }
                tvComment.setSelected(true);
                tvAtMe.setSelected(false);
                tvPrivateLetter.setSelected(false);
                tvNotice.setSelected(false);
                if (listener != null) {
                    listener.onSegmentViewClick(tvNotice, 2);
                }
            }
        });

        tvNotice.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (tvNotice.isSelected()) {
                    return;
                }
                tvNotice.setSelected(true);
                tvAtMe.setSelected(false);
                tvPrivateLetter.setSelected(false);
                tvComment.setSelected(false);
                if (listener != null) {
                    listener.onSegmentViewClick(tvNotice, 3);
                }
            }
        });
    }

    /**
     * 设置四个标题框的文本内容
     * @param tvAtMeName
     * @param tvPrivateLetterName
     * @param tvCommentName
     * @param tvNoticeName
     */
    public void setText(String tvAtMeName,String tvPrivateLetterName,String tvCommentName,String tvNoticeName) {
        tvAtMe.setText(tvAtMeName);
        tvPrivateLetter.setText(tvPrivateLetterName);
        tvComment.setText(tvCommentName);
        tvNotice.setText(tvNoticeName);
    }

    /**
     * 设置四个标题框的文本字体大小 单位dp
     * @param dp
     */
    public void setSegmentTextSize(int dp) {
        tvAtMe.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
        tvPrivateLetter.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
        tvComment.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
        tvNotice.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dp);
    }

    public void setOnSegmentViewClickListener(OnSegmentViewClickListener listener) {
        this.listener = listener;
    }


    /**
     * 自定义监听接口,监听标题栏的点击位置,使得ViewPager可以设置当前要显示的Fragment
     */
    public interface OnSegmentViewClickListener{
        /**
         *
         * @param v
         * @param position 0代表@我 1代表私信 2代表评论 3代表通知
         */
        void onSegmentViewClick(View v,int position);
    }


    /**
     * viewPager的切换监听
     */
    public class SegmentPagerChangerListener implements ViewPager.OnPageChangeListener {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }

        @Override
        public void onPageSelected(int position) {
            if(position == 0) {
                tvAtMe.setSelected(true);
                tvPrivateLetter.setSelected(false);
                tvComment.setSelected(false);
                tvNotice.setSelected(false);
            } else if(position == 1) {
                tvPrivateLetter.setSelected(true);
                tvComment.setSelected(false);
                tvNotice.setSelected(false);
                tvAtMe.setSelected(false);
            } else if(position == 2) {
                tvComment.setSelected(true);
                tvNotice.setSelected(false);
                tvAtMe.setSelected(false);
                tvPrivateLetter.setSelected(false);
            }else{
                tvNotice.setSelected(true);
                tvAtMe.setSelected(false);
                tvPrivateLetter.setSelected(false);
                tvComment.setSelected(false);
            }
        }
    }
}

R.drawable.seg_text_color_selector的样式代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_selected="true" android:color="#FFFFFF"/>
    <item android:color="#0079FF"/>
</selector>

R.drawable.seg_0的样式代码如下(R.drawable.seg_1,R.drawable.seg_2,R.drawable.seg_3的样式也是一样代码,分别设置四个是方便对其中任何一个做修改,做出更多的设计):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_selected="true">
        <shape >
            <stroke android:color="#0079FF" android:width="1dp"/>
            <solid android:color="#0079FF"/>
            <corners android:topLeftRadius="0dp" android:bottomLeftRadius="0dp" android:topRightRadius="0dp" android:bottomRightRadius="0dp"/>
        </shape>
    </item>
    <item>
        <shape >
            <stroke android:color="#0079FF" android:width="1dp"/>
            <solid android:color="#FFFFFF"/>
            <corners android:topLeftRadius="0dp" android:bottomLeftRadius="0dp" android:topRightRadius="0dp" android:bottomRightRadius="0dp"/>
        </shape>
    </item>
</selector>

主界面Activity的代码如下所示:

/**
 * Created by MarRn on 2016/6/25.
 */
public class TestSegmentControlActivity extends FragmentActivity {

    private ViewPager mViewPager;
    private SegmentView segment;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_segment_control);

        initView();

    }


    private void initView(){
        mViewPager = (ViewPager)findViewById(R.id.viewpager);
        segment = (SegmentView)findViewById(R.id.segment);
        SegmentClickListener segmentClickListener = new SegmentClickListener();
        FragmentPagerAdapter mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public int getCount() {
                return 4;
            }

            @Override
            public Fragment getItem(int arg0) {
                //创建Fragment
                Fragment fm1 = new TestFragment1();
                Fragment fm2 = new TestFragment2();
                Fragment fm3 = new TestFragment3();
                Fragment fm4 = new TestFragment4();
                if (arg0 == 0) {
                    return fm1;
                } else if (arg0 == 1) {
                    return fm2;
                } else if (arg0 == 2) {
                    return fm3;
                } else {
                    return fm4;
                }
            }
        };
        mViewPager.setAdapter(mAdapter);
        segment.setText("@我","私信","评论","通知");
        segment.setViewPager(mViewPager);
        segment.setOnSegmentViewClickListener(segmentClickListener);
    }

    private class SegmentClickListener implements SegmentView.OnSegmentViewClickListener {

        @Override
        public void onSegmentViewClick(View v, int position) {
            switch (position) {
                //设置当前要显示的Fragment
                case 0 :
                    mViewPager.setCurrentItem(position);
                    break;
                case 1:
                    mViewPager.setCurrentItem(position);
                    break;
                case 2:
                    mViewPager.setCurrentItem(position);
                    break;
                case 3:
                    mViewPager.setCurrentItem(position);
                    break;
                default:
                    break;
            }
        }
    }
}

主界面的layout文件代码:

<?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" >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="53dp"
        android:background="#ffff">
        <com.marrn.segmentcontrol.SegmentView
            android:id="@+id/segment"
            android:layout_width="343dp"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            />
    </RelativeLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>

四个Fragment的代码一致,因为注重在效果的实现,所以Fragment中也没有写实际的内容逻辑代码,这里以TestFragment1的代码为例:

/**
 * Created by MarRn on 2016/6/25.
 */
public class TestFragment1 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup 
    container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.test_fragment_1,null);

        if(savedInstanceState!=null){
            //如果数据在fragment被回收时有重写onSaveInstanceState()方法进行保存,
            // 则保存的数据从savedInstanceState中取出

        }
        return view;
    }


    //数据保存自己实现,保存在Bundle中,防止Fragment被回收之后,重新创建导致用户之前的操作数据丢失,导致用户体验不好
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }
}

晚上的博客编辑器好像变笨了,代码都不能进行调节,看着我自己都难受,大家辛苦将就着看吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值