Android中ViewPage+Fragment顶部及FragmentTabHost+Fragment底部 滑动切换

Android开发中ViewPage+Fragment实现区域顶部tab滑动切换

本教程我们将说说tab导航,导航分为一层和两层(底部区块+区域内头部导航),主要实现方案有RadioGroup+ViewPage+Fragment、Viewpager Indicator、ActionBar Tabs、FragmentTabHost+Fragment等,下面我们先采用RadioGroup+ViewPage+Fragment实现区域头部导航。

如图所示:

案例主要组件

1、先看一下MainActivity布局

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
      <HorizontalScrollView
        android:id="@+id/hvChannel"
         android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        >
        <RadioGroup
         android:id="@+id/rgChannel"
         android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:orientation="horizontal">
            
        </RadioGroup> 
    </HorizontalScrollView>
      <android.support.v4.view.ViewPager
              android:id="@+id/vpNewsList"
               android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
          >
      </android.support.v4.view.ViewPager>
</LinearLayout>

       

2、MainActivity代码:

public class MainActivity extends FragmentActivity implements OnPageChangeListener{
    private ViewPager viewPager;
    private RadioGroup rgChannel=null;
    private HorizontalScrollView hvChannel;
    private PageFragmentAdapter adapter=null;
    private List<Fragment> fragmentList=new ArrayList<Fragment>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView(){
        rgChannel=(RadioGroup)super.findViewById(R.id.rgChannel);
        viewPager=(ViewPager)super.findViewById(R.id.vpNewsList);
        hvChannel=(HorizontalScrollView)super.findViewById(R.id.hvChannel);
        rgChannel.setOnCheckedChangeListener(
                new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, 
                    int checkedId) {
                viewPager.setCurrentItem(checkedId);        
            }
        });
        viewPager.setOnPageChangeListener(this);
        initTab();//动态产生RadioButton
        initViewPager();
        rgChannel.check(0);
    }
    private void initTab(){
        List<Channel> channelList=ChannelDb.getSelectedChannel();
        for(int i=0;i<channelList.size();i++){
            RadioButton rb=(RadioButton)LayoutInflater.from(this).
                    inflate(R.layout.tab_rb, null);
            rb.setId(i);
            rb.setText(channelList.get(i).getName());
            RadioGroup.LayoutParams params=new 
            RadioGroup.LayoutParams(RadioGroup.LayoutParams.WRAP_CONTENT,
                            RadioGroup.LayoutParams.WRAP_CONTENT);
            rgChannel.addView(rb,params);
        }
        
    }
    private void initViewPager(){
        List<Channel> channelList=ChannelDb.getSelectedChannel();
        for(int i=0;i<channelList.size();i++){
            NewsFragment frag=new NewsFragment();
            Bundle bundle=new Bundle();
            bundle.putString("weburl", channelList.get(i).getWeburl());
            bundle.putString("name", channelList.get(i).getName());
            frag.setArguments(bundle);     //向Fragment传入数据
            fragmentList.add(frag);
        }
        adapter=new PageFragmentAdapter(super.getSupportFragmentManager(),fragmentList);
        viewPager.setAdapter(adapter);
        //viewPager.setOffscreenPageLimit(0);
    }
    
    /**
     * 滑动ViewPager时调整ScroollView的位置以便显示按钮
     * @param idx
     */
    private void setTab(int idx){
        RadioButton rb=(RadioButton)rgChannel.getChildAt(idx);
        rb.setChecked(true);
        int left=rb.getLeft();
        int width=rb.getMeasuredWidth();
        DisplayMetrics metrics=new DisplayMetrics();
        super.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int screenWidth=metrics.widthPixels;
        int len=left+width/2-screenWidth/2;
        hvChannel.smoothScrollTo(len, 0);//滑动ScroollView
    }
    @Override
    public void onPageScrollStateChanged(int arg0) {
    
    }
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }
    @Override
    public void onPageSelected(int position) {
        // TODO Auto-generated method stub
        setTab(position);
    }
}

其中initTab()方法实现向RadioGroup动态添加RadioButton

