我是不会滴,但是看了一些大神写的,我修改了一下,大家可以参照参照
一,自定义Mytabpageindicator,直接贴代码了,具体的在代码中有注释
1 package com.wangy.mytabpageindicator.Mytabpageindicator; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.Color; 7 import android.graphics.CornerPathEffect; 8 import android.graphics.Paint; 9 import android.graphics.Path; 10 import android.support.v4.view.ViewPager; 11 import android.util.AttributeSet; 12 import android.util.DisplayMetrics; 13 import android.util.Log; 14 import android.util.TypedValue; 15 import android.view.Gravity; 16 import android.view.View; 17 import android.view.WindowManager; 18 import android.widget.LinearLayout; 19 import android.widget.TextView; 20 21 import com.wangy.mytabpageindicator.R; 22 import com.wangy.mytabpageindicator.util.ScreenUtils; 23 24 import java.util.List; 25 26 /** 27 * Created by xhb on 2016/11/30. 28 */ 29 public class Mytabpageindicator extends LinearLayout { 30 /** 31 * 绘制三角形的画笔 32 */ 33 private Paint mPaint; 34 /** 35 * path构成一个三角形 36 */ 37 private Path mPath; 38 /** 39 * 三角形的宽度 40 */ 41 private int mTriangleWidth; 42 /** 43 * 三角形的高度 44 */ 45 private int mTriangleHeight; 46 47 /** 48 * 三角形的宽度为单个Tab的1/6 49 */ 50 private static final float RADIO_TRIANGEL = 1.0f / 6; 51 /** 52 * 三角形的最大宽度 53 */ 54 private final int DIMENSION_TRIANGEL_WIDTH = (int) (getScreenWidth() / 3 * RADIO_TRIANGEL); 55 56 /** 57 * 初始时,三角形指示器的偏移量 58 */ 59 private int mInitTranslationX; 60 /** 61 * 手指滑动时的偏移量 62 */ 63 private float mTranslationX; 64 65 /** 66 * 默认的Tab数量 67 */ 68 private static final int COUNT_DEFAULT_TAB = 4; 69 /** 70 * tab数量 71 */ 72 private int mTabVisibleCount = COUNT_DEFAULT_TAB; 73 74 /** 75 * tab上的内容 76 */ 77 private List<String> mTabTitles; 78 /** 79 * 与之绑定的ViewPager 80 */ 81 public ViewPager mViewPager; 82 83 /** 84 * 标题正常时的颜色 85 */ 86 private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF; 87 /** 88 * 标题选中时的颜色 89 */ 90 private static final int COLOR_TEXT_HIGHLIGHTCOLOR = 0xFFFFFFFF; 91 92 public Mytabpageindicator(Context context) 93 { 94 this(context, null); 95 } 96 97 public Mytabpageindicator(Context context, AttributeSet attrs) 98 { 99 super(context, attrs); 100 101 // 获得自定义属性,tab的数量 102 TypedArray a = context.obtainStyledAttributes(attrs, 103 R.styleable.ViewPagerIndicator); 104 mTabVisibleCount = a.getInt(R.styleable.ViewPagerIndicator_item_count, 105 COUNT_DEFAULT_TAB); 106 if (mTabVisibleCount < 0) 107 mTabVisibleCount = COUNT_DEFAULT_TAB; 108 a.recycle(); 109 110 // 初始化画笔 111 mPaint = new Paint(); 112 mPaint.setAntiAlias(true); 113 mPaint.setColor(Color.parseColor("#ffffffff")); 114 mPaint.setStyle(Paint.Style.FILL); 115 mPaint.setPathEffect(new CornerPathEffect(3)); 116 117 } 118 119 /** 120 * 绘制指示器 121 */ 122 @Override 123 protected void dispatchDraw(Canvas canvas) 124 { 125 canvas.save(); 126 // 画笔平移到正确的位置 127 canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1); 128 canvas.drawPath(mPath, mPaint); 129 canvas.restore(); 130 131 super.dispatchDraw(canvas); 132 } 133 134 /** 135 * 初始化三角形的宽度 136 */ 137 @Override 138 protected void onSizeChanged(int w, int h, int oldw, int oldh) 139 { 140 super.onSizeChanged(w, h, oldw, oldh); 141 mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGEL);// 1/6 of 142 // width 143 mTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth); 144 145 // // 初始化三角形 146 // initTriangle(); 147 //初始化矩形 148 initrectangle(); 149 150 // 初始时的偏移量 151 mInitTranslationX = getWidth() / mTabVisibleCount / 2 - mTriangleWidth 152 / 2; 153 } 154 155 /** 156 * 设置可见的tab的数量 157 * 158 * @param count 159 */ 160 public void setVisibleTabCount(int count) 161 { 162 this.mTabVisibleCount = count; 163 } 164 165 /** 166 * 设置tab的标题内容 可选,可以自己在布局文件中写死 167 * 168 * @param datas 169 */ 170 public void setTabItemTitles(List<String> datas) 171 { 172 // 如果传入的list有值,则移除布局文件中设置的view 173 if (datas != null && datas.size() > 0) 174 { 175 this.removeAllViews(); 176 this.mTabTitles = datas; 177 178 for (String title : mTabTitles) 179 { 180 // 添加view 181 addView(generateTextView(title)); 182 } 183 // 设置item的click事件 184 setItemClickEvent(); 185 } 186 187 } 188 189 /** 190 * 对外的ViewPager的回调接口 191 * 192 * @author zhy 193 * 194 */ 195 public interface PageChangeListener 196 { 197 public void onPageScrolled(int position, float positionOffset, 198 int positionOffsetPixels); 199 200 public void onPageSelected(int position); 201 202 public void onPageScrollStateChanged(int state); 203 } 204 205 // 对外的ViewPager的回调接口 206 private PageChangeListener onPageChangeListener; 207 208 // 对外的ViewPager的回调接口的设置 209 public void setOnPageChangeListener(PageChangeListener pageChangeListener) 210 { 211 this.onPageChangeListener = pageChangeListener; 212 } 213 214 // 设置关联的ViewPager 215 public void setViewPager(ViewPager mViewPager, int pos) 216 { 217 this.mViewPager = mViewPager; 218 219 mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() 220 { 221 @Override 222 public void onPageSelected(int position) 223 { 224 // 设置字体颜色高亮 225 resetTextViewColor(); 226 highLightTextView(position); 227 228 // 回调 229 if (onPageChangeListener != null) 230 { 231 onPageChangeListener.onPageSelected(position); 232 } 233 } 234 235 @Override 236 public void onPageScrolled(int position, float positionOffset, 237 int positionOffsetPixels) 238 { 239 // 滚动 240 scroll(position, positionOffset); 241 242 // 回调 243 if (onPageChangeListener != null) 244 { 245 onPageChangeListener.onPageScrolled(position, 246 positionOffset, positionOffsetPixels); 247 } 248 249 } 250 251 @Override 252 public void onPageScrollStateChanged(int state) 253 { 254 // 回调 255 if (onPageChangeListener != null) 256 { 257 onPageChangeListener.onPageScrollStateChanged(state); 258 } 259 260 } 261 }); 262 // 设置当前页 263 mViewPager.setCurrentItem(pos); 264 // 高亮 265 highLightTextView(pos); 266 } 267 268 /** 269 * 高亮文本 270 * 271 * @param position 272 */ 273 protected void highLightTextView(int position) 274 { 275 View view = getChildAt(position); 276 if (view instanceof TextView) 277 { 278 ((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHTCOLOR); 279 } 280 281 } 282 283 /** 284 * 重置文本颜色 285 */ 286 private void resetTextViewColor() 287 { 288 for (int i = 0; i < getChildCount(); i++) 289 { 290 View view = getChildAt(i); 291 if (view instanceof TextView) 292 { 293 ((TextView) view).setTextColor(COLOR_TEXT_NORMAL); 294 } 295 } 296 } 297 298 /** 299 * 设置点击事件 300 */ 301 public void setItemClickEvent() 302 { 303 int cCount = getChildCount(); 304 for (int i = 0; i < cCount; i++) 305 { 306 final int j = i; 307 View view = getChildAt(i); 308 view.setOnClickListener(new OnClickListener() 309 { 310 @Override 311 public void onClick(View v) 312 { 313 mViewPager.setCurrentItem(j); 314 } 315 }); 316 } 317 } 318 319 /** 320 * 根据标题生成我们的TextView 321 * 322 * @param text 323 * @return 324 */ 325 private TextView generateTextView(String text) 326 { 327 TextView tv = new TextView(getContext()); 328 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 329 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 330 lp.width = getScreenWidth() / mTabVisibleCount; 331 tv.setGravity(Gravity.CENTER); 332 tv.setTextColor(COLOR_TEXT_NORMAL); 333 tv.setText(text); 334 tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); 335 tv.setLayoutParams(lp); 336 return tv; 337 } 338 339 /** 340 * 初始化三角形指示器 341 */ 342 private void initTriangle() 343 { 344 mPath = new Path(); 345 346 mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2)); 347 mPath.moveTo(0, 0); 348 mPath.lineTo(mTriangleWidth, 0); 349 mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight); 350 mPath.close(); 351 } 352 353 /** 354 * 指示器跟随手指滚动,以及容器滚动 355 * 356 * @param position 357 * @param offset 358 */ 359 public void scroll(int position, float offset) 360 { 361 /** 362 * <pre> 363 * 0-1:position=0 ;1-0:postion=0; 364 * </pre> 365 */ 366 // 不断改变偏移量,invalidate 367 mTranslationX = getWidth() / mTabVisibleCount * (position + offset); 368 369 int tabWidth = getScreenWidth() / mTabVisibleCount; 370 371 // 容器滚动,当移动到倒数最后一个的时候,开始滚动,这边的1 也可以改成2 372 if (offset > 0 && position >= (mTabVisibleCount - 1) 373 && getChildCount() > mTabVisibleCount) 374 { 375 if (mTabVisibleCount != 1) 376 { 377 this.scrollTo((position - (mTabVisibleCount - 1)) * tabWidth 378 + (int) (tabWidth * offset), 0); 379 } else 380 // 为count为1时 的特殊处理 381 { 382 this.scrollTo( 383 position * tabWidth + (int) (tabWidth * offset), 0); 384 } 385 } 386 387 invalidate(); 388 } 389 390 /** 391 * 设置布局中view的一些必要属性;如果设置了setTabTitles,布局中view则无效 392 */ 393 @Override 394 protected void onFinishInflate() 395 { 396 Log.e("TAG", "onFinishInflate"); 397 super.onFinishInflate(); 398 399 int cCount = getChildCount(); 400 401 if (cCount == 0) 402 return; 403 404 for (int i = 0; i < cCount; i++) 405 { 406 View view = getChildAt(i); 407 LinearLayout.LayoutParams lp = (LayoutParams) view 408 .getLayoutParams(); 409 lp.weight = 0; 410 lp.width = getScreenWidth() / mTabVisibleCount; 411 view.setLayoutParams(lp); 412 } 413 // 设置点击事件 414 setItemClickEvent(); 415 416 } 417 418 /** 419 * 获得屏幕的宽度 420 * 421 * @return 422 */ 423 public int getScreenWidth() 424 { 425 WindowManager wm = (WindowManager) getContext().getSystemService( 426 Context.WINDOW_SERVICE); 427 DisplayMetrics outMetrics = new DisplayMetrics(); 428 wm.getDefaultDisplay().getMetrics(outMetrics); 429 return outMetrics.widthPixels; 430 } 431 432 // /** 433 // * path构成一个三角形 434 // */ 435 // private Path mPath; 436 // /** 437 // * 三角形的宽度 438 // */ 439 // private int mTriangleWidth; 440 // /** 441 // * 三角形的高度 442 // */ 443 // private int mTriangleHeight; 444 // 445 // /** 446 // * 三角形的宽度为单个Tab的1/6 447 // */ 448 // private static final float RADIO_TRIANGEL = 1.0f / 6; 449 // /** 450 // * 三角形的最大宽度 451 // */ 452 // private final int DIMENSION_TRIANGEL_WIDTH = (int) (getScreenWidth() / 3 * RADIO_TRIANGEL); 453 // 454 // 455 // /** 456 // * 初始时,三角形指示器的偏移量 457 // */ 458 // private int mInitTranslationX; 459 // /** 460 // * 手指滑动时的偏移量 461 // */ 462 // private float mTranslationX; 463 // /** 464 // * 默认的Tab数量 465 // */ 466 // private static final int COUNT_DEFAULT_TAB = 4; 467 // /** 468 // * tab数量 469 // */ 470 // private int count = COUNT_DEFAULT_TAB; 471 // /** 472 // * tab上的内容 473 // */ 474 // private List<String> mTabTitles; 475 // /** 476 // * 与之绑定的ViewPager 477 // */ 478 // public ViewPager mViewPager; 479 // /** 480 // * 标题正常时的颜色 481 // */ 482 // private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF; 483 // /** 484 // * 标题选中时的颜色 485 // */ 486 // private static final int COLOR_TEXT_HIGHLIGHTCOLOR = 0xFFFFFFFF; 487 // private Paint mpaint; 488 // 489 // public Mytabpageindicator(Context context) { 490 // this(context, null); 491 // } 492 // 493 // public Mytabpageindicator(Context context, AttributeSet attrs) { 494 // super(context, attrs); 495 // 496 // TypedArray arry = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator); 497 // 498 // count = arry.getInt(R.styleable.ViewPagerIndicator_item_count, COUNT_DEFAULT_TAB); 499 // if (count < 0) { 500 // count = COUNT_DEFAULT_TAB; 501 // } 502 // arry.recycle(); 503 // // 初始化画笔 504 // mpaint = new Paint(); 505 // //抗锯齿 506 // mpaint.setAntiAlias(true); 507 // mpaint.setColor(Color.RED); 508 // //设置知否填充 509 // mpaint.setStyle(Paint.Style.FILL); 510 // //连线之间转角处的圆滑程度 511 // mpaint.setPathEffect(new CornerPathEffect(3)); 512 // } 513 // 514 // /** 515 // * 设置布局中view的一些必要属性;如果设置了setTabTitles,布局中view则无效 516 // */ 517 // @Override 518 // protected void onFinishInflate() { 519 // super.onFinishInflate(); 520 // int childcount = getChildCount(); 521 // if (childcount == 0) 522 // return; 523 // for (int i = 0; i < childcount; i++) { 524 // View view = getChildAt(i); 525 // LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams(); 526 // lp.weight = 0; 527 // lp.width = getScreenWidth() / count; 528 // view.setLayoutParams(lp); 529 // } 530 // 531 // // 设置点击事件 532 // setItemClickEvent(); 533 // } 534 // 535 // // 设置点击事件 536 // private void setItemClickEvent() { 537 // int childcount = getChildCount(); 538 // for (int i = 0; i < childcount; i++) { 539 // final int j = i; 540 // View view = getChildAt(i); 541 // view.setOnClickListener(new OnClickListener() { 542 // @Override 543 // public void onClick(View v) { 544 // mViewPager.setCurrentItem(j); 545 // } 546 // }); 547 // } 548 // } 549 // 550 // /** 551 // * 初始化三角形的宽度 552 // * onSizeChanged,我们主要是确定三角形的宽度和Path去构造这个三角形。 553 // * <p/> 554 // * 默认的我们的三角形的底边的宽度为,每个Tab宽度的1/6;当然有个上限是 (int) (getScreenWidth() / 3 * RADIO_TRIANGEL);【RADIO_TRIANGEL = 1.0f / 6】 555 // * <p/> 556 // * 这个其实无所谓,主要为了屏幕适配,你可以抽取为自定义属性让用户去设置; 557 // * <p/> 558 // * initTriangle()中用Path去构造了一个三角形,这个很简单了~~ 559 // * <p/> 560 // * 这里还初始化了mInitTranslationX,因为一开始显示的就在第一个Tab的中间位置。 561 // * <p/> 562 // * 三角形初始化完成了,是不是应该去看看它在哪进行绘制的~~ 563 // */ 564 // @Override 565 // protected void onSizeChanged(int w, int h, int oldw, int oldh) { 566 // super.onSizeChanged(w, h, oldw, oldh); 567 // mTriangleWidth = (int) (w / count * RADIO_TRIANGEL);// 1/6 of 568 // // width 569 // mTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth); 570 // //初始化三角形 571 // initTriangle(); 572 //初始化矩形 573 initrectangle(); 574 // // 初始时的偏移量 575 // mInitTranslationX = getWidth() / count / 2 - mTriangleWidth 576 // / 2; 577 // } 578 // 579 // /** 580 // * 初始化三角形指示器 581 // */ 582 // private void initTriangle() { 583 // mPath = new Path(); 584 // mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2)); 585 // mPath.moveTo(0, 0); 586 // mPath.lineTo(mTriangleWidth, 0); 587 // mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight); 588 // mPath.close(); 589 // } 590 /** 591 * 初始化矩形指示器 592 */ 593 private int RECTANGLE_SCALE=40; 594 private void initrectangle() { 595 mTriangleWidth=getScreenWidth()/mTabVisibleCount; 596 mPath = new Path(); 597 mTriangleHeight =getHeight()/10; 598 mPath.moveTo(0, 0); 599 mPath.lineTo(mTriangleWidth, 0); 600 mPath.lineTo(mTriangleWidth, -mTriangleHeight); 601 mPath.lineTo(0, -mTriangleHeight); 602 mPath.close(); 603 } 604 605 }二、接下来就是直接使用了
activity_main:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 xmlns:tabstyle="http://schemas.android.com/apk/res-auto" 7 android:orientation="vertical"> 8 <com.wangy.mytabpageindicator.Mytabpageindicator.Mytabpageindicator 9 android:id="@+id/id_indicator" 10 android:layout_width="match_parent" 11 android:layout_height="45dp" 12 android:background="@drawable/bg_black" 13 android:orientation="horizontal" 14 tabstyle:item_count="4" > 15 16 </com.wangy.mytabpageindicator.Mytabpageindicator.Mytabpageindicator> 17 18 <android.support.v4.view.ViewPager 19 android:id="@+id/id_vp" 20 android:layout_width="match_parent" 21 android:layout_height="0dp" 22 android:layout_weight="1" > 23 </android.support.v4.view.ViewPager> 24 25 </LinearLayout>mainActivity:
1 package com.wangy.mytabpageindicator; 2 3 import android.support.v4.app.Fragment; 4 import android.support.v4.app.FragmentPagerAdapter; 5 import android.support.v4.view.ViewPager; 6 import android.support.v7.app.AppCompatActivity; 7 import android.os.Bundle; 8 import android.view.Window; 9 10 import com.wangy.mytabpageindicator.Mytabpageindicator.Mytabpageindicator; 11 12 import java.util.ArrayList; 13 import java.util.Arrays; 14 import java.util.List; 15 16 public class MainActivity extends AppCompatActivity { 17 18 private Mytabpageindicator mytabpageindicato; 19 private ViewPager viewPager; 20 private List<String> mDatas = Arrays.asList("短信1", "短信2", "短信3", "短信4", 21 "短信5", "短信6", "短信7", "短信8", "短信9"); 22 // private List<String> mDatas = Arrays.asList("短信", "收藏", "推荐"); 23 private List<Fragment> mTabContents = new ArrayList<Fragment>(); 24 private FragmentPagerAdapter fragmentPagerAdapter; 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 requestWindowFeature(Window.FEATURE_NO_TITLE); 30 setContentView(R.layout.activity_main); 31 initview(); 32 initData(); 33 //设置Tab上的标题 34 mytabpageindicato.setTabItemTitles(mDatas); 35 viewPager.setAdapter(fragmentPagerAdapter); 36 //设置关联的ViewPager 37 mytabpageindicato.setViewPager(viewPager,0); 38 } 39 private void initData(){ 40 for (String data:mDatas){ 41 VpFragment vpFragment=VpFragment.newInstance(data); 42 mTabContents.add(vpFragment); 43 } 44 45 fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { 46 @Override 47 public Fragment getItem(int position) { 48 return mTabContents.get(position); 49 } 50 51 @Override 52 public int getCount() { 53 return mTabContents.size(); 54 } 55 }; 56 } 57 private void initview(){ 58 mytabpageindicato = (Mytabpageindicator)findViewById(R.id.id_indicator); 59 viewPager = (ViewPager)findViewById(R.id.id_vp); 60 } 61 }
里面用到了:
vpFragment:
1 package com.wangy.mytabpageindicator; 2 3 import android.os.Bundle; 4 import android.support.annotation.Nullable; 5 import android.support.v4.app.Fragment; 6 import android.view.Gravity; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.view.ViewGroup; 10 import android.widget.TextView; 11 12 /** 13 * Created by xhb on 2016/12/1. 14 */ 15 public class VpFragment extends Fragment { 16 public static final String BUNDLE_TITLE = "title"; 17 private String mTitle = "DefaultValue"; 18 19 @Override 20 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 21 Bundle bundle = getArguments(); 22 if (bundle != null) { 23 mTitle = bundle.getString(BUNDLE_TITLE); 24 } 25 TextView textView = new TextView(getActivity()); 26 textView.setText(mTitle); 27 textView.setGravity(Gravity.CENTER); 28 return textView; 29 } 30 31 public static VpFragment newInstance(String mTitle) { 32 Bundle bundle = new Bundle(); 33 bundle.putString(BUNDLE_TITLE, mTitle); 34 VpFragment vpFragment = new VpFragment(); 35 vpFragment.setArguments(bundle); 36 return vpFragment; 37 } 38 }ScreenUtils:
1 package com.wangy.mytabpageindicator.util; 2 3 import android.content.Context; 4 import android.view.WindowManager; 5 6 /** 7 * Created by xhb on 2016/12/1. 8 */ 9 public class ScreenUtils { 10 @SuppressWarnings("deprecation") 11 public static int[] getScreenDispaly(Context context){ 12 WindowManager wm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 13 int width=wm.getDefaultDisplay().getWidth();//手机屏幕的宽度 14 int height=wm.getDefaultDisplay().getHeight();//手机屏幕的高度 15 int result[] = {width,height}; 16 return result; 17 } 18 }
转载于:https://www.cnblogs.com/wangying222/p/6210930.html