自定义控件之-ViewPagerIndicator
2015-11-23 15:49
441 查看
经常使用ViewPagerIndicator,今天自己写了一个,记录下来作为以后参考使用。先看一下效果:
先贴出使用方法的代码:
MainActivity代码:
activity_main.xml代码:
上面都非常好理解,就是简单的使用,下面贴出Indicator1的代码:
这里简直实现了一些功能,还可以加一些自定义属性等使功能更加丰富。
先贴出使用方法的代码:
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); } }
这里简直实现了一些功能,还可以加一些自定义属性等使功能更加丰富。
相关文章推荐
- 麻雀虽小五脏俱全 Dojo自定义控件应用
- WinForm自定义控件应用实例
- C++ 自定义控件的移植问题
- 百度地图自定义控件分享
- 用javascript添加控件自定义属性解析
- Android自定义控件之仿优酷菜单
- Android自定义表格控件满足人们对视觉的需求
- VC++ 自定义控件的建立及使用方法
- asp.net 自定义控件实现无刷新上传图片,立即显示缩略图,保存图片缩略图
- C#自定义控件添加右键菜单的方法
- asp.net DropDownList自定义控件,让你的分类更清晰
- 如何通过javascript操作web控件的自定义属性
- 自定义模板列在 PostBack 后消失的问题
- android自定义控件实例
- android中播放gif动画之二
- android面试常见的handler机制 AIDL机制 高级控件UI 内存优化
- Android Zxing条码扫描自定义控件(附代码)
- 仿滴滴打车底部滑动条代码逻辑实现
- winform控件显示及闪烁问题
- Android:ViewDragHelper学习