sweetyy、

导航

ViewPager+Listview实现内导航滑动切换与列表点击事件

ViewPager+Listview

(PS:底部导航实现参考博客之底部导航栏)

一、内部导航栏框架及滑动切换

1、设置Home.xml文件

(1)布局

(2)对应代码:

<?xml version="1.0" encoding="utf-8"?>
<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:background="@drawable/home"
    android:orientation="vertical"
    tools:context=".Home">
    <!-- TODO: Update blank fragment layout -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <!-- 导航标签,包含一个单选按钮组-->
        <HorizontalScrollView
            android:id="@+id/hvChannel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@+id/img_channel"
            android:scrollbars="none">

            <RadioGroup
                android:id="@+id/radiogroup"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
            </RadioGroup>

        </HorizontalScrollView>

        <!-- 任意数量不能显示时的缩略符号 -->
        <ImageView
            android:id="@+id/img_channel"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentRight="true"
            android:scaleType="fitXY"
            android:src="@mipmap/rg_channel" />
    </RelativeLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vpNewsList"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        tools:ignore="SpeakableTextPresentCheck,SpeakableTextPresentCheck" />
</LinearLayout>

2、 在Home的 onCreateView 方法中,为 ViewPager 设置适配器,实现滑动翻页切 换碎片

public class Home extends Fragment implements ViewPager.OnPageChangeListener
{
    private static final String ARG_CHANNEL_LIST = "channel_list";
    //以下声明 fragment_home.xml 对应的控件实例
    private View view = null;
    private RadioGroup rgChannel = null;
    private ViewPager viewPager;
    private HorizontalScrollView hvChannel = null;
    private String[] channelList = {"关注", "学习", "兔兔", "运动", "新闻", "天气",
                                    "科技","IT","家人","朋友","诗歌","绘画"};
    //栏目列表
    private FAdapter adapter;

    public Home()
    {
        // Required empty public constructor
        System.out.println("H1");
    }


// 原本
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        if(view==null)
        {
            view=inflater.inflate(R.layout.fragment_home, container, false);
            viewPager=(ViewPager)view.findViewById(R.id.vpNewsList);
            initViewPager();
        }
        return view;
    }
}

3、设置 ViewPager 容器的适配器

(1)初始化内导航标签

//初始化内导航标签
private void initViewPager()
{
    FragmentManager fragmentManager = super.getActivity().getSupportFragmentManager();
    adapter = new FAdapter(fragmentManager, channelList);
    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(2);
    //viewPager.setCurrentItem(0);
    viewPager.addOnPageChangeListener(this);
    System.out.println("H3");
}

(2)添加ViewPager 切换监听器 ViewPager.OnPageChangeListener 的3个事件处理方 法,用接口方式实现ViewPager.OnPageChangeListener

 @Override
    public void onPageScrolled(int i, float v, int i1)
    {System.out.println("H4");
    }

    @Override
//某个碎片被选中时的动作,对应的内导航标签将要滑动到屏幕中央,并且有下划线显示
    public void onPageSelected(int i)
    {
        setTab(i); //后面再实现,控制导航栏保持一致
        System.out.println("H5");
    }

    @Override
    public void onPageScrollStateChanged(int i)
    {System.out.println("H6");
    }

4、新建FAdapter.java文件,适配器为 ViewPager 提供碎片,当滑动 ViewPager 时,切换到后一碎片或者前一碎片。

public class FAdapter extends FragmentStatePagerAdapter
{
    private String[] channelList;
    private FragmentManager fm;
    public FAdapter(FragmentManager fm, String[] channelList)
    {
        super(fm);
        this.channelList = channelList;
        this.fm=fm;
        System.out.println("A1");
    }

    //getItem()方法,根据position(这里是idx)得到某一行的记录
    @Override
    public Fragment getItem(int idx)
    {
        Log.e("FAdapter","getItem"+idx);
        String CategoryTitle = channelList[idx];
        System.out.println("A2");//不能在return之后加
        return ChannelFragment.newInstance(CategoryTitle);
        /*
        newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。
        分步的好处是可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。
        newInstance: 弱类型。低效率。只能调用无参构造。
        new: 强类型。相对高效。能调用任何public构造。
         */
    }
    //getCount()方法,得到数据的行数
    @Override
    public int getCount()
    {
        System.out.println("A3");
        return channelList.length;
    }
}

5、新建ChannelFragment活动,在ChannelFragment.java中实例化碎片

package com.example.myapplication6;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;

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

