使用 ViewPager 和 RadioGroup 封装的一个导航控件

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
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.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup; import java.lang.reflect.Field;
import java.util.List; /**
* 使用 ViewPager 和 RadioGroup 封装的一个导航控件<p/>
* 有2种布局方式:<br/>
* 1. ViewPager + 图标在上文本在下的tab 栏<br/>
* 2. 仅有文本的tab + ViewPager<br/>
* 只需要调用 viewPagerIndicator.bind(fragments, indicatorEntityList) 方法<br/>
* 其中如果indicatorEntityList 中如果传入图标,就是布局方式1,否则就是布局方式2<br/>
* <br/> Fragment需要用v4的 ,Activity需要继承自 FragmentActivity
*/
public class ViewPagerIndicator extends LinearLayout implements RadioGroup.OnCheckedChangeListener { /**
* 需要的实体类<p/>
* 如果只设置tab的名字, 则不会显示图标<br/>
* 如果设置了图标,会显示对应的图标
*/
public static class IndicatorEntity {
/** tab的名字 */
String indicator;
/** tab的选中状态和非选中状态的图标 */
int selectedRes, unSelectedRes;
boolean isShowIconEnable; /**
* @param indicator tab的名字
*/
public IndicatorEntity(String indicator) {
this.indicator = indicator;
isShowIconEnable = false;
} /**
* @param indicator tab的名字
* @param selectedRes tab的选中状态的图标
* @param unSelectedRes tab的非选中状态的图标
*/
public IndicatorEntity(String indicator, int selectedRes, int unSelectedRes) {
this.indicator = indicator;
this.selectedRes = selectedRes;
this.unSelectedRes = unSelectedRes;
isShowIconEnable = true;
}
} /** 选中和非选中tab的前景色, 也就是字体颜色 */
public static final int selected_fg_Color = 0xff0000ff, unselected_fg_Color = 0xFF000000;
/** 选中和非选中tab的背景色 */
public static final int selected_bg_Color = 0xff00ff00, unselected_bg_Color = 0xcccccccc;
/** 分隔线的颜色 */
public static final int divide_line_color = 0xFF000000;
/** 指示条的颜色 */
public static final int indicator_color = 0xFF0000FF; // 是否允许ViewPager 滑动
private boolean scrollable = true;
// radioGroup 即tab 栏的高度,可以使用 DimenUtil 传入dp单位的高度
private int radioGroupShowIconHeight = 54 * 3;
private int radioGroupGoneIconHeight = 36 * 3;
private int radioGroupHeight = radioGroupShowIconHeight;
private Context context;
// 屏幕宽度
private int mScreenWidth;
private RadioGroup mRadioGroup;
private MyViewPager mViewPager;
private List<IndicatorEntity> indicatorEntityList;
// 是否显示图标
private boolean isShowIconEnable = true; /** 上一次的指示条的位置 */
private int lastSelectedIndex;
/** 指示条控件 */
private View indicatorView; public ViewPagerIndicator(Context context) {
this(context, null);
} public ViewPagerIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
this.setOrientation(VERTICAL);
// 获取屏幕宽度
DisplayMetrics outMetrics = new DisplayMetrics();
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
} /** 设置是否允许ViewPager 滑动 */
public void setScrollable(boolean scrollable) {
this.scrollable = scrollable;
} /**
* 绑定页面<br/>
* fragments 和 indicatorEntityList 的数量必须一致
* <p/>
*
* @param fragments 绑定的fragment
* @param indicatorEntityList 绑定的tab的名字或者图标
*/
public void bind(List<Fragment> fragments, List<IndicatorEntity> indicatorEntityList) {
if (fragments == null || fragments.size() <= 0 || indicatorEntityList == null || indicatorEntityList.size() <= 0 || fragments.size() != indicatorEntityList.size())
return;
this.indicatorEntityList = indicatorEntityList;
isShowIconEnable = indicatorEntityList.get(0).isShowIconEnable;
initViews();
mViewPager.setFragments(fragments);
for (int i = 0; i < indicatorEntityList.size(); i++) {
mRadioGroup.addView(generateRadioButton(i));
}
//设置第一个tab为选中状态
((RadioButton) mRadioGroup.getChildAt(0)).setChecked(true);
mViewPager.setCurrentItem(0);
} /** 分隔线 */
private View generateDivideLine() {
View view = new View(context);
view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
view.setBackgroundColor(divide_line_color);
return view;
} private void initViewPager() {
mViewPager = new MyViewPager(context);
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
layoutParams.weight = 1;
mViewPager.setLayoutParams(layoutParams);
mViewPager.setId((int) (System.currentTimeMillis() % 10000)); // Id 必须设置,不然会有 NotFoundException 异常
mViewPager.addOnPageChangeListener(mOnPageChangeListener);
} private void initRadioGroup() {
radioGroupHeight = isShowIconEnable ? radioGroupShowIconHeight : radioGroupGoneIconHeight;
mRadioGroup = new RadioGroup(context);
mRadioGroup.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, radioGroupHeight));
mRadioGroup.setOrientation(HORIZONTAL);
mRadioGroup.setOnCheckedChangeListener(this);
} /** 初始化需要添加的添加控件以及事件 */
private void initViews() {
initViewPager();
initRadioGroup();
if (isShowIconEnable) {
this.addView(mViewPager);
this.addView(generateDivideLine());
this.addView(mRadioGroup);
} else {
this.addView(mRadioGroup);
initIndicatorView();
this.addView(indicatorView);
this.addView(generateDivideLine());
this.addView(mViewPager);
}
} private void initIndicatorView() {
indicatorView = new View(context);
LayoutParams layoutParams = new LayoutParams((int) (mScreenWidth / indicatorEntityList.size() * 0.8f), radioGroupHeight / 10);
layoutParams.setMargins((int) (mScreenWidth / indicatorEntityList.size() * 0.1f), -layoutParams.height, 0, 0);
indicatorView.setLayoutParams(layoutParams);
indicatorView.setBackgroundColor(indicator_color);
} private RadioButton generateRadioButton(int index) {
RadioButton rb = new RadioButton(context);
// 均分宽度,TODO 不知道这里用 weight 为什么无法显示出来
rb.setLayoutParams(new LayoutParams(mScreenWidth / indicatorEntityList.size(), ViewGroup.LayoutParams.MATCH_PARENT));
rb.setId(index);
rb.setGravity(Gravity.CENTER);
rb.setText(indicatorEntityList.get(index).indicator);
rb.setPadding(0, radioGroupHeight / 10, 0, radioGroupHeight / 10); // 设置上下边距,不至于挨着边
// rb.setCompoundDrawablePadding(2); // 文本和图片的间距
rb.setButtonDrawable(android.R.color.transparent); // 去掉圆圈圈
return rb;
} /** 处理tab切换以后的ui状态 */
private void setSelectedItem(int position) {
for (int i = 0; i < indicatorEntityList.size(); i++) {
((RadioButton) mRadioGroup.getChildAt(i)).setTextColor(i == position ? selected_fg_Color : unselected_fg_Color); // 字体颜色
if (isShowIconEnable) {
Drawable drawable = ContextCompat.getDrawable(context, i == position ? indicatorEntityList.get(i).selectedRes : indicatorEntityList.get(i).unSelectedRes);
drawable.setBounds(0, 0, radioGroupHeight / 2, radioGroupHeight / 2);
((RadioButton) mRadioGroup.getChildAt(i)).setCompoundDrawables(null, drawable, null, null);// 图标
} else {
mRadioGroup.getChildAt(i).setBackgroundColor(i == position ? selected_bg_Color : unselected_bg_Color); // 背景颜色
}
}
// 设置 indicatorView 动画 TODO indicatorView 动画是在 ViewPager 滑动动画完成后执行的,不是和 ViewPager 同步的
if (indicatorView != null && lastSelectedIndex != position) {
ObjectAnimator.ofFloat(indicatorView, "TranslationX", lastSelectedIndex * mScreenWidth / indicatorEntityList.size(), position * mScreenWidth / indicatorEntityList.size())
.setDuration(300).start();
lastSelectedIndex = position;
}
} @Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (mViewPager != null) mViewPager.setCurrentItem(checkedId);
setSelectedItem(checkedId);
} private ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
} @Override
public void onPageSelected(int position) {
setSelectedItem(position);
} @Override
public void onPageScrollStateChanged(int state) {
}
}; /**
* 自定义ViewPager<p/>
* Override onTouchEvent() 和 onInterceptTouchEvent() 是为了屏蔽滑动事件<br/>
* Override setCurrentItem() 是为了在点击非相邻的tab时,避免中间滚动太多<br/>
*/
class MyViewPager extends ViewPager { private Context context;
private List<Fragment> mFragments;
private MyFragmentPagerAdapter mAdapter; public MyViewPager(Context context) {
this(context, null);
} public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
} /**
* 如果Activity不是继承 FragmentActivity,会crash掉
*
* @param fragments
*/
public void setFragments(List<Fragment> fragments) {
if (!(context instanceof FragmentActivity)) {
throw new ClassCastException("activity need to extents FragmentActivity");
}
mAdapter = new MyFragmentPagerAdapter(((FragmentActivity) context).getSupportFragmentManager());
this.setAdapter(mAdapter);
mFragments = fragments;
mAdapter.notifyDataSetChanged();
} @Override
public boolean onTouchEvent(MotionEvent ev) {
return scrollable && super.onTouchEvent(ev);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return scrollable && super.onInterceptTouchEvent(ev);
} @Override
public void setCurrentItem(int item) {
try {
Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
mFirstLayout.setAccessible(true);
mFirstLayout.set(this, true);
getAdapter().notifyDataSetChanged();
super.setCurrentItem(item);
} catch (Exception e) {
e.printStackTrace();
}
} public class MyFragmentPagerAdapter extends FragmentPagerAdapter { public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
} @Override
public Fragment getItem(int position) {
return mFragments == null ? null : mFragments.get(position);
} @Override
public int getCount() {
return mFragments == null ? 0 : mFragments.size();
}
}
}
}
上一篇:64位与32位编程的数据类型区别(C/C++)


下一篇:[转][MSSQL]SQL Server 2008 记住密码功能