自定义tab,下边是viewpager。滑动viewpager,tab跟着动,点击tab,有动画效果并且viewpager也动。

本文介绍了一种自定义Tab与ViewPager相结合的方法,通过动画效果实现流畅的切换体验。同时,针对Fragment在ViewPager中的缓存进行了优化,避免了每次切换时的重复加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果

自定义tab,下边是viewpager。滑动viewpager,tab跟着动,点击tab,有动画效果并且viewpager也动。

按住viewpager滑动,tab也相应滑动
并且viewpager中的是fragment,不要每次都重写加载fragment

主要代码


/**
 * Created by Administrator on 2016/6/21.
 */
public class ServiceCommentFragment extends BaseFragment {
    private TextView good_comment;
    private TextView middle_comment;
    private TextView bad_comment;
    private int good_commentLeft;
    private int middle_commentLeft;
    private int bad_commentLeft;
    private TextView blue_tab;
    private int locationLeft = 0;
    private FragmentManager fragmentManger;
    private FragmentAdapter mFragmentAdapter;
    private SonMyCouponFragment couponFragment;
    private FrameLayout fl_container;
    private ArrayList<Fragment> fragments;
    private JSONObject mJsonObject;
    private String bcType;
    private Boolean mIsFromHomeFragment;
    private ViewPager viewpager;
    private myViewpagerAdapter adapter;
    private int screenWidth;
    private double currentIndex;
    private LinearLayout.LayoutParams lp;
    public static ServiceCommentFragment getInstance(String jsonObjectString, Boolean isFromHomeFragment) {
        ServiceCommentFragment f = new ServiceCommentFragment();
        Bundle args = new Bundle();
        args.putString("jsonObjectString", jsonObjectString);
        args.putBoolean("isFromHomeFragment", isFromHomeFragment);
        f.setArguments(args);
        return f;
    }
    @Override
    protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_service_comment, container, false);
    }
    @Override
    protected void initData(View view, Bundle savedInstanceState) {
        setTitle(view, "服务评价");
        if (getArguments() != null) {
            if (getArguments().containsKey("jsonObjectString")) {
                String jsonObjectString = getArguments().getString("jsonObjectString");
                if (!TextUtils.isEmpty(jsonObjectString)) {
                    JSONObject jsonObject = JSON.parseObject(jsonObjectString);
                    this.mJsonObject = jsonObject;
                }
            }
            if (getArguments().containsKey("isFromHomeFragment")) {
                Boolean isFromHomeFragment = getArguments().getBoolean("isFromHomeFragment");
                this.mIsFromHomeFragment = isFromHomeFragment;
            }
        }
        good_comment = (TextView) view.findViewById(R.id.good_comment);
        middle_comment = (TextView) view.findViewById(R.id.middle_comment);
        bad_comment = (TextView) view.findViewById(R.id.bad_comment);
        blue_tab = (TextView) view.findViewById(R.id.blue_tab);
        //fl_container = (FrameLayout) view.findViewById(R.id.fl_container);
        fragments = new ArrayList<Fragment>();//存放fragment的集合
        fragmentManger = getActivity().getSupportFragmentManager();
        bcType = mJsonObject.getString("bcType");
        if (mIsFromHomeFragment) {
            //是从首页进来的
            getDataFromHome();
        } else {
            //不是从首页跳过来的,访问别的接口,获取所有的 评论
            if ("0".equals(bcType)) {
                //大B 游乐类
                getPlayCommentCount();
            } else if ("1".equals(bcType)) {
                //大c 教育类
                getEduCommentCount();
            }
            fragments.add(CommentFragment.getInstance(0, mJsonObject.toJSONString()));//好评
            fragments.add(CommentFragment.getInstance(1, mJsonObject.toJSONString()));//中评
            fragments.add(CommentFragment.getInstance(2, mJsonObject.toJSONString()));//差评
            viewpager = (ViewPager) view.findViewById(R.id.viewpager);
            adapter = new myViewpagerAdapter(fragmentManger, fragments);
            viewpager.setAdapter(adapter);
            //viewpager.setOffscreenPageLimit(2);//设置缓存view 的个数(实际有3个,缓存2个+正在显示的1个)
            viewpager.setCurrentItem(0);
            addTabClickEvent();
            initTabLineWidth();

            //拖动viewpager,tab也滑动相应的距离
            viewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float offset, int positionOffsetPixels) {
                    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) blue_tab
                            .getLayoutParams();
                    if (currentIndex == 0 && position == 0)// 0->1
                    {                                                                   //0页
                        lp.leftMargin = (int) (offset * (screenWidth * 1.0 / 2) + currentIndex * (screenWidth / 4));
                    }
                    if (currentIndex == 0 && position == 1)// 0->1
                    {                                                                   //0页
                        lp.leftMargin = (int) (-(1 - offset) * (screenWidth * 1.0 / 2) + currentIndex * (screenWidth / 4));
                    } else if (currentIndex == 1 && position == 0) // 1->0
                    {
                        lp.leftMargin = (int) (-(1 - offset) * (screenWidth * 1.0 / 2) + currentIndex * (screenWidth / 5 * 2.53));
                    } else if (currentIndex == 1 && position == 1) // 1->0
                    {
                        lp.leftMargin = (int) (offset * (screenWidth * 1.0 / 5) + currentIndex * ((screenWidth / 5 * 2.53)));
                    } else if (currentIndex == 1 && position == 2) // 1->2
                    {
                        lp.leftMargin = (int) (-(1 - offset) * (screenWidth * 1.0 / 5) + currentIndex * (screenWidth / 5 * 2.53));
                    } else if (currentIndex == 2 && position == 1) // 2->1
                    {
                        lp.leftMargin = (int) (-(1 - offset) * (screenWidth * 1.0 / 5) + currentIndex * (screenWidth / 5 * 1.85));
                    } else if (currentIndex == 2 && position == 2) // 2->1
                    {
                        lp.leftMargin = (int) (offset * (screenWidth * 1.0 / 5) + currentIndex * (screenWidth / 5 * 1.85));
                    }
                    blue_tab.setLayoutParams(lp);
                }
                @Override
                public void onPageSelected(int position) {
                    setStartLocation(position);
                    currentIndex = position;
                }
                @Override
                public void onPageScrollStateChanged(int state) {
                }
            });
        }
    }
    private void setStartLocation(int position) {
        good_comment.setTextColor(getContext().getResources().getColor(R.color.qinase));
        middle_comment.setTextColor(getContext().getResources().getColor(R.color.qinase));
        bad_comment.setTextColor(getContext().getResources().getColor(R.color.qinase));
        switch (position) {
            case 0:
                good_comment.setTextColor(getContext().getResources().getColor(R.color.black_text));
                break;
            case 1:
                middle_comment.setTextColor(getContext().getResources().getColor(R.color.black_text));
                break;
            case 2:
                bad_comment.setTextColor(getContext().getResources().getColor(R.color.black_text));
                break;
        }
    }
    private void initTabLineWidth() {
        DisplayMetrics dpMetrics = new DisplayMetrics();
        getActivity().getWindow().getWindowManager().getDefaultDisplay()
                .getMetrics(dpMetrics);
        screenWidth = dpMetrics.widthPixels;
        lp = (LinearLayout.LayoutParams) blue_tab
                .getLayoutParams();
        lp.width = screenWidth / 5;
        blue_tab.setLayoutParams(lp);
    }
    /**
     * 初始位置的标志设置
     *
     * @param index
     */
    public void setLocation(int index) {
        switch (index) {
            case 0:
                lp.leftMargin = index * (int) (screenWidth / 5 * 1.9);
                break;
            case 1:
                lp.leftMargin = index * (int) ((screenWidth / 5 * 2.6));
                break;
            case 2:
                lp.leftMargin = index * (int) (screenWidth / 5 * 1.9);
                break;
        }
        viewpager.setCurrentItem(index);
        blue_tab.setLayoutParams(lp);
    }
   //点击Tab,动画效果。值动画
    public void setLocationAnim(int index) {
        int oldMargin = lp.leftMargin;
        int newMargin = 0;
        switch (index) {
            case 0:
                newMargin= index * (int) (screenWidth / 5 * 1.9);
                break;
            case 1:
                newMargin = index * (int) ((screenWidth / 5 * 2.6));
                break;
            case 2:
                newMargin = index * (int) (screenWidth / 5 * 1.9);
                break;
        }
        ValueAnimator animator = ValueAnimator.ofFloat(oldMargin,newMargin );
        // 设置作用对象
        animator.setTarget(lp.leftMargin);
        // 设置执行时间(1000ms)
        animator.setDuration(500);
        // 添加动画更新监听
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 获取当前值

                blue_tab.setLayoutParams(lp);
            }
        });
        // 开始动画
        animator.start();
        viewpager.setCurrentItem(index);
    }
    //给tab添加点击事件
    private void addTabClickEvent() {
        good_comment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setLocationAnim(0);
            }
        });
        middle_comment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setLocationAnim(1);
            }
        });
        bad_comment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setLocationAnim(2);
            }
        });
    }
    //访问从首页进去的那个接口
    private void getDataFromHome() {
        HashMap<String, String> map = new HashMap<>();
        String commentId = mJsonObject.getString("commentId");
        PublicService.getInstance().postJsonObjectRequest(StringUtils.makeUrl(ConfigUrls.COMMENT_GET_LIST_FROMHOME, bcType, commentId), map,
                new JsonObjectListener() {
                    @Override
                    public void onJsonObject(JSONObject obj) {
                        String serviceId = obj.getString("serviceId");
                        final int type = obj.getInteger("type");
                        String skip = obj.getString("skip");
                        String bcType = obj.getString("bcType");
                        JSONObject object = new JSONObject();
                        object.put("targetId", serviceId);
                        object.put("bcType", bcType);
                        object.put("skip", skip);
                        fragments.set(0, CommentFragment.getInstance(0, object.toJSONString()));//好评
                        fragments.set(1, CommentFragment.getInstance(1, object.toJSONString()));//中评
                        fragments.set(2, CommentFragment.getInstance(2, object.toJSONString()));//差评
                        viewpager.setAdapter(new myViewpagerAdapter(fragmentManger, fragments));
                    }
                    @Override
                    public void onObjError() {
                        ToastUtil.showNormalShortToast("error");
                        popBackStack();
                    }
                });
    }
    //获得教育类的 好中差评的数量
    private void getEduCommentCount() {
        String serviceId = mJsonObject.getString("targetId");
        PublicService.getInstance().postJsonObjectRequest(StringUtils.makeUrl(ConfigUrls.QUERY_COMMENTCOUNT_EDU, serviceId), null,
                new JsonObjectListener() {
                    @Override
                    public void onJsonObject(JSONObject obj) {
                        String goodCount = obj.getString("goodCount");
                        String normalCount = obj.getString("normalCount");
                        String badCount = obj.getString("badCount");
                        good_comment.setText("好评(" + goodCount + ")");
                        middle_comment.setText("中评(" + normalCount + ")");
                        bad_comment.setText("差评(" + badCount + ")");
                    }
                    @Override
                    public void onObjError() {
                        ToastUtil.showNormalShortToast("error");
                    }
                });
    }
    private void getPlayCommentCount() {
        String serviceId = mJsonObject.getString("targetId");
        PublicService.getInstance().postJsonObjectRequest(StringUtils.makeUrl(ConfigUrls.QUERY_COMMENTCOUNT_PLAY, serviceId), null,
                new JsonObjectListener() {
                    @Override
                    public void onJsonObject(JSONObject obj) {
                        String goodCount = obj.getString("goodCount");
                        String normalCount = obj.getString("normalCount");
                        String badCount = obj.getString("badCount");
                        good_comment.setText("好评(" + goodCount + ")");
                        middle_comment.setText("中评(" + normalCount + ")");
                        bad_comment.setText("差评(" + badCount + ")");
                    }
                    @Override
                    public void onObjError() {
                        ToastUtil.showNormalShortToast("error");
                    }
                });
    }