导航按钮数据来源于ChannelDb

    private static List<Channel>   selectedChannel=new ArrayList<Channel>();
    static{
        selectedChannel.add(new Channel("","头条",0,"",""));
        selectedChannel.add(new Channel("","娱乐",0,"",""));
        selectedChannel.add(new Channel("","体育",0,"",""));
        selectedChannel.add(new Channel("","财经",0,"",""));
        selectedChannel.add(new Channel("","热点",0,"",""));
        selectedChannel.add(new Channel("","科技",0,"",""));
        selectedChannel.add(new Channel("","图片",0,"",""));
        selectedChannel.add(new Channel("","汽车",0,"",""));
        selectedChannel.add(new Channel("","时尚",0,"",""));
    }
    public static  List<Channel> getSelectedChannel(){
         return selectedChannel;
    }

导航按钮外观:tab_rb.xml和tab_selector.xml背景选择器(实现选择后带红色下划线效果)

<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:text="今日"
                android:background="@drawable/tab_selector"
                android:paddingLeft="15dp"
                android:paddingRight="15dp"
                 android:paddingTop="10dp"
                android:paddingBottom="10dp"
                  android:button="@null"
                />
tab_selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
      <item android:state_checked="true" ><!-- 选中状态 -->
        <layer-list >
            <item >
                <shape android:shape="rectangle">
                    <stroke android:width="5dp"  android:color="#ff0000"/>    
                </shape>
            </item>
            <item  android:bottom="5dp" >
                <shape android:shape="rectangle" >
                        <solid android:color="#fff"/>
               </shape>
            </item>
        </layer-list> 
    </item>
    <item ><!-- 默认状态 -->
        <shape >
                <solid  android:color="#FAFAFA"/>
        </shape>
    </item>
</selector>

3、PageFragmentAdapter适配器

public class PageFragmentAdapter extends FragmentPagerAdapter{
    private List<Fragment> fragmentList;
    private FragmentManager fm;
    public PageFragmentAdapter(FragmentManager fm,List<Fragment> fragmentList){
        super(fm);
        this.fragmentList=fragmentList;
        this.fm=fm;
    }
    @Override
    public Fragment getItem(int idx) {
        return fragmentList.get(idx%fragmentList.size());
    }
    @Override
    public int getCount() {
        return fragmentList.size();
    }
    @Override  
    public int getItemPosition(Object object) {  
       return POSITION_NONE;  //没有找到child要求重新加载
    }  }

4、NewsFragment组件:

public class NewsFragment extends Fragment {
    private String weburl;
    private String channelName;
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }
    private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if(view==null){//优化View减少View的创建次数    
            //该部分可通过xml文件设计Fragment界面,再通过LayoutInflater转换为View组件
            //这里通过代码为fragment添加一个TextView
            TextView tvTitle=new TextView(getActivity());
            tvTitle.setText(channelName);
            tvTitle.setTextSize(16);
            tvTitle.setGravity(Gravity.CENTER);
            tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
            view=tvTitle;
        }
        ViewGroup parent=(ViewGroup)view.getParent();
        if(parent!=null){//如果View已经添加到容器中,要进行删除,负责会报错
            parent.removeView(view);
        }
        return view;
    }
    @Override
    public void setArguments(Bundle bundle) {//接收传入的数据
        weburl=bundle.getString("weburl");
        channelName=bundle.getString("name");    
    }
    
}


Android开发中FragmentTabHost+Fragment实现底部tab切换

上面我们使用RadioGroup+ViewPage+Fragmen实现了顶部滑动导航,接下来我们使用FragmentTabHost+Fragment实现底部tab切换,效果如图所示


案例主要组件

1、MainActivity布局

  把整个Activity分成两部TabHost和TabContent,TabHost包含各个tab,tab之间切换将在TabContent所关联的FrameLayout区域中显示各自板块的内容

<LinearLayout  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:orientation="vertical"
    tools:context=".MainActivity" >
    <FrameLayout  android:id="@+id/contentLayout"
         android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"> 
    </FrameLayout>
     <android.support.v4.app.FragmentTabHost
         android:id="@android:id/tabhost"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="#F6F6F6"
         >
         <FrameLayout android:id="@android:id/tabcontent"
             android:layout_height="0dp" android:layout_width="0dp"
             />
     </android.support.v4.app.FragmentTabHost>
</LinearLayout>

2、MainActivity代码

