无需SherlockActionbar的SlidingMenu使用详解(二)——向Fragment中添加ViewPager和Tab

  之前我们对大体框架有了一定的认识,现在我们来做Fragment界面,其实这里面和这个框架的关系就不大了,但因为有些同学对于在SlidingMenu中切换fragment还是有问题,所以我就在本篇进行详细讲解。

1.定义MenuFragment

1.1首先定义这个fragment的布局文件,其实很简单了就是几张图片和一个listview

app_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp" 
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="120dp" >

        <ImageView
            android:id="@+id/backgroundPicture_id"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:src="@drawable/background" />

        <ImageView
            android:id="@+id/head_pic_id"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="22dp"
            android:layout_marginTop="40dp"
            android:scaleType="fitXY"
            android:src="@drawable/kale" />

        <TextView
            android:id="@+id/name_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/head_pic_id"
            android:layout_marginBottom="20dp"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="55dp"
            android:layout_toRightOf="@id/head_pic_id"
            android:text="JackTony"
            android:textColor="#ffffff"
            android:textSize="20sp" />

    </RelativeLayout>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/personalSetting_id"
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:layout_marginRight="10dp"
            android:src="@drawable/personalsettingbutton"
            android:scaleType="fitCenter" />
        
        <ImageView
            android:id="@+id/releaseMessageButton_id"
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:layout_marginLeft="10dp"
            android:src="@drawable/releasemessagebutton"
            android:scaleType="fitCenter" />
        
    </LinearLayout>
    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <ListView
             android:id="@+id/menu_list"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:paddingLeft="15dp" />
         
    
    </RelativeLayout>

</LinearLayout>
 

1.2和往常一样,我们在Fragment中加载布局文件,并且给里面的listview添加适配器用于绑定数据

MenuFragment

package com.kale.slidingmenutest.fragment;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.kale.slidingmenutest.MainActivity;
import com.kale.slidingmenutest.R;

/**
 * @author:JackTony
 * @tips :菜单的fragment
 * @date :2013-11-17
 */
public class MenuFragment extends Fragment {
    
    private MainActivity activity;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.activity = (MainActivity)activity;
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.app_menu, null);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        
        String []items = {"第一个栏目","第二个栏目"};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                getActivity(), android.R.layout.simple_list_item_1,items);
        ListView menuLv = (ListView)getActivity().findViewById(R.id.menu_list);
        //设置适配器和监听器
        menuLv.setAdapter(adapter);
        menuLv.setOnItemClickListener(new MenuItemClickListener());
    }
    
    class MenuItemClickListener implements OnItemClickListener{

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
            Fragment newFragment = null;
            MainActivity.NOW_FRAGMENT_NO = position;
            activity.supportInvalidateOptionsMenu();
            
            switch (position) {
            case 0:
                newFragment = new FirstFragment();
                break;
            case 1:
                newFragment = new SecondFragment();
                break;
            }
            
            if (newFragment != null) {
                //交给Activity来切换正文fragment
                activity.switchContent(newFragment);
            }
        }
    }
    
}

讲解:

1.listview用一个最简单的ArrayAdapter来放了两个数据,并且添加了监听器来监听点击事件。

2.在实际使用中不同的fragment很可能会需要不同的菜单,所以我通过对MainActivity中静态变量的设置和activity.supportInvalidateOptionsMenu();来使得每次切换Fragment的时候都重新根据静态变量的值来生成菜单项

3.这里面因为要用到MainActivity中切换Fragment的方法,所以要生成MainActivity对象。需要注意的是在多次切换后这个Fragment中的getActivity()方法很可能会出错,返回null值。因此这里在绑定activity时实例化一个activity对象是很有必要的!

2.简单的Fragment

SecondFragment是个很简单的Fragment,就是为了举例子用的。

package com.kale.slidingmenutest.fragment;

import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class SecondFragment extends MenuFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        TextView textView = new TextView(getActivity());
        textView.setGravity(Gravity.CENTER);
        textView.setText("第二个Fragment");
        textView.setTextSize(30);
        return textView;
    }
}

3.拥有TAB和ViewPager的FirstFragment

先贴上布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible" />

</LinearLayout>

这里面稍微有个难点就是,在不同的页面滑动时要实时改变slidingMenu的触控范围,是边缘还是全屏触控都需要设置。

