Fragment & ViewPager

Fragment & ViewPager

一、Fragment

1.fragment加载

(1)静态加载fragment
  • 创建一个fragment,在其xml布局文件中添加如下代码,实现点击按钮切换文字的效果

    <?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:orientation="vertical"
        tools:context=".BlankFragment1">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:id="@+id/textview"
            android:text="@string/hello_blank_fragment" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:text="how are you?"
            android:id="@+id/btn"/>
    
    </LinearLayout>
    
  • 在fragment.java文件中,添加逻辑代码

public class BlankFragment1 extends Fragment {
private View root;
private TextView textView;
private Button button;

public BlankFragment1(){}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    //如果为空
    if (root == null) {
        root = inflater.inflate(R.layout.fragment_blank1, container, false);
    }
    //添加控件的点击事件
    textView = root.findViewById(R.id.textview);
    button = root.findViewById(R.id.btn);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            textView.setText("Yes,I am,and you?");
        }
    });
    return  root;
}

}
```

刚才创建的fragment要继承Fragment类,里面会自动添加几个方法,这几个方法与fragment的声明周期有关系,可以自己研究一下fragment的生命周期,fragment就是一个小型的activi。

  • 在mainactivity的xml布局文件中,添加刚才我们创建的fragment,实现对fragment的绑定
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <fragment android:name="com.example.fragmentbase.BlankFragment1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/fragment1"/>

</LinearLayout>

这样就实现了fragment的静态加载

(2)fragment的动态加载
  • 在主活动的xml文件中加上如下代码,通过button实现页面的切换
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:text="@string/change"></Button>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn_2"
        android:text="@string/replace"></Button>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/framelayout"
        android:background="@color/colorAccent"></FrameLayout>

</LinearLayout>
  • 创建一个fragment 名为BlankFragment1

    • 创建一个fragment 名为 ItemFragment
  • 主活动的.java文件中添加以下代码:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button button = findViewById(R.id.btn);
            button.setOnClickListener(this);
            Button button2 = findViewById(R.id.btn_2);
            button2.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.btn:
                    BlankFragment1 bf = new BlankFragment1();
                    replaceFragment(bf);
                    break;
                case R.id.btn_2:
                    replaceFragment(new ItemFragment() );
    
            }
        }
    
        // 动态切换fragment
        private void replaceFragment(Fragment fragment) {
            //获取fragment的管理类,来管理fragment
            FragmentManager fragmentManager = getSupportFragmentManager();
            //设置触发器,得到FragmentTransaction,fragment的替换动作由beginTransaction完成
            FragmentTransaction transation = fragmentManager.beginTransaction();
            //把需要的id替换进去
            transation.replace(R.id.framelayout, fragment);
            //把fragment添加到一个栈里面去
            transation.addToBackStack(null);
            //必须提交才能执行!
            transation.commit();
        }
    }
    

至此就完成了fragment的动态添加

" 动态添加fragment的过程分为5步来执行":

1.创建一个待处理的fragment;

2.获取FragmentManager,一般都是通过getSupportFragmentManager();

3.开启一个事务transaction,调用transaction的beginTransaction()

4.使用transaction进行fragment的替换

5.提交事务

2.Activity 与 Fragment 的通信

(1)原生方案:Bundle
  • 把上面的主活动中oncreate()代码修改如下:

@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn:
//定义一个Bundle
Bundle bundle = new Bundle();
bundle.putString(“message”, " i love you");
//添加一个fragment
BlankFragment1 bf = new BlankFragment1();
//向一个fragment中传递参数
bf.setArguments(bundle);
bf.setFragmentCallback(new IFragmentCallback() {
@Override
public void sendMsgToActivity(String msg) {
Toast.makeText(MainActivity.this,msg, Toast.LENGTH_SHORT).show();
}

                @Override
                public String getMsgFromActivity(String msg) {
                    return "hello, I am from activity";
                }
            });

            replaceFragment(bf);
            break;
        case R.id.btn_2:
            replaceFragment(new ItemFragment() );

    }
}

##### (2)接口

* 定义一个接口 命名为 IFragmentCallback

```java
public interface IFragmentCallback {
   void sendMsgToActivity(String msg);
   String getMsgFromActivity(String msg);
}
  • 在fragment的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=".BlankFragment1">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/hello_blank_fragment" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:id="@+id/btn_3"
            android:text="数据传递"/>
    
    </FrameLayout>
    
  • 在fragment中修改代码;

    public class BlankFragment1 extends Fragment {
        private static final String TAG = "BlankFragment1";
        private View rootview;
    
    
        public BlankFragment1() {
            // Required empty public constructor
        }
    
        private IFragmentCallback fragmentCallback;
        public void setFragmentCallback(IFragmentCallback callback){
            fragmentCallback = callback;
        }
    
        @Override
        public void onAttach(@NonNull Context context) {
            super.onAttach(context);
            Log.d(TAG, "onAttach: ");
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Bundle bundle = this.getArguments();
            String string = bundle.getString("message");
            Log.d(TAG, "onCreate: " + string);
    
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            if (rootview == null){
                rootview = inflater.inflate(R.layout.fragment_blank1, container, false);
            }
            Button btn = rootview.findViewById(R.id.btn_3);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    //                fragmentCallback.sendMsgToActivity("hello, I'm from Fragment");
                    String msg = fragmentCallback.getMsgFromActivity("null");
                    Toast.makeText(BlankFragment1.this.getContext(), msg, Toast.LENGTH_SHORT).show();
                }
            });
            Log.d(TAG, "onCreateView: ");
            return rootview;
        }
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.d(TAG, "onActivityCreated: ");
        }
    
