我们在一个activity中,并列显示两个Fragment,其中左边的显示图书列表,点击后在右边显示详情。
首先我们在mainActivity中的界面布局文件中划分两个部分。左边绑定ListFragment,右边放一个Fragment的容器
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:showDividers="middle"> <fragment android:id="@+id/book_list" android:name="com.example.fragment.BookListFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> <FrameLayout android:id="@+id/book_detail_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"> </FrameLayout> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
然后我们实现显示列表的ListFragment
1 package com.example.fragment; 2 3 import android.content.Context; 4 import android.os.Bundle; 5 import android.view.View; 6 import android.widget.ArrayAdapter; 7 import android.widget.ListView; 8 9 import androidx.annotation.NonNull; 10 import androidx.annotation.Nullable; 11 import androidx.fragment.app.ListFragment; 12 13 import com.example.fragment.model.BookManager; 14 15 import java.util.List; 16 17 public class BookListFragment extends ListFragment { 18 19 //定义一个回调接口,用于与Activity交互 20 private Callbacks myCallbacks; 21 interface Callbacks{ 22 void onItemSelected(int id); 23 } 24 25 @Override 26 public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) { 27 super.onListItemClick(l, v, position, id); 28 29 myCallbacks.onItemSelected(BookManager.ITEMS.get(position).id); 30 } 31 32 @Override 33 public void onAttach(@NonNull Context context) { 34 super.onAttach(context); 35 36 if(!(context instanceof Callbacks)){ 37 throw new IllegalStateException("没有实现Callbacks接口"); 38 } 39 myCallbacks = (Callbacks) context; 40 } 41 42 @Override 43 public void onCreate(@Nullable Bundle savedInstanceState) { 44 super.onCreate(savedInstanceState); 45 46 //为ListFragment设置Adapter 47 setListAdapter(new ArrayAdapter<>(getActivity(), 48 android.R.layout.simple_list_item_1, 49 android.R.id.text1, BookManager.ITEMS)); 50 } 51 52 53 @Override 54 public void onDetach() { 55 super.onDetach(); 56 myCallbacks = null; 57 } 58 }
主要包括,在activity加载fragment时,将回调接口绑定到activity。
这里Callbacks接口是我自定义的。我们的main_activtity实现了这个接口。
这样我们可以把fragment上的点击事件,传到main_activity上进行处理
此外,在实例化的时候,绑定一个ArrayAdapter,这个没什么好说的
在main_activity中实现onItemSelected方法:也就是获取图书详情,然后显示到右侧的fragment里面去
这里可以看到,是先创建了fragment,然后把Bundle传过去。那么fragment如何在初始化的时候获取Bundle中的参数呢。
我猜测是这样的:这些资源准备好之后,已经绑定好了,commit之后,fragment才正式被创建,所以读取到了要传递给它的参数。
然后我们看一下显示图书详情的fragment
package com.example.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; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.example.fragment.model.BookManager; public class BookDetailFragment extends Fragment { public static final String ITEM_ID = "item_id"; private BookManager.Book book; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(BookManager.CreatTAG,"调用bookDetailFragment的 oncreate方法"); if(getArguments().containsKey(ITEM_ID)){ Log.d(BookManager.CreatTAG,"bookDetailFragment中,读取 Bundle中的参数"); book = BookManager.ITEM_MAP.get(getArguments().getInt(ITEM_ID)); } } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { //return super.onCreateView(inflater, container, savedInstanceState); View rootView = inflater.inflate(R.layout.fragment_book_detail,container,false); if(book != null ){ ((TextView) rootView.findViewById(R.id.book_title)).setText(book.title); ((TextView) rootView.findViewById((R.id.book_desc))).setText(book.desc); } return rootView; } }
就是根据图书id,加载图书详情,没什么好说的。下面这个是加载View
最后给出图书管理类
package com.example.fragment.model; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BookManager { public final static String CreatTAG = "---SHOW_CREAT----"; //定义一个内部类,作为系统的业务对象 public static class Book{ public int id; public String title; public String desc; public Book(int id, String title, String desc) { this.id = id; this.title = title; this.desc = desc; } @Override public String toString() { return title; } } public static List<Book> ITEMS = new ArrayList<>(); public static Map<Integer,Book> ITEM_MAP = new HashMap<>(); static { addItem(new Book(1,"疯狂JAVA","十年沉淀的必读JAVA经典")); addItem(new Book(2,"疯狂JAVA2","十年沉淀的必读JAVA经典")); addItem(new Book(3,"疯狂JAVA3","十年沉淀的必读JAVA经典")); } private static void addItem(Book book){ ITEMS.add(book); ITEM_MAP.put(book.id,book); } }
项目结构如图