ViewPager是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api。而viewpager就是其中之一利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等。那如何使用它呢,与ListView类似,我们也需要一个适配器,他就是PagerAdapter。
ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的View类。ViewPager类需要一个PagerAdapter适配器类给它提供数据。ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和 FragmentStatePagerAdapter类供Fragment中的ViewPager使用。
ViewPager的功能就是可以使视图滑动,就像Lanucher左右滑动那样。
.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
.support.v4.view.ViewPager>
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
//当页面选中时
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
//arg0 当前页
//arg1 移动页百分比
//arg2 移动像素点
}
@Override
public void onPageScrollStateChanged(int arg0) {
//滑动状态改变
}
});
PagerTitleStrip是ViewPager的一个关于当前页面、上一个页面和下一个页面的一个非交互的指示器。它经常作为ViewPager控件的一个子控件被被添加在XML布局文件中。在你的布局文件中,将它作为子控件添加在ViewPager中。而且要将它的android:layout_gravity属性设置为TOP或BOTTOM来将它显示在ViewPager的顶部或底部。每个页面的标题是通过适配器的getPageTitle(int)函数提供给ViewPager的。
PagerTabStrip与PagerTitleStrip类似,只有两点不同
PagerTabStrip在当前页面下,会有一个下划线条来提示当前页面的Tab是哪个。 PagerTabStrip的Tab是可以点击的,当用户点击某一个Tab时,当前页面就会跳转到这个页面,而PagerTitleStrip则没这个功能。
例子:实现一个跟随页面移动的指示条
具体的实现的代码都是在ViewPager的监听方法中实现
我们知道,实现ViewPager是要有适配器的,我们前面用的适配器是 PagerAdapter,而对于Fragment,它所使用的适配器是:FragmentPagerAdapter。 FragmentPagerAdapter派生自PagerAdapter,它是用来呈现Fragment页面的,这些 Fragment页面会一直保存在fragment manager中,以便用户可以随时取用。
在 使 用 ViewPager 时 , 必 须 使 用 v 4 包 下 的 Fragment, 并 且 使 用 FragmentActivity。
这个适配器最好用于有限个静态fragment页面的管理。尽管不可见的视图有时会被销毁,但用户所有 访问过的fragment都会被保存在内存中。因此fragment实例会保存大量的各种状态,这就造成了很 大的内存开销。所以如果要处理大量的页面切换,建议使用FragmentStatePagerAdapter.
对于FragmentPagerAdapter的派生类,只需要重写getItem(int)和getCount()就可以了。
public class FragAdapter extends FragmentPagerAdapter {
private List mFragments;
public FragAdapter(FragmentManager fm,List fragments) {
super(fm);
mFragments=fragments;
}
@Override
public Fragment getItem(int arg0) {
//根据传来的参数arg0,来返回当前要显示的Fragment
return mFragments.get(arg0);
}
@Override
public int getCount() {
//返回用于滑动的fragment总数
return mFragments.size();
}
}
下面是ViewPager的使用示例
这里设计的是页面可以左右滑动页面,实现图片的切换,并且下面有每一个图片对应的图标,当页面滑动到第八张图片弹出一个按钮,可以做相应的操作。
这里设置了无限滑动的设置!代码控制的。
代码设计:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/main_vp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/main_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:gravity="center"
android:orientation="horizontal" />
<Button
android:id="@+id/main_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_margin="20dp"
android:text="点击马上体验!"
android:visibility="invisible" />
RelativeLayout>
在drawable文件夹下,创建start_selsect.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/star" android:state_selected="true">item>
<item android:state_selected="false">
<shape android:shape="oval">
<solid android:color="@android:color/darker_gray" />
shape>
item>
selector>
上面要放一张小星星的图片到资源文件中。
下面还有放八张大图片到资源文件中,用于划屏时显示。
package fuxi.viewpager1;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
//布局中的对象
ViewPager vp;
LinearLayout ll;
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.main_btn);
initPoints();//初始化小圆点
initView();//初始化数据
}
/**
* 实现小圆点的添加,
* 找到线性布局动态的向线性布局内添加小圆,并添加drawable选择的效果
*/
private void initPoints() {
//实例化线性布局
ll = (LinearLayout) findViewById(R.id.main_ll);
//绘制和图片对应的圆点的数量
for (int i = 0; i < images.length; i++) {
View view = new View(this);
//设置圆点的大小
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(30, 30);
//设置间距
params.setMargins(10, 10, 10, 10);
//设置图片的自定义效果
view.setBackgroundResource(R.drawable.stars_select);
//把设置好的视图属性设置到View中
view.setLayoutParams(params);
//把创建好的View添加到线性布局中
ll.addView(view);
}
Log.e("TAG", ":" + ll.getChildCount());
//设置选中线性布局中的第一个
ll.getChildAt(0).setSelected(true);
}
/**
* 初始化数据
*/
private void initView() {
//实例化ViewPager
vp = (ViewPager) findViewById(R.id.main_vp);
//创建适配器对象
Myadapter adapter = new Myadapter();
//给视图ViewPager添加适配器
vp.setAdapter(adapter);
//给ViewPager添加监听事件
//这个监听事件设置不是点击的,也不是选中的,使用添加页面改变的监听
vp.addOnPageChangeListener(this);
//设置图片开始的位置,从中间开始,并且是从八张图片中的第一张开始
vp.setCurrentItem(Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % 8));
}
/**
* 下面三个方法是,实现ViewPager监听页面改变时要实现的方法
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//页面滑动时触发
}
int index = 0;//设置一个游标值记录当前的显示页面
@Override
//页面选中时的回调方法
public void onPageSelected(int position) {
//对小圆点的设置
//取消前一个视图的选中
ll.getChildAt(index).setSelected(false);
//选中下一个显示的视图
ll.getChildAt(position % 8).setSelected(true);
//跟新游标的值
index = position % 8;
//当显示最后一个页面时,可以实现跳转
if (index == 7) {
ll.setVisibility(View.INVISIBLE);
btn.setVisibility(View.VISIBLE);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Toast.makeText(MainActivity.this, "点击了按钮", Toast.LENGTHRT).show();
//页面跳转到具体页面
//startActivity(new Intent(MainActivity.this, MainActivity2.class));
//关闭原来界面
finish();
}
});
} else {
ll.setVisibility(View.VISIBLE);
btn.setVisibility(View.INVISIBLE);
}
}
//页面状态改变时的回调方法
@Override
public void onPageScrollStateChanged(int state) {
//对ViewPager状态进行判断决定是否执行轮播页面
if (state == ViewPager.SCROLL_STATE_IDLE) {
if (!handler.hasMessages(1)) {
startGuide();
}
} else {
stopGuide();
}
}
/**
* 创建一个Handler对象,用于实现自动轮播画面
*/
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
vp.setCurrentItem(vp.getCurrentItem() + 1);
sendEmptyMessageDelayed(1, 2000);//延长两秒后给自己发消息,没有被移除前都是会一直循环的
}
};
/**
* 开始轮播
*/
private void startGuide() {
handler.sendEmptyMessageDelayed(1, 2000);
}
/**
* 停止轮播
*/
private void stopGuide() {
//把消息移除,轮播页面就会停止
handler.removeMessages(1);
}
//数据源,8张图片
int[] images = {R.mipmap.a1, R.mipmap.a2, R.mipmap.a3, R.mipmap.a4, R.mipmap.a5, R.mipmap.a6, R.mipmap.a7, R.mipmap.a8};
//定义一个集合用来存放视图的View对象
List listOfView = new ArrayList<>();
/**
* 在类内创建Adapter对象,
* 这里ViewPager要对应的Adapter是PagerAdapter
*/
class Myadapter extends PagerAdapter {
//可滑动的页面的数量
@Override
public int getCount() {
//return listOfView.size();//实现只能滑动一遍图片的效果
return Integer.MAX_VALUE;//实现无限滑动的效果
}
//判断两页的地址是否相同
@Override
public boolean isViewFromObject(View view, Object object) {
//这是google要求的写法
return view == object;
}
//重写构造方法,当创建实例时,把数据添加到集合中
public Myadapter() {
for (int i = 0; i < images.length; i++) {
//创建ImageView存放图片
ImageView iv = new ImageView(getApplicationContext());
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setImageResource(images[i]);
//把图片添加到集合zhong
listOfView.add(iv);
}
}
//下面的两个方法也是必须重写的
//这里要返回的是View的视图对象
@Override
public Object instantiateItem(ViewGroup container, int position) {
//添加一个item 显示
//Toast.makeText(getBaseContext(), position + "页", Toast.LENGTH_SHORT).show();
container.addView(listOfView.get(position % 8));
return listOfView.get(position % 8);
}
//销毁一个View的对象
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(listOfView.get(position % 8));
}
}
}
这里就可以实现相关页面的跳转,但是本实例中只是关闭页面。
上面程序使用了Handler对象操作实现自动轮播的页面,如果没有滑动页面两秒页面是会自动轮播的,而滑动时页面是不会轮播的。
可以看到上面有一个指示器在跟着滑动。
代码设计:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/home_rg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/home_rb_dujia"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/back"
android:button="@null"
android:gravity="center"
android:padding="10dp"
android:text="旅游度假" />
<RadioButton
android:id="@+id/home_rb_ticker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/back"
android:button="@null"
android:gravity="center"
android:padding="10dp"
android:text="景点门票" />
RadioGroup>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="5dp">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#4e6bd4" />
<View
android:id="@+id/home_fl_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#16308c" />
FrameLayout>
<android.support.v4.view.ViewPager
android:id="@+id/home_vp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
LinearLayout>
这里使用的是ViewPager来装载碎片,既没有使用fragment标签,也没有使用FrameLayout标签。
在drawable文件夹下的back.xml文件
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorPrimary" android:state_selected="false" />
<item android:drawable="@color/colorAccent" android:state_selected="true" />
selector>
上面的颜色资源也是系统提供的,也可以使用自己定义的。
package fuxi.viewpager2;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* 这是个人旅游页面的碎片布局
*/
public class TourFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是个人旅游页面的碎片布局");
view.setBackgroundColor(Color.YELLOW);
return view;
}
}
package fuxi.viewpager2;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* 这是景点售票页面的碎片布局
*/
public class TickerFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是景点售票页面的碎片布局");
view.setBackgroundColor(Color.GREEN);
return view;
}
}
package fuxi.viewpager2;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RadioGroup;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener, ViewPager.OnPageChangeListener {
//定义布局内的控件
RadioGroup rg;
View vi;//自定义的指示器
ViewPager vp;
//数据源的集合
List list = new ArrayList<>();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载数据
list.add(new TourFragment());
list.add(new TickerFragment());
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化布局
*/
private void initView() {
//实例化控件
rg = (RadioGroup) findViewById(R.id.home_rg);
vp = (ViewPager) findViewById(R.id.home_vp);
vi = findViewById(R.id.home_fl_view);
//创建适配器,设置的碎片管理器使用的是getChildFragmentManager()
FragmentStatePagerAdapter adapter = new Myadapter(getSupportFragmentManager());
//给ViewPager设置适配器
vp.setAdapter(adapter);
//给控件设置监听事件
rg.setOnCheckedChangeListener(this);
//给ViewPager设置监听器使用的是add而不是set了
vp.addOnPageChangeListener(this);
initVi();
}
//屏幕一半的宽度
int width;
//把下划线View设置初始值
private void initVi() {
width = getResources().getDisplayMetrics().widthPixels / 2;
//设置下划线View的长度
FrameLayout.LayoutParams par = new FrameLayout.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT);
vi.setLayoutParams(par);
}
//单选按钮点击后触发的回调方法
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//点击后选择对应的ViewPager页面
vp.setCurrentItem(checkedId == R.id.home_rb_dujia ? 0 : 1);
}
//屏幕滑动的回调方法,设置指示器
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//"页面:" + position + "
// offset偏移百分比" + positionOffset
// pix像素" + positionOffsetPixels
//设置下划线的属性
//设置下划线View的长度
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams) vi.getLayoutParams();
//设置下划线距离左边的位置长度
int left = (int) ((positionOffset + position) * width);
par.setMargins(left, 0, 0, 0);
vi.setLayoutParams(par);
}
//屏幕被选择的回调方法
@Override
public void onPageSelected(int position) {
//选择页面后设置单选按钮的选择
rg.check(position == 0 ? R.id.home_rb_dujia : R.id.home_rb_ticker);
}
//滑动页面状态的改变,这个方法不用理会
//如果要实现自动轮播可以重写
@Override
public void onPageScrollStateChanged(int state) {
}
//创建ViewPager适配器的类
class Myadapter extends FragmentStatePagerAdapter {
public Myadapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
}
}
可以看到这里没有使用事务,就可以实现页面的隐藏和显示,这些都是ViewPager在底层已经做好的事情了。
本示例中也设计了指示器的效果,就是按钮下面那条横线,设计的方法也是有三种的,一个是使用PagerTitleStrip,一个是使用PagerTabStrip,另一个就是使用自定义的指示器。当然这三种只是简单的指示器的设计,如果想要特殊效果的指示器还是有很多方法的。指示器的使用另作总结。
个人觉得使用自定义的指示器还是比较方便的,而且代码是固定的,如果不理解也没关系,复制使用就可以了。另外两种指示器是比较另类的,还有其他指示器的设计方法是比较麻烦的。
程序设计外层的页面是五个Fragment页面,不能滑动,只能点击切换,但是其中一个Fragment页面有ViewPager页面,可以实现滑动页面。
程序运行效果:
点击下面的按钮可以实现Fragment界面的切换,这里设计中间一个Fragment是一个ViewPager页面,可以左右滑动选择页面。
这个页面和上面一个示例是相似的。但是这里是碎片中的碎片!
可以看到这里每一个按钮都做了选择器。并且中间碎片页面也是有个指示器的。
下面是代码设计:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.exam.framework.MainActivity">
<RadioGroup
android:id="@+id/main_rg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<RadioButton
android:id="@+id/main_rb0"
style="@style/MyRadioStyle"
android:drawableTop="@drawable/favor"
android:tag="0"
android:text="收藏" />
<RadioButton
android:id="@+id/main_rb1"
style="@style/MyRadioStyle"
android:drawableTop="@drawable/order"
android:tag="1"
android:text="订单" />
<RadioButton
android:id="@+id/main_rb2"
style="@style/MyRadioStyle"
android:drawableTop="@drawable/home"
android:tag="2"
android:text="主页" />
<RadioButton
android:id="@+id/main_rb3"
style="@style/MyRadioStyle"
android:drawableTop="@drawable/uc"
android:singleLine="true"
android:tag="3"
android:text="个人中心" />
<RadioButton
android:id="@+id/main_rb4"
style="@style/MyRadioStyle"
android:drawableTop="@drawable/setting"
android:tag="4"
android:text="设置" />
RadioGroup>
<FrameLayout
android:id="@+id/main_fl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/main_rg">FrameLayout>
RelativeLayout>
这里动态显示隐藏Fragment要先添加FrameLayout布局容器。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/home_rg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/home_rb_dujia"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/back"
android:button="@null"
android:gravity="center"
android:padding="10dp"
android:text="旅游度假" />
<RadioButton
android:id="@+id/home_rb_ticker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/back"
android:button="@null"
android:gravity="center"
android:padding="10dp"
android:text="景点门票" />
RadioGroup>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="5dp">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#4e6bd4" />
<View
android:id="@+id/home_fl_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#16308c" />
FrameLayout>
<android.support.v4.view.ViewPager
android:id="@+id/home_vp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
LinearLayout>
这里也是动态加载Fragment但是使用的是ViewPager。并且这里有自定义的指示器。
上面有用到比较多的资源文件
drawable–》favor.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/icon_favor_normal" android:state_checked="false" />
<item android:drawable="@mipmap/icon_favor_press" android:state_checked="true" />
selector>
drawable–》order.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/icon_order_normal" android:state_checked="false" />
<item android:drawable="@mipmap/icon_order_press" android:state_checked="true" />
selector>
drawable–》home.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/icon_home_normal" android:state_checked="false" />
<item android:drawable="@mipmap/icon_home_press" android:state_checked="true" />
selector>
drawable–》uc.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/icon_uc_normal" android:state_checked="false" />
<item android:drawable="@mipmap/icon_uc_press" android:state_checked="true" />
selector>
drawable–》setting.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/icon_setting_normal" android:state_checked="false" />
<item android:drawable="@mipmap/icon_setting_press" android:state_checked="true" />
selector>
drawable–》back.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/color_back" android:state_selected="false" />
<item android:drawable="@color/color_backnor" android:state_selected="true" />
selector>
Values——》colors.xml
<resources>
<color name="colorPrimary">#3F51B5color>
<color name="colorPrimaryDark">#303F9Fcolor>
<color name="colorAccent">#FF4081color>
<color name="color_back">#207579color>
<color name="color_backnor">#7fdcd9color>
resources>
上面颜色资源中最下面俩个是自己添加的,上面的几个是系统有的。
package com.exam.framework;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class FavorFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是收藏页面");
view.setBackgroundColor(Color.RED);
return view;
}
}
除了中间的Fragment的java代码是复杂一点的,其他的都是简单数据的显示。
package com.exam.framework;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class OrderFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是订单页面的碎片布局");
view.setBackgroundColor(Color.GREEN);
return view;
}
}
这个页面的代码和上面一个示例的代码几乎一样。
package com.exam.framework;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RadioGroup;
import java.util.ArrayList;
import java.util.List;
public class HomeFragment extends Fragment implements RadioGroup.OnCheckedChangeListener, ViewPager.OnPageChangeListener {
//定义布局内的控件
RadioGroup rg;
View vi;
ViewPager vp;
//数据源的集合
List list = new ArrayList<>();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载数据
list.add(new TourFragment());
list.add(new TickerFragment());
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载自己编写的布局文件
return View.inflate(getActivity(), R.layout.activity_frag_home, null);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//实例化控件
rg = (RadioGroup) view.findViewById(R.id.home_rg);
vp = (ViewPager) view.findViewById(R.id.home_vp);
vi = view.findViewById(R.id.home_fl_view);
//创建适配器,设置的碎片管理器使用的是getChildFragmentManager()
FragmentStatePagerAdapter adapter = new Myadapter(getChildFragmentManager());
//给ViewPager设置适配器
vp.setAdapter(adapter);
//给控件设置监听事件
rg.setOnCheckedChangeListener(this);
//给ViewPager设置监听器使用的是add而不是set了
vp.addOnPageChangeListener(this);
initVi();
}
//屏幕一般的宽度
int width;
//把下划线View设置初始值
private void initVi() {
width = getResources().getDisplayMetrics().widthPixels / 2;
//设置下划线View的长度
FrameLayout.LayoutParams par = new FrameLayout.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT);
vi.setLayoutParams(par);
}
//单选按钮点击后触发的回调方法
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//点击后选择对应的ViewPager页面
vp.setCurrentItem(checkedId == R.id.home_rb_dujia ? 0 : 1);
}
//屏幕滑动的回调方法
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//"页面:" + position + "
// offset偏移百分比" + positionOffset
// pix像素" + positionOffsetPixels
//设置下划线的属性
//设置下划线View的长度
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams) vi.getLayoutParams();
//设置下划线距离左边的位置长度
int left = (int) ((positionOffset + position) * width);
par.setMargins(left, 0, 0, 0);
vi.setLayoutParams(par);
}
//屏幕被选择的回调方法
@Override
public void onPageSelected(int position) {
//选择页面后设置单选按钮的选择
rg.check(position == 0 ? R.id.home_rb_dujia : R.id.home_rb_ticker);
}
//这个方法不用理会
@Override
public void onPageScrollStateChanged(int state) {
}
//创建ViewPager适配器的类
class Myadapter extends FragmentStatePagerAdapter {
public Myadapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
}
}
package com.exam.framework;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TourFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是个人旅游页面的碎片布局");
view.setBackgroundColor(Color.YELLOW);
return view;
}
}
package com.exam.framework;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TickerFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是景点售票页面的碎片布局");
view.setBackgroundColor(Color.BLUE);
return view;
}
}
package com.exam.framework;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class UCFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是个人中心页面的碎片布局");
view.setBackgroundColor(Color.YELLOW);
return view;
}
}
package com.exam.framework;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class SettingFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//加载系统里面的布局文件
TextView view = (TextView) View.inflate(getActivity(), android.R.layout.simple_list_item_1, null);
view.setText("这是设置页面的碎片布局");
view.setTextColor(Color.argb(1,6,0,0));
view.setBackgroundColor(Color.BLACK);
return view;
}
}
这个代码也是要重点理解的。
package com.exam.framework;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.RadioGroup;
public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
//定义布局内的RadioGroup控件
RadioGroup rg;
//定义Fragment数组存放Fragment对象
Fragment[] fragments = new Fragment[5];
//之前选中的页面游标值
int beforeIndex = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
//初始化数据
private void initView() {
//实例化RadioGroup
rg = (RadioGroup) findViewById(R.id.main_rg);
//为控件设置监听事件
rg.setOnCheckedChangeListener(this);
//默认显示主页面的碎片
rg.check(R.id.main_rb2);
// showFragment(2);
}
//点击对应的按钮后触发的事件
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//checkedId是布局文件里面的ID,比如:R.id.main_rb2
View view = rg.findViewById(checkedId);
String tag = view.getTag().toString();//获得对应视图的Tag字符串
//显示对应的碎片
showFragment(Integer.parseInt(tag));
// Toast.makeText(this, "选择:" + tag, Toast.LENGTH_SHORT).show();
}
//显示碎片的方法
private void showFragment(int index) {
Log.e("TAG", "index=" + index);
//如果点击的是前显示的页面,直接返回去
if (beforeIndex == index) {
return;
}
//对碎片继续各种操作,这里需要用到事务来完成
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
//隐藏上一次显示的碎片
if (beforeIndex != -1) {
ft.hide(fragments[beforeIndex]);
}
//如果要出现的碎片页面没有创建过,就要创建;否则显示出来就可以了
if (fragments[index] == null) {
//创建碎片(实例化)
fragments[index] = FragmentUtil.CreateFragment(index);
//把创建的布局添加到事务里面
//第一个参数是存放碎片的位置
//第二个参数是碎片的对象
ft.add(R.id.main_fl, fragments[index]);
} else {
//如不是空的对象就直接显示出来就可以了
ft.show(fragments[index]);
}
//提交事务
ft.commit();
//把当前的选择保存
beforeIndex = index;
}
}
程序运行的界面上面已经有了,这里就不演示了。
由于文中用到的资源文件比较多,图片也是比较多,有些人可能不熟悉,这里提供项目源码文件的下载:
地址:http://download.csdn.net/detail/wenzhi20102321/9708875
在程序开发中,碎片中有碎片,并且外面不能滑动,里面能滑动,或者外面的能滑动,而里面不能滑动都是有这样的需求的。
Fragment是碎片的意思,其中可以显示碎片的方法有三种,一种是静态显示碎片使用标签fragment,另一个是使用动态显示碎片,要使用FrameLayout布局容器,还有一种是使用ViewPager来显示Fragment。
但是无论使用哪一种,都是要写自定义的类来继承Fragment。
并且要注意的是一般使用Fragment都是使用v4包下的,Activity对应的也是要v4包下,否则会报错。在AndroidStudio中是自动加载的,而Eclipse中要自己手动加载。
ViewPager的使用也是比较频繁的,比如引导页面,某些局部的广告页面,轮播的实现,都是我们要去掌握的知识。
ViewPager的显示都是要使用Adapter的,如果是显示简单的图片的适配器使用的是:PagerAdapter,如果显示的是Fragment页面,使用的适配器是:FragmentStatePagerAdapter。
ViewPager和Fragment结合使用在很多App程序中是非常常见和使用的。也是要我们去熟练掌握的一个UI设计形式。
关于Fragment详细总结的知识我之前有一篇文章:
http://blog.csdn.net/wenzhi20102321/article/details/53572610