您的位置:首页 > 其它

自定义控件之-ViewPagerIndicator

2015-11-23 15:49 441 查看
经常使用ViewPagerIndicator,今天自己写了一个,记录下来作为以后参考使用。先看一下效果:



先贴出使用方法的代码:

MainActivity代码:

public class MainActivity extends Activity {
private ViewPager vp;
private Indicator1 indicator;
private String[] titles = { "新闻", "美女", "健康", "正能量", "特卖", "图片", "推荐",
"热点", "淄博", "视频", "社会", "小日本", "哈哈哈" };

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
indicator = (Indicator1) findViewById(R.id.indicator);
vp = (ViewPager) findViewById(R.id.vp);
indicator.setTitles(vp, titles, new OnTitleClickListener() {

@Override
public void onClick(int position) {
Toast.makeText(getApplicationContext(), titles[position],
Toast.LENGTH_SHORT).show();
}
});
vp.setAdapter(new PagerAdapter() {

@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
container.removeView((View) object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
TextView tv = new TextView(MainActivity.this);
tv.setGravity(Gravity.CENTER);
tv.setTextSize(40);
tv.setText(titles[position]);
container.addView(tv);
return tv;
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}

@Override
public int getCount() {
return titles.length;
}
});

}
}


activity_main.xml代码:

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

<com.example.myindicator.Indicator1
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.example.myindicator.Indicator1>

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

</LinearLayout>


上面都非常好理解,就是简单的使用,下面贴出Indicator1的代码:

public class Indicator1 extends LinearLayout implements OnPageChangeListener,
OnClickListener {

private int blockWidth;// 滑块宽度
private int blockHeight;// 滑块高度
private int blockTop;// 滑块顶部的坐标
private int blockLeft;// 滑块左上角的坐标
private String[] titles;// 保存导航的标题
private int titleLength;// 标题的个数
private int screenWidth;// 屏幕的宽度
private Paint paint;// 画滑块的画笔
private int visibleTitleCount = 4;// 默认的可见的标题栏数量
private boolean isFirst = true;// 是否是第一次加载
private OnTitleClickListener listener;// 点击某个标题的时间监听器
private ViewPager viewPager;// 关联的ViewPager

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

public Indicator1(Context context) {
super(context);
init(context);
}

private void init(Context context) {
// 将滑块的高度转成px,默人为10dp
blockHeight = dp2px(10);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);// 抗锯齿
paint.setColor(Color.RED);// 设置滑块颜色
setOrientation(LinearLayout.HORIZONTAL);// 水平布局
// 这里需要设置背景,否则onDraw不会调用;或者调用setWillNotDraw(false)方法,也会调用onDraw方法
setBackgroundColor(Color.TRANSPARENT);
setGravity(Gravity.CENTER_VERTICAL);// 设置对其方式为垂直居中
// 获取屏幕的宽度
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int left = blockLeft;
int top = blockTop;
int right = blockLeft + blockWidth;
int bottom = blockHeight + blockTop;
// 绘制滑块
canvas.drawRect(left, top, right, bottom, paint);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 计算每个滑块的宽度
blockWidth = screenWidth / visibleTitleCount;
titleLength = titles.length;// 给标题个数赋值
// 计算加入标题后的宽度,这里是总的标题的个数乘以每个标题的宽度
int width = titleLength * blockWidth;
int height = getMeasuredHeight();// 得到测量的高度
int topGap = dp2px(5);// 增加一个滑块和标题的距离,不然会挨太近不好看
blockTop = height + topGap;// 计算滑块顶部的位置
height = height + blockHeight;
// 重新测量宽高
setMeasuredDimension(width, height);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (isFirst) {
MarginLayoutParams lp = null;
TextView tv = null;
// 循环添加标题
for (int i = 0; i < titleLength; i++) {
tv = new TextView(getContext());
tv.setText(titles[i]);
tv.setTextSize(16);
tv.setTag(i);// 为了识别点击时间中点击了哪个位置的标题,这里将下表设置为tag
tv.setGravity(Gravity.CENTER);
lp = new MarginLayoutParams(blockWidth,
MarginLayoutParams.WRAP_CONTENT);
lp.leftMargin = i * blockWidth;
tv.setOnClickListener(this);// 设置点击事件
addView(tv, lp);
}
isFirst = false;
}
}

/**
* 为Indicator设置标题栏
*
* @param viewPager
*            关联的ViewPager
* @param titles
*            标题数组
* @param listener
*            OnTitleClickListener
*/
public void setTitles(ViewPager viewPager, String[] titles,
OnTitleClickListener listener) {
if (viewPager == null) {
throw new IllegalArgumentException("ViewPager不能为空");
}
if (titles == null || titles.length == 0) {
throw new IllegalArgumentException("titles不能为空,或者长度必须大于0");
}
this.viewPager = viewPager;
this.titles = titles;
viewPager.setOnPageChangeListener(this);
this.listener = listener;
}

@Override
public void onPageScrollStateChanged(int position) {

}

@Override
public void onPageScrolled(int position, float fraction, int arg2) {
// 计算滑块的左边位置
blockLeft = (int) ((position + fraction) * blockWidth);
moveTitle(position, fraction);
invalidate();
}

@Override
public void onPageSelected(int position) {

}

/**
* 移动标题
*
* @param position
*            当前viewPager的位置
* @param fraction
*            百分比
*/
private void moveTitle(int position, float fraction) {
// 如果滑块移动到屏幕可视标题个数的倒数第1个,并且标题个数大于一屏的可是个数,则开始移动整个标题栏
if (position >= visibleTitleCount - 2
&& titleLength > visibleTitleCount) {
if (position >= titles.length - 2) {
// 如果移动到了最后一个标题,则停止移动,防止后面出现空白
return;
}
// 计算移动的距离
int temp = (position - (visibleTitleCount - 2)) * blockWidth
+ (int) (blockWidth * fraction);
scrollTo(temp, 0);
}
}

/**
* 将dp转成px
*
* @param dp
* @return
*/
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
getResources().getDisplayMetrics());
}

@Override
public void onClick(View v) {
// 得到对应的点击标题的下标
int position = (Integer) v.getTag();
// 计算点击的标题对应的滑块需要滑动的左边位置
blockLeft = (int) (position * blockWidth);
// 将ViewPager设置显示到这个标题对应的位置
viewPager.setCurrentItem(position);
// 回调OnTitleClickListener中的onClick方法
if (listener != null) {
listener.onClick(position);
}
// 重绘
invalidate();
}

/**
* 某个标题被点击的监听器
*
* @author Administrator
*
*/
public interface OnTitleClickListener {
/**
* 返回对应的下标
*
* @param position
*/
public void onClick(int position);
}

}


这里简直实现了一些功能,还可以加一些自定义属性等使功能更加丰富。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  自定义控件