//    //控件滑动的动画  方法
//    public void anim(TextView tv,int left){
//        int tvLeft = getLocationLeft(tv);
//        ObjectAnimator oa = ObjectAnimator.ofFloat(tv, "TranslationX", tvLeft, left);
//        oa.setDuration(300);
//        oa.start();
//    }
//
////    // View宽,高  得到距离左边的距离
//    public int getLocationLeft(View v) {
//        int[] loc = new int[2];
//        int[] location = new int[2];
//        v.getLocationOnScreen(location);
//        loc[0] = location[0];
//        loc[1] = location[1];
////        int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
////        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
////        v.measure(w, h);
////
////        loc[2] = v.getMeasuredWidth();
////        loc[3] = v.getMeasuredHeight();
//
//        //base = computeWH();
//        return loc[0];
//    }
}

fragment的在viewpager中缓存,不要每次都加载,这里就是重写FragmentPagerAdapter 的两个方法instantiateItem() 和 destroyItem()隐藏和显示fragment,避免重复加载。

/**
 * Created by 张玉水 on 2016/8/2.
 */
public class myViewpagerAdapter extends FragmentPagerAdapter {
    private FragmentManager fm;
    private ArrayList<Fragment> fragments;
    public myViewpagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments) {
        super(fm);
        this.fm = fm;
        this.fragments = fragments;
    }
    @Override
    public Fragment getItem(int position) {
        Fragment fragment;
        fragment = fragments.get(position);
        return fragment;
    }
    @Override
    public int getCount() {
        return fragments.size();
    }
    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
    @Override
    public Fragment instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        fm.beginTransaction().show(fragment).commit();
        return fragment;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // super.destroyItem(container, position, object);     
        fm.beginTransaction().hide(fragments.get(position)).commit();
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值