public class ChannelFragment extends Fragment
{
    private static final String ARG_CATEGORY_TITLE = "category_title";
    private String newsCategoryTitle = "Default";
    private TextView mTitleField;

    public static ChannelFragment newInstance(String newsCategoryTitle)
    {
        Bundle args = new Bundle();
        args.putString(ARG_CATEGORY_TITLE, newsCategoryTitle);
        ChannelFragment fragment = new ChannelFragment();
        fragment.setArguments(args);
        System.out.println("C1");
        return fragment;
    }

    public ChannelFragment() {
        // Required empty public constructor
        System.out.println("C2");
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        try {
            newsCategoryTitle = (String) getArguments().getString(ARG_CATEGORY_TITLE);
        } catch (java.lang.NullPointerException e) {
            System.out.println("TestFragment getArg error!");
        }
        System.out.println("C3");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.activity_channel_fragment, container, false);
        mTitleField = (TextView) view.findViewById(R.id.newsCategoryTitle);
        mTitleField.setText(newsCategoryTitle);
        Log.e("ChannelFragment", "createView" + newsCategoryTitle);
        System.out.println("C4");
        return view;
    }
}

6、修改ChannelFragment.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".ChannelFragment">
    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:id="@+id/newsCategoryTitle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="30sp"
        android:text="hello" />
</FrameLayout>

7、加入顶部导航,实现当单击内导航按钮时,ViewPager 可以切换到对应碎片。

(1)修改Home.java的OnCreateView()方法

//单选按钮点击事件
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState)
{
    // Inflate the layout for this fragment
    if (view == null)
    {
        view = inflater.inflate(R.layout.activity_home, container, false);
        viewPager = (ViewPager) view.findViewById(R.id.vpNewsList);
        initViewPager();
        //第二个
        rgChannel = (RadioGroup) view.findViewById(R.id.radiogroup);
        hvChannel = (HorizontalScrollView) view.findViewById(R.id.hvChannel);
        initTab(inflater); //初始化内导航标签
        rgChannel.setOnCheckedChangeListener( //单选按钮的监听事件响应
                new RadioGroup.OnCheckedChangeListener()
                {
                    @Override
                    public void onCheckedChanged(RadioGroup group, int checkedId)
                    {
                        viewPager.setCurrentItem(checkedId);
                        //实现两个方法显示内容
                    }
                });
    }
    System.out.println("H2");
    return view;
}

(2)初始化内导航标签,使用radiogroup布局构造各个单选按钮

//初始化内导航标签
private void initTab(LayoutInflater inflater)
{
    for(int i=0;i<channelList.length;i++)
    {//以下添加单选按钮的实例到内导航
        RadioButton rb=(RadioButton)inflater.inflate(R.layout.radiogroup, null);
        rb.setId(i);
        rb.setText(channelList[i]);
        RadioGroup.LayoutParams params=new
                RadioGroup.LayoutParams(RadioGroup.LayoutParams.WRAP_CONTENT,
                RadioGroup.LayoutParams.WRAP_CONTENT);
        rgChannel.addView(rb,params);
    }
    rgChannel.check(0); //第一个选项
    System.out.println("H8");
}

8、新建radiogroup.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/rg_selector"
    android:paddingLeft="15dp"
    android:paddingRight="15dp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:button="@null"
    />

9、新建rg_selector.xml文件,设置内导航单选按钮的background属性,在其被选 中时显示青绿色短横线

<?xml version="1.0" encoding="utf-8"?>
<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=""@color/teal_200""/>
                </shape>

            </item>
            <item android:bottom="5dp" >
                <shape android:shape="rectangle" >
                    <solid android:color="#fff"/>
                </shape>
            </item>
        </layer-list>


    </item>
    <item android:state_selected="true" >
        <layer-list >
            <item >
                <shape android:shape="rectangle">
                    <stroke android:width="5dp" android:color="@color/teal_200"/>
                </shape>
            </item>
            <item android:bottom="5dp" >
                <shape android:shape="rectangle" >
                    <solid android:color="#fff"/>
                </shape>
            </item>
        </layer-list>
    </item>
    <item >
        <shape >
            <solid android:color="#ffF"/>
        </shape>
    </item>
</selector>

10、在Home.java的事件处理程序 onPageSelected()方法中调用setTab()方法, setTab()方法如下:

//设置选定某个碎片时水平滚动视图的显示 HorizontalScrollView
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.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int screenWidth=metrics.widthPixels;
    int len=left+width/2-screenWidth/2;
    hvChannel.smoothScrollTo(len, 0);
    System.out.println("H7");
}

