您的位置:首页 > 其它

自定义tabpageindicator,可以自定义tab是三角形还是矩形,但是tab不具有滑动的功能

2016-12-22 13:51 155 查看
我是不会滴,但是看了一些大神写的,我修改了一下,大家可以参照参照

一,自定义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 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