3.1初始化viewPager和actionbar,并添加监听器。

因为actionbar监听器中需要传入viewpager做判断,所以要先初始化viewpager。

    ViewPager viewPager;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO 自动生成的方法存根
        return inflater.inflate(R.layout.first_fragment, null);
    }
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        // TODO 自动生成的方法存根
        super.onActivityCreated(savedInstanceState);
        //设置actionbar
        initViewPager();
        initActionBar();
    }
    
    /**
     */
    private void initActionBar() {
        ActionBar actionBar = ((MainActivity)getActivity()).getSupportActionBar();
        //设定有Tab
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        ActionBar.Tab tab;
        //开始添加Tab,这里添加4个,并且设置监听器
        for (int i = 1; i <= 4; i++) {
            tab = actionBar.newTab();
            tab.setText("Tab " + i);
            tab.setTabListener(new MyTabListener(viewPager));
            actionBar.addTab(tab);
        }
    }
    
    private void initViewPager() {
        ArrayList<View> list = new ArrayList<View>();
        for (int i = 0; i < 4; i++) {
            list.add(newTextView("第"+(i+1)+"个界面"));
        }
        viewPager = (ViewPager)getActivity().findViewById(R.id.viewPager);
        viewPager.setAdapter(new MyPagerAdapter(list));
        viewPager.setOnPageChangeListener(new PageChangeListener((MainActivity)getActivity()));
    }
    
    private TextView newTextView(String text) {
        TextView tv = new TextView(getActivity());
        tv.setText(text);
        tv.setTextSize(30);
        tv.setGravity(Gravity.CENTER);
        return tv;
    }