11、效果图

二、拓展:内导航碎片页使用Listview实现新闻列表显示+在活动中读取strings.xml中数组资源

1、新建LFragment.java文件,设置代码如下:

package com.example.myapplication6;

import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;

import androidx.fragment.app.ListFragment;

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

public class LFragment extends ListFragment
{
    ArrayList<String> datas = new ArrayList<>();
    public static LFragment get_list( String[] s)
    {
        //往下传参数
        Bundle bundle = new Bundle();
        bundle.putStringArray("channelList", s);

        //创建一个对象,调用构造函数,调用默认的方法
        LFragment fragment = new LFragment();
        fragment.setArguments(bundle);
        return fragment;
    }
    public LFragment(){   //构造函数
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState)
    {
        super.onViewCreated(view, savedInstanceState);
        //接收数据
        Bundle bundle = getArguments();
        String[] channelList = bundle.getStringArray("channelList");
        List<String> datas = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            datas.add(channelList[i%15]);
        }
        //调用默认的适配器
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout
                .simple_list_item_1, datas);
        setListAdapter(adapter);
    }
}

2、修改适配器

①FAdapter类中新增数组

private String[] news={"中美元首视频会晤","法国总统马克龙修改国旗颜色","MIUI 13即将来临",
                       "浦发银行回应2.95亿元被质押", "台湾宜兰县海域地震", "中国女排杨珺菁退役",
                       "安庆步行街杀人案宣判","十九届六中全会公报发布","拜登重申不支持台独",
                       "俄方回应卫星碎片危及国际空间站","央视网评45岁程序员求职难","辽宁新增7例本土确诊",
                       "联合国向马斯克提供解决饥荒计划","意大利错失直接晋级世界杯资格","安徽一客车与货车相撞已致8死8伤"};

②getItem()方法中新增分支判断

public Fragment getItem(int idx)
{
    if (idx==4)   //第5个内部碎片
    {
           return LFragment.get_list(news);  //返回数组
    }
}

③完整FAdapter.java

package com.example.myapplication6;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;

import java.util.HashMap;

public class FAdapter extends FragmentStatePagerAdapter
{
    private String[] channelList;
    private FragmentManager fm;
    private String[] news={"中美元首视频会晤","法国总统马克龙修改国旗颜色","MIUI 13即将来临",
                           "浦发银行回应2.95亿元被质押", "台湾宜兰县海域地震", "中国女排杨珺菁退役",
                           "安庆步行街杀人案宣判","十九届六中全会公报发布","拜登重申不支持台独",
                           "俄方回应卫星碎片危及国际空间站","央视网评45岁程序员求职难","辽宁新增7例本土确诊",
                           "联合国向马斯克提供解决饥荒计划","意大利错失直接晋级世界杯资格","安徽一客车与货车相撞已致8死8伤"};
    public FAdapter(FragmentManager fm, String[] channelList)
    {
        super(fm);
        this.channelList = channelList;
        this.fm=fm;
        System.out.println("A1");
    }


    //    getItem(int idx) 方法在滑动翻页时根据 idx 返回需要装入 ViewPager 的碎片。
    // getItem(int idx) 根据参数 idx 获取内导航栏目标签标题,然后用栏目标题作为参数实例化碎片 NewsChannelFragment:
    //getItem()方法,根据position(这里是idx)得到某一行的记录
    @Override
    public Fragment getItem(int idx)
    {
        if (idx==4)   //第5个内部碎片
        {
               return LFragment.get_list(news);  //返回数组
        }
         Log.e("FAdapter","getItem"+idx);
        String CategoryTitle = channelList[idx];
        System.out.println("A2");//不能在return之后加
        return ChannelFragment.newInstance(CategoryTitle);
    }
    //getCount()方法,得到数据的行数
    @Override
    public int getCount()
    {
        System.out.println("A3");
        return channelList.length;
    }
}

3、在活动中读取strings.xml中数组资源

①在strings.xml文件中新增数组资源

<resources>
    <string name="app_name">小粉书</string>
    <string-array name="channel">
        <item>关注</item>
        <item>学习</item>
        <item>兔兔</item>
        <item>运动</item>
        <item>新闻</item>
        <item>天气</item>
        <item>科技</item>
        <item>IT</item>
        <item>家人</item>
        <item>朋友</item>
        <item>诗歌</item>
        <item>绘画</item>
    </string-array>