(3)Fragment的生命周期
  • 打开页面 onCreate()-> onCreateView() -> onActivityCreated() -> onStart() -> onResume()
  • 按下主屏键 onPause() -> onStop()
  • 重新打开界面 onStart() -> onResume()
  • 按back键 onPause() -> onStop() -> onDestroyView() -> onDestroy() -> onDetach()

二、ViewPager

1.viewpager用法:

  • 创建几个layout做准备(两个或两个以上,代码不展示了)

  • 主活动xml文件中 添加以下代码当做viewpage的容器

    <androidx.viewpager.widget.ViewPager
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:id="@+id/vp" />
    
  • 在主活动 .java 文件中绑定ViewPagr控件

    ViewPager viewPager = findViewById(R.id.vp);
    
  • 创建viewPager适配器

    public class MyAdapter extends PagerAdapter {
    
        private List<View> mlist;
    
        public MyAdapter(List<View> mlist){
            this.mlist = mlist;
        }
    
        //返回viewPager的数量
        @Override
        public int getCount() {
            return mlist.size();
        }
    
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            //拿到对应位置的view
            container.addView(mlist.get(position),0);
            return mlist.get(position);
        }
    
        //判断是否相等
        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            return false;
        }
    }
    
    
  • 主活动中添加如下代码:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ViewPager viewPager = findViewById(R.id.vp);
    
    
            //进行数据的渲染,拿到数据
            LayoutInflater lf = getLayoutInflater().from(this);
            View view1 = lf.inflate(R.layout.layout1,null);
            View view2 = lf.inflate(R.layout.layout2,null);
            View view3 = lf.inflate(R.layout.layout3,null);
    
            //渲染数据到主界面上
            List<View> viewList = new ArrayList<>();
            viewList.add(view1);
            viewList.add(view1);
            viewList.add(view1);
    
            MyAdapter myAdapter = new MyAdapter(viewList);
            viewPager.setAdapter(myAdapter);
    
        }
    }
    

    然后运行项目就可以了。viewpager滑动效果就可以了

2.viewPager与Fragment 嵌套使用形成翻页效果

  • 在主活动的xml文件中修改代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <androidx.viewpager2.widget.ViewPager2
       android:layout_width="match_parent"
       android:layout_height="match_parent"
      android:id="@+id/viewPager"
      android:background="@color/colorAccent">

   </androidx.viewpager2.widget.ViewPager2>

</LinearLayout>
  • 添加一个ViewPager数据适配器

    public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewPagerViewHolder> {
        private List<String> titles = new ArrayList<>();
        private List<Integer> colors = new ArrayList<>();
    
        public ViewPagerAdapter(){
            titles.add("1");
            titles.add("2");
            titles.add("3");
            titles.add("4");
            titles.add("5");
            titles.add("6");
            titles.add("7");
            titles.add("8");
            titles.add("9");
            titles.add("10");
    
            colors.add(R.color.white);
            colors.add(R.color.black);
            colors.add(R.color.red);
            colors.add(R.color.colorAccent);
            colors.add(R.color.colorPrimary);
            colors.add(R.color.white);
            colors.add(R.color.black);
            colors.add(R.color.red);
            colors.add(R.color.colorPrimary);
            colors.add(R.color.white);
    
        }
        @NonNull
        @Override
        public ViewPagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new ViewPagerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pager, parent, false));
        }
    
        @Override
        public void onBindViewHolder(@NonNull ViewPagerViewHolder holder, int position) {
            holder.mTv.setText(titles.get(position));
            holder.mContainer.setBackgroundResource(colors.get(position));
        }
    
        @Override
        public int getItemCount() {
            return 10;
        }
    
        class ViewPagerViewHolder extends RecyclerView.ViewHolder{
            TextView mTv;
            RelativeLayout mContainer;
            public ViewPagerViewHolder(@NonNull View itemView) {
                super(itemView);
                mContainer = itemView.findViewById(R.id.container);
                mTv = itemView.findViewById(R.id.tvTitle);
            }
        }
    }
    

    这个适配器和 RecycleView 的数据适配器其实一样的,不懂得可以看看我的另外一篇文章RecycleView的使用及优化

  • 新建一个xml文件,作为viewPager的页面展示效果

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/container">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:id="@+id/tvTitle"
        android:layout_centerInParent="true"
        android:textColor="#ff4532"
        android:textSize="32dp"
        android:text="hello"></TextView>
</RelativeLayout>
  • 最后在主活动中修改代码:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ViewPager2 viewPager = findViewById(R.id.viewPager);
            ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter();
            viewPager.setAdapter(viewPagerAdapter);
        }
    }
    
上一篇:android笔试题!腾讯团队实力打造flutter入门教程,我先收藏为敬


下一篇:不可不会的Fragment