/**
     * @author:Jack Tony 这里配置适配器
     * @tips :这里传入一个list数组,从每个list中可以剥离一个view并显示出来
     * @date :2014-9-24
     */
    public class MyPagerAdapter extends PagerAdapter {
        private ArrayList<View> mViewList;
        private int pagerNum = 0;

        public MyPagerAdapter(ArrayList<View> viewList) {
            mViewList = viewList;
        }

        public int getPagerNum() {
            return pagerNum;
        }

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

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public void destroyItem(View arg0, int arg1, Object arg2) {
            if (mViewList.get(arg1) != null) {
                ((ViewPager) arg0).removeView(mViewList.get(arg1));
            }
        }

        @Override
        public Object instantiateItem(View arg0, int arg1) {
            try {
                if (mViewList.get(arg1).getParent() == null) {
                    ((ViewPager) arg0).addView(mViewList.get(arg1), 0);
                } else {
                    /*
                     * 很难理解新添加进来的view会自动绑定一个父类,由于一个儿子view不能与两个父类相关,
                     * 所以得解绑不这样做否则会产生 viewpager java.lang.IllegalStateException:
                     * The specified child already has a parent. You must call
                     * removeView() on the child's parent first.
                     */
                    ((ViewGroup) mViewList.get(arg1).getParent())
                            .removeView(mViewList.get(arg1));
                    ((ViewPager) arg0).addView(mViewList.get(arg1), 0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                pagerNum = arg1;
            }
            return mViewList.get(arg1);
        }

    }

全部代码:

package com.kale.slidingmenutest.fragment;

import java.util.ArrayList;

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

import com.kale.slidingmenutest.MainActivity;
import com.kale.slidingmenutest.R;
import com.kale.slidingmenutest.listener.MyTabListener;
import com.kale.slidingmenutest.listener.PageChangeListener;

public class FirstFragment extends Fragment {

    ViewPager viewPager;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO 自动生成的方法存根
        return inflater.inflate(R.layout.first_fragment, null);
    }
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        // TODO 自动生成的方法存根
        super.onActivityCreated(savedInstanceState);
        //设置actionbar
        initViewPager();
        initActionBar();
    }
    
    /**
     */
    private void initActionBar() {
        ActionBar actionBar = ((MainActivity)getActivity()).getSupportActionBar();
        //设定有Tab
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        ActionBar.Tab tab;
        //开始添加Tab,这里添加4个,并且设置监听器
        for (int i = 1; i <= 4; i++) {
            tab = actionBar.newTab();
            tab.setText("Tab " + i);
            tab.setTabListener(new MyTabListener(viewPager));
            actionBar.addTab(tab);
        }
    }
    
    private void initViewPager() {
        ArrayList<View> list = new ArrayList<View>();
        for (int i = 0; i < 4; i++) {
            list.add(newTextView("第"+(i+1)+"个界面"));
        }
        viewPager = (ViewPager)getActivity().findViewById(R.id.viewPager);
        viewPager.setAdapter(new MyPagerAdapter(list));
 
        viewPager.setOnPageChangeListener(new PageChangeListener((MainActivity)getActivity()));
    }
    
    private TextView newTextView(String text) {
        TextView tv = new TextView(getActivity());
        tv.setText(text);
        tv.setTextSize(30);
        tv.setGravity(Gravity.CENTER);
        return tv;
    }
    
    /**
     * @author:Jack Tony 这里配置适配器
     * @tips :这里传入一个list数组,从每个list中可以剥离一个view并显示出来
     * @date :2014-9-24
     */
    public class MyPagerAdapter extends PagerAdapter {
        private ArrayList<View> mViewList;
        private int pagerNum = 0;

        public MyPagerAdapter(ArrayList<View> viewList) {
            mViewList = viewList;
        }

        public int getPagerNum() {
            return pagerNum;
        }

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

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public void destroyItem(View arg0, int arg1, Object arg2) {
            if (mViewList.get(arg1) != null) {
                ((ViewPager) arg0).removeView(mViewList.get(arg1));
            }
        }

        @Override
        public Object instantiateItem(View arg0, int arg1) {
            try {
                if (mViewList.get(arg1).getParent() == null) {
                    ((ViewPager) arg0).addView(mViewList.get(arg1), 0);
                } else {
                    /*
                     * 很难理解新添加进来的view会自动绑定一个父类,由于一个儿子view不能与两个父类相关,
                     * 所以得解绑不这样做否则会产生 viewpager java.lang.IllegalStateException:
                     * The specified child already has a parent. You must call
                     * removeView() on the child's parent first.
                     */
                    ((ViewGroup) mViewList.get(arg1).getParent())
                            .removeView(mViewList.get(arg1));
                    ((ViewPager) arg0).addView(mViewList.get(arg1), 0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                pagerNum = arg1;
            }
            return mViewList.get(arg1);
        }

    }
    
    
    
}

3.2设置ViewPager的滑动监听,滑动时要求tab也需要跟着变换,并且滑动到最左边的界面时将触控范围变为全屏有效。

PageChangeListener

package com.kale.slidingmenutest.listener;

import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;

import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.kale.slidingmenutest.MainActivity;

public class PageChangeListener implements ViewPager.OnPageChangeListener {

    private ActionBarActivity activity;

    public PageChangeListener(ActionBarActivity activity) {
        this.activity = activity;
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        // TODO 自动生成的方法存根

    }

    @Override
    public void onPageSelected(int position) {
        //System.out.println("position:" + position);
        activity.getSupportActionBar().setSelectedNavigationItem(position);
        //设置在其他页面滑动时slingmenu是边缘模式,最边上页面是全屏模式(防误触)
         switch (position) {
            case 0:
                ((MainActivity)activity).getMySlidingMenu().
                setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
                break;
            default:
                ((MainActivity)activity).getMySlidingMenu().
                setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
                break;
        }
    }
}

3.3MyTabListener

注意:要判断viewpager是否为空

package com.kale.slidingmenutest.listener;

import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;

/**
 * @author:Jack Tony
 * @tips :设置tab的监听器,控制viewpager的显示
 * @date :2014-7-30
 */
public class MyTabListener implements ActionBar.TabListener {
    ViewPager viewPager;

    public MyTabListener(ViewPager viewPager) {
        this.viewPager = viewPager;
    }

    @Override
    public void onTabReselected(Tab arg0, FragmentTransaction arg1) {

    }

    /* 核心方法
     * @see android.support.v7.app.ActionBar.TabListener#onTabSelected(android.support.v7.app.ActionBar.Tab, android.support.v4.app.FragmentTransaction)
     * 选中某个tab时,同时切换viewpager
     */
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction arg1) {
        if (viewPager != null && viewPager.getCurrentItem() != tab.getPosition()) {
            viewPager.setCurrentItem(tab.getPosition());
        }
    }

    @Override
    public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {

    }

}

源码下载:http://download.csdn.net/detail/shark0017/7976759

原文地址:https://www.cnblogs.com/tianzhijiexian/p/3994329.html