</resources>

②在Home.java中新增如下代码,构建Home时向其传递数组资源

public class Home extends Fragment implements ViewPager.OnPageChangeListener
{
   private String[] channelList ;//获取strings文件里的内容
   
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
                  {
                    channelList = getResources().getStringArray(R.array.channel);
                  }
}

③完整的Home.java

package com.example.myapplication6;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.RadioButton;
import android.widget.RadioGroup;

/**
 * A simple {@link Fragment} subclass.
 */


// public class Home extends Fragment
//{
//         public Home()
//    {
//        // Required empty public constructor
//    }
//        @Override
//    public View onCreateView(LayoutInflater inflater, ViewGroup container,
//                             Bundle savedInstanceState)
//    {
//        // Inflate the layout for this fragment
//        return inflater.inflate(R.layout.activity_home, container, false);
//    }
//}


public class Home extends Fragment implements ViewPager.OnPageChangeListener
{
    private static final String ARG_CHANNEL_LIST = "channel_list";
    //以下声明 fragment_home.xml 对应的控件实例
    private View view = null;
    private RadioGroup rgChannel = null;
    private ViewPager viewPager;
    private HorizontalScrollView hvChannel = null;
//    private String[] channelList = {"关注", "学习", "兔兔", "运动", "新闻", "天气",
//                                    "科技","IT","家人","朋友","诗歌","绘画"};
   private String[] channelList ;//获取strings文件里的内容
    //要放在onCreateView方法里
//    private String[] channelList= getResources().getStringArray(R.array.channel);

    //栏目列表
    private FAdapter adapter;

    public Home()
    {
        // Required empty public constructor
        System.out.println("H1");
    }


//    原本
//    @Override
//    public View onCreateView(LayoutInflater inflater, ViewGroup container,
//                             Bundle savedInstanceState)
//    {
//        // Inflate the layout for this fragment
//        if(view==null)
//        {
//            view=inflater.inflate(R.layout.fragment_home, container, false);
//            viewPager=(ViewPager)view.findViewById(R.id.vpNewsList);
//            initViewPager();
//        }
//        return view;
//    }

    //单选按钮点击事件,实现ViewPager换页
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        if (view == null)
        {
            view = inflater.inflate(R.layout.activity_home, container, false);
            viewPager = (ViewPager) view.findViewById(R.id.vpNewsList);
            //获取strings里面的内容,要放在里面
            channelList = getResources().getStringArray(R.array.channel);
            initViewPager();
            //第二个
            rgChannel = (RadioGroup) view.findViewById(R.id.radiogroup);
            hvChannel = (HorizontalScrollView) view.findViewById(R.id.hvChannel);
            initTab(inflater); //初始化内导航标签
            rgChannel.setOnCheckedChangeListener( //单选按钮的监听事件响应
                    new RadioGroup.OnCheckedChangeListener()
                    {
                        @Override
                        public void onCheckedChanged(RadioGroup group, int checkedId)
                        {
                            viewPager.setCurrentItem(checkedId);
                            //实现两个方法显示内容
                        }
                    });
        }
        System.out.println("H2");
        return view;
    }

    //初始化内导航标签
    private void initViewPager()
    {
        FragmentManager fragmentManager = super.getActivity().getSupportFragmentManager();
        adapter = new FAdapter(fragmentManager, channelList);
        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(2);
        //viewPager.setCurrentItem(0);
        viewPager.addOnPageChangeListener(this);
        System.out.println("H3");
    }

    @Override
    public void onPageScrolled(int i, float v, int i1)
    {System.out.println("H4");
    }

    @Override
//某个碎片被选中时的动作,对应的内导航标签将要滑动到屏幕中央,并且有下划线显示
    public void onPageSelected(int i)
    {
        setTab(i); //后面再实现,控制导航栏保持一致
        System.out.println("H5");
    }

    @Override
    public void onPageScrollStateChanged(int i)
    {System.out.println("H6");
    }

    //设置选定某个碎片时水平滚动视图的显示 HorizontalScrollView
    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.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int screenWidth=metrics.widthPixels;
        int len=left+width/2-screenWidth/2;
        hvChannel.smoothScrollTo(len, 0);
        System.out.println("H7");
    }

    //初始化内导航标签,使用radiogroup布局构造各个单选按钮
    private void initTab(LayoutInflater inflater)
    {
        for(int i=0;i<channelList.length;i++)
        {//以下添加单选按钮的实例到内导航
            RadioButton rb=(RadioButton)inflater.inflate(R.layout.radiogroup, null);
            rb.setId(i);
            rb.setText(channelList[i]);
            RadioGroup.LayoutParams params=new
                    RadioGroup.LayoutParams(RadioGroup.LayoutParams.WRAP_CONTENT,
                    RadioGroup.LayoutParams.WRAP_CONTENT);
            rgChannel.addView(rb,params);
        }
        rgChannel.check(0); //第一个选项
        System.out.println("H8");
    }
}

