ITPub博客

首页 > IT职业 > IT职场 > 【Android】顶部Tab指示器(自定义LinearLayout+V

【Android】顶部Tab指示器(自定义LinearLayout+V

IT职场 作者:llittle 时间:2021-09-09 08:58:05 0 删除 编辑

2016-11-13 第一篇 ViewPagerIndicator

根据鸿洋的视频编写,然后自己添加了可以滑动的图形方式,直线或者三角形。还添加了可以在xml中自定义样式的功能。

最后效果演示图
图片描述

图片描述

ChangeablePagerIndicator类(顶部的指示器类)
重写父类主要的方法:
1.dispatchDraw(Canvas canvas) 绘制直线或者三角形
图片描述
2.onFinishInflate() xml文件加载完成之后调用此放过,在xml中设置item时,在此方法重新设置item的宽度
图片描述


Tab item移动的方法:
1.scroll(int position,float offset)
图片描述

代码生成Items的方法
1.setTabItems(List titles)
图片描述


内部处理ViewPager的滑动
1.设置ViewPager :setViewPager(ViewPager viewPager,int currentPos)
图片描述
2.设置监听事件(这里的IndicatorListener是实现ViewPager.OnPageChangeListener接口)
图片描述


点击Item跳转ViewPager
1.setItemClickListener()
图片描述


xml中自定义的属性值
图片描述
图片描述


全部代码


指示器类代码(ChangeablePagerIndicator.java)

package jfsl.view.toptab.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

import jfsl.view.toptab.R;
import jfsl.view.toptab.listener.IndicatorListener;

/**
 * 顶部Tab的导航区域
 * 固定的顶部Indicator
 *
 * @version 1.0
 * @aduthor JFSL
 * @date 2016/11/12
 * @date 2016-11-13 15:08 完成
 */

public class ChangeablePagerIndicator extends LinearLayout
{
    //默认的高亮文本颜色:白色
    public static final int COLOR_TEXT_HIGHLIGHT = Color.parseColor("#FFFFFFFF");
    //默认的正常文本颜色:灰色
    public static final int COLOR_TEXT_NORMAL = Color.parseColor("#77FFFFFF");
    //默认绘制图形的颜色:白色
    public static final int COLOR_GRAPHICS = Color.parseColor("#FFFFFFFF");
    //默认Tab的文本大小 16sp
    public static final int TAB_TEXT_SIZE = 16;
    //直线的高度 10dp
    public static final int LINE_HEIGHT = 10;
    //最小的显示Tab的数量
    public static final int DEFAULT_VISIBLE_COUNTS = 3;
    //绘制的类型:1.直线 2.三角形
    public static final int STYLE_LINE = 100;
    public static final int STYLE_TRIANGLE = 200;
    //三角形的比例
    public static final float TRIANGLE_RADIO = 1 / 6F;
    //绘制三角形的画笔
    private Paint mTrianglePaint;
    //绘制三角形的路径
    private Path mTrianglePath;
    //三角形的宽
    private int mTriangleWidth;
    //三角形的高
    private int mTriangleHeight;
    //绘制直线的画笔
    private Paint mLinePaint;
    //线的宽度
    private int mLineWidth;
    //初始位置时三角形的位置
    private int mStartX;
    //移动时三角形的位置
    private int mMoveX;
    //绘制的类型
    private int mDrawStyle = STYLE_LINE;
    //默认显示的tab item数量
    private int mDefaultVisibleCounts;
    //高亮文本的颜色
    private int mHighLightColor;
    //普通文本的颜色
    private int mNormalTextColor;
    //文本大小
    private int mTextSize;
    //线的高度(strokeWidth)
    private int mLineHeight;
    //直线或者三角形的颜色
    private int mGraphicsColor;

    public ChangeablePagerIndicator(Context context)
    {
        this(context,null);
    }

    public ChangeablePagerIndicator(Context context,AttributeSet attrs)
    {
        super(context,attrs);
        //获取自定义的值
        getCustomValue(context,attrs);
        //初始化三角形的画笔
        initTrianglePaint();
        //初始化直线的画笔
        initLinePaint();
    }

    /**
     * 加载完XML时,调用此方法
     */
    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        int coutns = getChildCount();
        if(coutns == 0)
            return;

        for(int i = 0;i = (mDefaultVisibleCounts - 2) && offset > 0
                && getChildCount() > mDefaultVisibleCounts
                && position != getChildCount() - 2)
        {
            if(mDefaultVisibleCounts != 1)
            {
                int scrollX = (position - (mDefaultVisibleCounts - 2)) * tabWidth
                        + (int)(tabWidth * offset);
                this.scrollTo(scrollX,0);
            } else
            {
                this.scrollTo((position * tabWidth
                        + (int)(tabWidth * offset)),0);
            }

        }
        //重新绘制
        invalidate();
    }

    /**
     * 设置绘制的类型
     * 1.STYLE_LINE    直线
     * 2.STYLE_TRIANGLE 三角形
     */
    public void setDrawStyle(int style)
    {
        mDrawStyle = style;
        invalidate();
    }

    public void setDefaultVisibleCounts(int counts)
    {
        mDefaultVisibleCounts = counts;
        if(counts  titles)
    {
        if(titles == null)
            return;
        //首先移除所有的View
        this.removeAllViews();
        //根据标题生成TextView
        for(String title : titles)
        {
            this.addView(generateTitleView(title));
        }
        //设置监听
        setItemClickListener();
    }

    /**
     * 设置ViewPager
     *
     * @param viewPager
     * @param currentPos 当前选的位置
     */
    private ViewPager mViewPager;

    public void setViewPager(ViewPager viewPager,int currentPos)
    {
        mViewPager = viewPager;
        viewPager.addOnPageChangeListener(mListener);
        //设置当前选中项
        viewPager.setCurrentItem(currentPos);
    }

    /**
     * ViewPager监听
     */
    private IndicatorListener mListener = new IndicatorListener()
    {

        @Override
        public void scrollChanged(int position,float offset)
        {
            //进行Tab滚动
            scroll(position,offset);
        }

        @Override
        public void selected(int position)
        {
            //设置高亮文本,当前ViewPager与Tab一一对应
            setHighLightText(position);
        }
    };

    /**
     * Tab Item的点击监听
     */
    private void setItemClickListener()
    {
        for(int i = 0;i 

自定义ViewPager监听类(IndicatorListener.java)

package jfsl.view.toptab.listener;

import android.support.v4.view.ViewPager;

/**
 * @version 1.0
 * @aduthor JFSL
 * @date 2016/11/13 0013
 */

public abstract class IndicatorListener implements ViewPager.OnPageChangeListener
{
    @Override
    public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels)
    {
        scrollChanged(position,positionOffset);
    }

    @Override
    public void onPageSelected(int position)
    {
        selected(position);
    }

    @Override
    public void onPageScrollStateChanged(int state)
    {

    }

    /**
     * ViewPager滑动
     * @param position
     * @param offset
     */
    public abstract void scrollChanged(int position,float offset);

    /**
     * 选择当前页
     * @param position
     */
    public abstract void selected(int position);
}

ViewPager指示器类(TopViewPagerAdapter.java)

package jfsl.view.toptab.adapter;

import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import java.util.List;

import jfsl.view.toptab.fragment.SimpleFragment;

/**
 * @version 1.0
 * @aduthor JFSL
 * @date 2016/11/12 0012
 */

public class TopViewPagerAdapter  extends FragmentPagerAdapter
{
    private Context mContext;
    private List mFragments;

    public TopViewPagerAdapter(FragmentManager fm,Context context,List fragments)
    {
        super(fm);
        mContext = context;
        mFragments = fragments;
    }
    @Override
    public Fragment getItem(int position)
    {
        return mFragments.get(position);
    }

    @Override
    public int getCount()
    {
        return mFragments.size();
    }
}

测试用的Fragment(SimpleFragment.java)

package jfsl.view.toptab.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**测试用的Fragment
 * @version 1.0
 * @aduthor JFSL
 * @date 2016/11/12 0012
 */

public class SimpleFragment extends Fragment
{
    public static final String BUNDLE_TITLE = "title";
    private String mTitle;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)
    {
        Bundle bundle = getArguments();
        if(bundle != null)
            mTitle = bundle.getString(BUNDLE_TITLE);

        TextView textView = new TextView(getActivity());
        textView.setText(mTitle);
        textView.setGravity(Gravity.CENTER);

        return textView;
    }

    /**
     * 获取实例
     * @param title
     * @return
     */
    public static SimpleFragment newInstance(String title)
    {
        Bundle bundle = new Bundle();
        bundle.putString(BUNDLE_TITLE,title);
        SimpleFragment fragment = new SimpleFragment();
        fragment.setArguments(bundle);
        return fragment;
    }
}

测试的Activity(ChangeableMainActivity .java)

package jfsl.view.toptab;

import android.os.Bundle;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import jfsl.view.toptab.adapter.TopViewPagerAdapter;
import jfsl.view.toptab.fragment.SimpleFragment;
import jfsl.view.toptab.view.ChangeablePagerIndicator;

/**
 * 测试自定义View的效果
 */
public class ChangeableMainActivity extends AppCompatActivity
{
    private ViewPager mViewPager;
    private ChangeablePagerIndicator mIndicator;
    private List mTitles = Arrays.asList("国际","军事","社会","娱乐","体育","财经","历史","本地","中国");
    private List mFragments = new ArrayList();
    private FragmentPagerAdapter mPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main_changeable2);

        initViews();
        initDatas();
        initEvent();
    }

    private void initEvent()
    {
    }

    private void initDatas()
    {
        for(String title : mTitles)
        {
            mFragments.add(SimpleFragment.newInstance(title));
        }
        mPagerAdapter = new TopViewPagerAdapter(getSupportFragmentManager(),this,mFragments);
        mViewPager.setAdapter(mPagerAdapter);

//        mIndicator.setDefaultVisibleCounts(3);
        //设置绘制的类型
//        mIndicator.setDrawStyle(ChangeablePagerIndicator.STYLE_TRIANGLE);
        //注意:其他设置要放在这个之前
        mIndicator.setTabItems(mTitles);
        mIndicator.setViewPager(mViewPager,1);
    }

    private void initViews()
    {
        mIndicator = (ChangeablePagerIndicator)findViewById(R.id.id_pager_indicator);
        mViewPager = (ViewPager)findViewById(R.id.id_viewpager);

    }
}

自定义属性文件(indicator_attrs.xml)

<!--默认的显示的Tab数量--><!--高亮文本的颜色--><!--正常文本的颜色--><!--图形的颜色--><!--文本的大小--><!--图形的高度--><!--图形的类型--><!--默认的显示的Tab数量--><!--高亮文本的颜色--><!--正常文本的颜色--><!--图形的颜色--><!--文本的大小--><!--图形的高度--><!--图形的类型-->

颜色值文件(colors.xml)

#009688#06776d#FF4081

代码地址:http://114.215.186.20/14551100130/toptab.zip


参考资料:
1.http://blog.csdn.net/scorplopan/article/details/6302827 ondraw() 和dispatchdraw()的区别

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/813/viewspace-2798354/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-04-12

  • 博文量
    448
  • 访问量
    4365