public class MainActivity extends FragmentActivity
 implements OnTabChangeListener{
    private FragmentTabHost tabHost;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tabHost=(FragmentTabHost)super.findViewById(android.R.id.tabhost);
        tabHost.setup(this,super.getSupportFragmentManager()
                ,R.id.contentLayout);
        tabHost.getTabWidget().setDividerDrawable(null);
        tabHost.setOnTabChangedListener(this);
        initTab();
    }
    private void initTab(){
        String tabs[]=TabDb.getTabsTxt();
        for(int i=0;i<tabs.length;i++){
            TabSpec tabSpec=tabHost.newTabSpec(tabs[i]).setIndicator(getTabView(i));
            tabHost.addTab(tabSpec,TabDb.getFragments()[i],null);
            tabHost.setTag(i);
        }
    }
    private View getTabView(int idx){
        View view=LayoutInflater.from(this).inflate(R.layout.footer_tabs,null);
        ((TextView)view.findViewById(R.id.tvTab)).setText(TabDb.getTabsTxt()[idx]);
        if(idx==0){
            ((TextView)view.findViewById(R.id.tvTab)).setTextColor(Color.RED);
    ((ImageView)view.findViewById(R.id.ivImg)).setImageResource(TabDb.getTabsImgLight()[idx]);
        }else{
            ((ImageView)view.findViewById(R.id.ivImg)).setImageResource(TabDb.getTabsImg()[idx]);
        }
        return view;
    }
    @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;
    }
    @Override
    public void onTabChanged(String tabId) {
        // TODO Auto-generated method stub
        updateTab();
    }
    private void updateTab(){
        TabWidget tabw=tabHost.getTabWidget();
        for(int i=0;i<tabw.getChildCount();i++){
            View view=tabw.getChildAt(i);
            ImageView iv=(ImageView)view.findViewById(R.id.ivImg);
            if(i==tabHost.getCurrentTab()){
                ((TextView)view.findViewById(R.id.tvTab)).setTextColor(Color.RED);
                iv.setImageResource(TabDb.getTabsImgLight()[i]);
            }else{        ((TextView)view.findViewById(R.id.tvTab)).setTextColor(getResources().getColor(R.color.foot_txt_gray));
                iv.setImageResource(TabDb.getTabsImg()[i]);
            }
            
        }
    }
}

3、TabDb组件

 提供界面设计所需的tab文本、tab图片和Fragment类型数据

public class TabDb {
    public static String[] getTabsTxt(){
        String[] tabs={"新闻","阅读","试听","发现"," 我"};
        return tabs;
    }
    public static int[] getTabsImg(){
        int[] ids={R.drawable.foot_news_normal,R.drawable.foot_read_normal,R.drawable.foot_vdio_normal,R.drawable.foot_fond_normal,R.drawable.foot_out_normal};
        return ids;
    }
    public static int[] getTabsImgLight(){
        int[] ids={R.drawable.foot_news_light,R.drawable.foot_read_light,R.drawable.foot_vdio_light,R.drawable.foot_found_light,R.drawable.foot_out_light};
        return ids;
    }
    public static Class[] getFragments(){
        Class[] clz={NewsFragment.class,ReadFragment.class,VideoFragment.class,FoundFragment.class,OwnerFragment.class};
        return clz;
    }
}

4、每个tab各自对应的Fragment组件

  共5个Fragment为NewsFragment、ReadFragment、FoundFragment、OwnerFragment、VideoFragment,根据不同板块各自设计界面,这里重点是如何实现底部tab切换,简单布局一下即可,以NewsFragment为例代码如下:

public class NewsFragment extends Fragment {
    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        TextView tvTitle=new TextView(super.getActivity());
        tvTitle.setText("新闻");
        tvTitle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
        tvTitle.setGravity(Gravity.CENTER);
        tvTitle.setTextSize(30);
        return tvTitle;
    }
    @Override
    public void setArguments(Bundle args) {
        // TODO Auto-generated method stub
        super.setArguments(args);
    }
}