4、效果图(此时点击新闻列表没有任何效果)

三、拓展:内导航碎片用ListView实现列表点击事件监听

1、新建Array.java文件,并设置如下:

package com.example.myapplication6;

import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;

import java.util.ArrayList;

public class Array extends Fragment
{
    // 存放传回的信息
    String[] news;
    // 存放列表数据
    ArrayList<String> datas = new ArrayList<>();
    // 存放新闻内容详细信息,作为后面的弹出信息
    public String[] info = {"经中美双方商定,北京时间11月16日上午同美国总统拜登举行视频会晤,就中美关系和双方共同关心的问题交换意见。现在会晤已开始举行。",
            "英国广播公司14日报道称,法国总统马克龙悄悄修改了法国国旗的颜色。就在去年(2020年),法国总统府已经悬挂上了带有新色调的旗帜,但并没有向外界宣布。法国官员向媒体透露,马克龙已将法国国旗三块颜色中的蓝色进行修改,用色调更深的海军蓝取代了原先较亮的颜色。外媒称,新的颜色是法国大革命的象征。",
            "据此前消息,MIUI 13 的很多系统界面都会有新 UX,带来新的用户交互体验。小米曾在 MIUI 12.5 中对视觉、听觉、触觉效果进行更新,是 MIUI 12 设计的延伸。",
            "11月16日晚间,科远智慧(002380)披露风险提示性公告称,全资子公司在浦发银行南通分行的4000万元定期存款,在存入当天就作为南通瑞豪国际贸易有限公司(以下简称南通瑞豪)开具银行承兑汇票的质押担保,由于后者未能按时偿债,导致科远智慧4000万元定期存款到期未能及时赎回。",
    "据外媒报道,15日,俄罗斯进行了一次反卫星试验,用一枚地基导弹摧毁了美国的一颗卫星,产生了数千块太空碎片,导致目前驻留在国际空间站的7名宇航员不得不躲进飞船避难。美方还称,这些碎片已经扩散到地球轨道,并可能威胁到所有国家的利益。",
    "联合国世界粮食计划署(WFP)15日向全球亿万富翁发出呼吁,请求他们捐赠66亿美元,让4200万人免遭饥荒,并公布了该笔资金的使用计划。马斯克曾经要求联合国向其证明自己的60亿美元财富如何解决全球饥饿问题。计划公布后,署长David Beasley在推特上向马斯克喊话,“这就是你要的明确计划,我们时刻准备和你沟通,也准备着和其他真切希望拯救生命的人进行交流。",
    "北京时间11月16日凌晨3点45分,2022年世界杯欧洲区预选赛C组,意大利客场对阵北爱尔兰。两支球队苦战90分钟均未能取得进球,最终0-0战平。C组最后一轮小组赛中瑞士4-0击败保加利亚,积分榜排名超过意大利升到了第1位,直接获得了卡塔尔世界杯的入场券,小组排名下滑到第2位的意大利将通过附加赛继续争夺世界杯参赛资格。"};

//创建函数返回一个fragment,因为onCreate和onCreateView方法返回值都不是一个实例化对象
    public static Array get_list(String []s)
    {
        // 回传数据到下方
        Bundle bundle = new Bundle();
        bundle.putStringArray("news",s);
        // 直接创建实例对象,目的是自动调用下方的函数,添加列表项并且设置监听
        Array fragment = new Array();
        // 数据传递到下方
        fragment.setArguments(bundle);
        return fragment;
    }
    public Array(){}

    @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        try {
            // 接收来自上方的信息
            Bundle bundle = getArguments();
            news = bundle.getStringArray("news");
        } catch (java.lang.NullPointerException e) {
           //  没有接收到显示报错
            System.out.println("TestFragment getArg error!");
        }
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list, container, false);
        ListView l = (ListView) view.findViewById(android.R.id.list);
        for (int i = 0; i < 100; i++) {
            datas.add(news[i%15]);
        }
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
                android.R.layout.simple_list_item_1,datas);
        l.setAdapter(adapter);
        l.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
