滑动页面的一个例子

1. 目的

实现一个Tab列表、多个页面滑动的效果。涉及到如下几个概念:

  • ViewPager: 所有页面的容器,里边通过适配器安装多个Fragment
  • ActionBar:页面上面的ActionBar,这里的风格是一组TAB
  • ActionBar.Tab:页面上面的tab列表,通过选择每个Tab导航到对应的页面,即Fragment
  • FragmentActivity:活动页面的主Activity要继承自FragmentActivity类。因为在创建给ViewPager使用的FragmentPagerAdapter的时候,要调用FragmentActivity的getSupportFragmentManager()方法
  • FragmentPagerAdapter:是ViewPager和一系列Fragment对象之间的适配器
  • Fragment: 实际的每一页现实的内容。可以和其他的Activity联系起来,此属于更进一步的用法,所以本文不涉及。
  • TabListener:监听页面最上面的Tab选择事件,从而通过FragmentPagerAdapter更新Fragment对象。


以上这些概念,通过具体一步步模仿一个小例子即可了解。


2. 参考资料

本文参考: 利用ViewPager+Fragment+actionbar实现可左右滑动的Action Tab


3. 效果


4. 代码

4.1 ViewPager对应的布局文件

activity_main.xml --------- ADT自动生成的不能满足要求,修改如下:

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.hellofragment.MainActivity"/>

4.2 Fragment布局文件

fragment_main.xml --- ADT自动生成的基础上,增加了一个id属性,从而代码中可以引用这个TextView对象。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.hellofragment.MyFragment" >

    <TextView
        android:id="@+id/text_view_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

4.3 字符串资源

strings.xml---- ADT自动生成,未作修改

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

    <string name="app_name">HelloFragment</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

</resources>

4.4 Java代码

package com.example.hellofragment;

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

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * We hard code in this example, the number of action tab and fragment is 3.
 * 
 */
public class MainActivity extends FragmentActivity implements TabListener {
	private final String TAG = "MainActivity";
	
    private ActionBar actionBar = null;
    private ViewPager viewPager = null;
    
    /**
     * used by {@link #addTabs()} to get each page's title
     */
    private PagerAdapter pagerAdapter = null;  
    
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG, "onCreate()");
        
        initActionBar();
        initViewPager();
        addTabs();
    }

	private void initActionBar() {
		Log.d(TAG, "initActionBar()");
		
		actionBar  = this.getActionBar();
        
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayShowHomeEnabled(false);
	}

	/**
	 * addTab() will trigger the {@link #onTabSelected()}.
	 * 
	 * So initialize ViewPager first.
	 */
	private void addTabs() {
		Log.d(TAG, "addTabs()");
		
		for (int i = 0; i < 3/*hard code here*/; i++) {
			actionBar.addTab(actionBar.newTab()
    				.setText(pagerAdapter.getPageTitle(i))
    				.setTabListener(this));
    	}
	}
	
    private void initViewPager() {
    	Log.d(TAG, "initViewPager()");
    	
    	viewPager = (ViewPager)this.findViewById(R.id.container);
        
    	// set ViewPager's adapter, which includes the fragment creation
    	pagerAdapter = new MyFragmentPagerAdapter(this.getSupportFragmentManager());
    	viewPager.setAdapter(pagerAdapter);
    	
    	// set default item
        viewPager.setCurrentItem(0);
        
        // set listener
        viewPager.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageScrollStateChanged(int arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onPageSelected(int position) {
				Log.d(TAG, "OnPageChangeListener, onPageSelected(), position=" + position);
				actionBar.setSelectedNavigationItem(position);
			}
        });
	}
    
    /**
	 * Delete the auto generated code to disable the option menu items.
	 */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        //getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

	/**
	 * Delete the auto generated code to disable the option menu items.
	 */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        /*int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }*/
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     * 
     */
    public static class MyFragment extends Fragment {
    	private final String DEFAULT_TEXT = "default text";
    	private String text = DEFAULT_TEXT; //used by textView
    	private TextView textView = null;
    	
    	/**
    	 * This title is used by Pager
    	 */
    	private final String DEFAULT_TITLE = "default title";
    	private String title = DEFAULT_TITLE;
    	
        public MyFragment() {
        }

        private void setText(String text) {
        	this.text = text;
        }
        
        public String getText() {
        	return text;
        }
        
        public void setTitle(String title) {
        	this.title = title;
        }
        
        public String getTitle() {
        	return title;
        }
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            textView = (TextView)rootView.findViewById(R.id.text_view_id);
            textView.setText(text);
            
            return rootView;
        }
        
    }


    public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    	private List<MyFragment> fragments = new ArrayList<MyFragment>();
    	
		public MyFragmentPagerAdapter(FragmentManager fm) {
			super(fm);

	        createFragments();
		}

		private void createFragments() {
	    	String[] texts = new String[] {
	    			"First fragment", "Second fragment", "Third fragment"
	    	};
	    	
	    	String[] titles = new String[] {
	    			"First tab", "Second tab", "Third tab"
	    	};
	    	
			MyFragment fragment = null;
			for (int i = 0; i < 3; i++) {
				fragment = new MyFragment();
				fragment.setText(texts[i]);
				fragment.setTitle(titles[i]);
				fragments.add(fragment);
			}
			
		}
		
		@Override
		public Fragment getItem(int position) {
			Log.d(TAG, "MyFragmentPagerAdapter, getItem(), position=" + position);
			return fragments.get(position);
		}

		@Override
		public int getCount() {
			return fragments.size();
		}
    	
		/**
		 * This title is same as fragment's title, used by {@link MainActivity#addTabs()} 
		 * to set corresponding tab's text.
		 */
		@Override
		public String getPageTitle(int position) {
			Log.d(TAG, "MyFragmentPagerAdapter, getPageTitle(), position=" + position);
			return fragments.get(position).getTitle();
		}
    }


	@Override
	public void onTabSelected(Tab tab, FragmentTransaction ft) {
		Log.d(TAG, "onTabSelected()");
		
		viewPager.setCurrentItem(tab.getPosition()); 
	}


	@Override
	public void onTabUnselected(Tab tab, FragmentTransaction ft) {
	}


	@Override
	public void onTabReselected(Tab tab, FragmentTransaction ft) {
		// TODO Auto-generated method stub
		
	}
}

5. 打印日志


6. 一点说明

主要的步骤是:

  • 设置ActionBar的属性,比如tab显示方式等;
  • 创建ViewPager对象,并设置其一些属性,重点是设置适配器,这个适配器会和Fragment关联起来
  • 创建ActionBar的Tab列表。


Fragment和Tab的联动,一方面,是通过ViewPager的FragmentPagerAdapter对象来实现的:当页面滑动的时候,适配器会自动更新fragment(getItem()方法);另一方面,ViewPagerde的OnPageChangeListener()调用ActionBar的setSelectedNavigationItem()方法来更新Tab。

反过来,当Tab变化的时候,通过实现TabListener接口的onTabSelected()方法,去调用ViewPager的setCurrentItem(),进而触发OnPageChangeListener()。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值