相信大家都见过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);
}
}
晚上的博客编辑器好像变笨了,代码都不能进行调节,看着我自己都难受,大家辛苦将就着看吧~