//                Toast.makeText(getContext(),info[position%4],
//             Toast.LENGTH_LONG).show();
                new AlertDialog.Builder(getContext())
                        .setTitle("详细内容")
                        .setMessage(info[position%4])
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            }
                        }).show();
            };
        });
        return view;
    }
}

2、新建list.xml文件(注意:官方给出的id是android:id="@android:id/list")

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".Array">

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>

3、在获取碎片的方法中添加列表碎片

    @Override
    public Fragment getItem(int idx)
    {
        if (idx==4)   //第5个内部碎片
        {
             // return LFragment.get_list(news);  //返回数组
                return Array.get_list(news);  //返回列表碎片
        }
        ……
    }

4、效果图(点击新闻列表显示详细内容)

五、相关问题

1、单击某一个内导航按钮时,应用程序执行了哪些代码?请说明应用程序代码的对应执行过程。

①获取对应的内导航文本个数

//getCount()方法,得到数据的行数
@Override
public int getCount()
{
    System.out.println("A3");
    return channelList.length;
}

②getItem(int idx) 方法在滑动翻页时根据 idx 返回需要装入 ViewPager 的碎片,调用getItem方法创建新的Fragment,若之前已创建,则不会重复调用该方法

    // 虚函数,函数的目的就是为了生成新的Fragment对象
    @Override
    public Fragment getItem(int idx)
    {
        //如果是新闻的页面,采用列表碎片,否则直接用文本替换的简单碎片
        if (idx==4)   //第5个内部碎片
        {
//              return LFragment.get_list(news);  //返回数组
                 return Array.get_list(news);  //返回列表碎片
        }
        String CategoryTitle = channelList[idx];
        System.out.println("A2");//不能在return之后加
        // 获取当前的item,并色绘制对应的文本信息
        return ChannelFragment.newInstance(CategoryTitle);
}

③创建一个实例化对象,将数据传入到下方Oncreate()和OncreateView()方法,创建视图

public static ChannelFragment newInstance(String newsCategoryTitle)
{
    Bundle args = new Bundle();
    args.putString(ARG_CATEGORY_TITLE, newsCategoryTitle);
    // 传递参数给下方的Oncreat方法
    ChannelFragment fragment = new ChannelFragment();
    fragment.setArguments(args);
    System.out.println("C1");
    return fragment;
}

④生成对应的碎片,作为上一步的返回值(碎片)

public ChannelFragment() {
    // 空的构造函数,用来创建实例化对象,自动调用Oncreate和OncreatView方法
    System.out.println("C2");
}

⑤将获取到的文本传递到NewsChannelFragment实例化对象中

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    try {
        newsCategoryTitle = (String) getArguments().getString(ARG_CATEGORY_TITLE);
    } catch (java.lang.NullPointerException e) {
        System.out.println("TestFragment getArg error!");
    }
    System.out.println("C3");
}

⑥创建视图

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState)
{
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.activity_channel_fragment, container, false);
    mTitleField = (TextView) view.findViewById(R.id.newsCategoryTitle);
    mTitleField.setText(newsCategoryTitle);
    Log.e("ChannelFragment", "createView" + newsCategoryTitle);
    System.out.println("C4");
    return view;
}

⑦页面滑动时调用

@Override
public void onPageScrolled(int i, float v, int i1)
{System.out.println("H4");
}

⑧状态改变时调用

@Override
public void onPageScrollStateChanged(int i)
{System.out.println("H6");
}

⑨说明页面切换发生变化,调用setTab(i)方法

public void onPageSelected(int i)
{
    setTab(i); //后面再实现,控制导航栏保持一致
    System.out.println("H5");
}

⑩将对应序号的文本进行选择,会调用selector进行标绿,滚动条计算进行滚动。

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.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int screenWidth=metrics.widthPixels;
    int len=left+width/2-screenWidth/2;
    hvChannel.smoothScrollTo(len, 0);
    System.out.println("H7");
}

⑪内部导航栏RadioGroup的监听器立马响应,调用setCurrentItem(checkedId);跳转对应位置的页面

//单选按钮的监听事件响应
rgChannel.setOnCheckedChangeListener(
        new RadioGroup.OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId)
            {
            // 点击按钮切换到当前的页面,点击子导航跳转子页面
                viewPager.setCurrentItem(checkedId);
            }
        });

posted on 2021-11-17 16:10  sweetyy、  阅读(118)  评论(0)    收藏  举报