5、tab布局样式(footer_tabs.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    android:gravity="center"
    android:padding="5dp"
    android:background="#F6F6F6"
    >
    <ImageView
        android:id="@+id/ivImg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
       />
    <TextView
        android:id="@+id/tvTab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/ivImg"
          android:textColor="#AEAEAE"
        android:text="新闻" android:layout_marginTop="2dp"/>

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, view
, 导航
, this
null
fragmenttabhost 底部、fragmenttabhost 顶部、fragmenttabhost 滑动、fragmenttabhost、fragmenttabhost用法,以便于您获取更多的相关知识。

时间: 2024-11-03 22:32:37

Android中ViewPage+Fragment顶部及FragmentTabHost+Fragment底部 滑动切换的相关文章

Android中ViewPager获取当前显示的Fragment

前言 在项目中,有时会用到在ViewPager中显示同样类型的Fragment,同时这样的Fragment的个数是动态的,但是PagerAdapter没有给我们提供getCurrentFragment类似的方法.下面就给大家介绍下Android中ViewPager获取当前显示的Fragment的方法,一起看看吧. 一.使用 getSupportFragmentManager().findFragmentByTag()方法 Viewpager + FragmentPagerAdapter 情况下

Android中ViewPager组件的基本用法及实现图片切换的示例

ViewPager是android-support-v4.jar包里的组件.在布局文件里标签需要连包名一起 写全称<android.support.v4.view.ViewPager /> 基本用法 ViewPager的基本用法我概括为三步 第一步 在主布局文件里放一个ViewPager组件 第二步 为每个页面建立布局文件,把界面写好 第三步 在主Activity里获取ViewPager组件,并为它设定Adapter. Adapter详细讲讲,ViewPager对应的Adapter继承自Pag

android中使用Activity实现监听手指上下左右滑动_Android

用Activity的onTouchEvent方法实现监听手指上下左右滑动 应用了Activity的ontouchEvent方法监听手指点击事件,手指滑动的时候会先按下,滑倒另一个地方再抬起,我们就可以根据按下的坐标和抬起的坐标算出用户是往哪一个方向滑动了. package com.example.testtt; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; impor

Android中实现Webview顶部带进度条的方法_Android

写这篇文章,做份备忘,简单滴展示一个带进度条的Webview示例,进度条位于Webview上面. 示例图如下: 主Activity代码: 复制代码 代码如下: package com.droidyue.demo.webviewprogressbar; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.vi

Android中实现Webview顶部带进度条的方法

写这篇文章,做份备忘,简单滴展示一个带进度条的Webview示例,进度条位于Webview上面. 示例图如下: 主Activity代码: 复制代码 代码如下: package com.droidyue.demo.webviewprogressbar; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.vi

android中使用Activity实现监听手指上下左右滑动

用Activity的onTouchEvent方法实现监听手指上下左右滑动 应用了Activity的ontouchEvent方法监听手指点击事件,手指滑动的时候会先按下,滑倒另一个地方再抬起,我们就可以根据按下的坐标和抬起的坐标算出用户是往哪一个方向滑动了. package com.example.testtt; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; impor

[Android] 使用Include布局+Fragment滑动切换屏幕

    前面的文章已经讲述了"随手拍"项目图像处理的技术部分,该篇文章主要是主界面的布局及屏幕滑动切换,并结合鸿洋大神的视频和郭神的第一行代码(强推两人Android博客),完成了下面的内容:    (1).学习使用Include布局XML    (2).通过添加适配器加载fragment    (3).实现滑动触摸切换屏幕ViewPager    (4).改变图标及背景,并响应fragment中控件及传递参数参考资料:     郭霖大神的<Android第一行代码>  

android中fragment切换的时候遇到非法参数异常的问题

问题描述 android中fragment切换的时候遇到非法参数异常的问题 FragmentTabHost中加入了两个fragment,片段1和片段2.运行后从片段1到片段2没有出问题,当从片段2再回到片段1的时候出现非法参数异常. 异常代码如图 找到错误主要原因是设置了一个布局的ID: gridview_layout.setId(CAL_LAYOUT_ID); 请问为什么在fragment中设置id切换片段后会发生异常? 解决方案 你这两个页面的id相同 但是页面不是同一种类型的 有冲突

急急急!-如何在这个fragment中使用fragmenttabhost+fragment啊?

问题描述 如何在这个fragment中使用fragmenttabhost+fragment啊? activity上已经嵌套一层fragment,如何在这个fragment中使用fragmenttabhost+fragment啊? 解决方案 drawerNavigation被fragment overlay, FragmentTabHost使用FragmentTabHost+fragment中获得fragment的对象Android之Fragment的使用(一) 解决方案二: 可以再嵌套一层的Ad