Android学习笔记十五.深入理解fragment(三) 之《兼容多分辨率的应用》实战
<?xml version="1.0" encoding="utf-8"?> <resources> <!--定义activity_book_list实际引用@layout/activity_book_twopane资源 --> <item type="layout" name="activity_book_list"> @layout/activity_book_twopane</item> </resources>
<?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:name="com.example.android_fragment_1.BookListFragment" android:id="@+id/book_list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="16dp" android:layout_marginLeft="16dp"/>
这个布局文件就定义了Activity的显示界面:左边将会显示一个ListFragment,右边只是一个FrameLayout容器。其中FrameLayout容器将会动态更新其中显示的Fragment。
<?xml version="1.0" encoding="utf-8"?> <!-- 定义一个水平排列的LinearLayout,并指定使用中等分隔条 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:divider="?android:attr/dividerHorizontal" android:showDividers="middle"> <!-- 使用资源文件方式:添加一个fragment到Activity中 --> <fragment android:name="com.example.android_fragment_1.BookListFragment" android:id="@+id/book_list" android:layout_height="match_parent" android:layout_width="0dp" android:layout_weight="1"/> <!-- 添加一个FrameLayout容器,用于显示图书详细信息 --> <FrameLayout android:id="@+id/book_detail_container" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3"/> </LinearLayout>
package com.example.android_fragment_1; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class BookListActivity extends Activity implements BookListFragment.Callbacks { //1.定义一个旗标,用于标识是否该应用是否支持大屏幕 private boolean mTwoPane; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //2.指定加载activity_book_list对应的界面布局文件,实际上会根据分辨率选择相应的布局界面 setContentView(R.layout.activity_book_list); //3.如果加载的界面布局文件中包含ID为book_detail_container的组件,则说明支持大屏幕 if(findViewById(R.id.book_detail_container)!=null) { mTwoPane=true; //支持大屏幕 ((BookListFragment)getFragmentManager() .findFragmentById(R.id.book_list)) .setActivateOnItemClick(true); } } //4.实现Fragment与Activity交互方法 @Override public void onItemSelected(Integer id) { /*如果加载的是大屏幕布局界面文件*/ if(mTwoPane) { //a.创建Bundle,准备向Fragment传入参数(将键值对绑定到arguments对象中) Bundle arguments=new Bundle(); arguments.putInt(BookDetailFragment.ITEM_ID,id); //b.创建BookDetailFragment对象,并向Fragment传入参数 BookDetailFragment fragment=new BookDetailFragment(); fragment.setArguments(arguments); //c.使用fragment替换book_detail_container容器当前显示的Fragment getFragmentManager().beginTransaction() .replace(R.id.book_detail_container, fragment).commit(); } /*如果加载的是小屏幕布局界面文件*/ else { //a.创建启动BookDetailActivity的Intent Intent detailIntent=new Intent(this,BookDetailActivity.class); //b.设置传递给BookDetailActivity参数,并启动Activity detailIntent.putExtra(BookDetailFragment.ITEM_ID, id); startActivity(detailIntent); } } }
package com.example.android_fragment_1; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.MenuItem; public class BookDetailActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); //1.指定加载/res/layout目录下的activity_book_detail.xml布局文件 setContentView(R.layout.activity_book_detail); //2.将ActionBar上应用图标转换成可点击的按钮 getActionBar().setDisplayHomeAsUpEnabled(true); if(savedInstanceState==null) { //a.创建BookDetailFragment对象 BookDetailFragment fragment=new BookDetailFragment(); //b.创建Bundle对象 Bundle arguments=new Bundle(); arguments.putInt(BookDetailFragment.ITEM_ID, getIntent() .getIntExtra(BookDetailFragment.ITEM_ID,0)); //c.向Fragment传入参数 fragment.setArguments(arguments); //d.指定fragment添加到book_detail_container容器中 getFragmentManager().beginTransaction() .add(R.id.book_detail_container, fragment).commit(); } } //3.按下图标响应 @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub if(item.getItemId()==android.R.id.home) { //a.创建启动BookListActivity的Intent Intent intent=new Intent(this,BookListActivity.class); //b.添加额外的Flag,将Activity栈中处于FirstActivity之上的Activity弹出 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); //c.启动intent对应的Activity startActivity(intent); return true; } return super.onOptionsItemSelected(item); } /res/layout目录下的activity_book_detail.xml布局文件 该界面布局文件内只定义了一个ID名为book_detail_container的FrameLayout,用于显示图书详情。 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/book_detail_container" > </FrameLayout>
package com.example.android_fragment_1; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /*功能: * 使用Fragment将会显示加载一份简单的界面布局文件,并根据传入的参数来更新 * 界面组件*/ public class BookDetailFragment extends Fragment { public static final String ITEM_ID="item_id"; BookContent.Book book; //保存该Fragment显示的book对象 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //如果启动该Fragment时包含了ITEM_ID参数,其中 Map containsKey(String Key) 判断key有没有对应的value值; 有,则返回true 没有,则返回false //从Bundle对象中获取传入的参数(键值对) if(getArguments().containsKey(ITEM_ID)) { book=BookContent.ITEM_MAP.get(getArguments().getInt(ITEM_ID)); //获取启动该Fragment时传入的ITEM_ID参数并根据该ID获取BookContent的ITEM_MAP中的图书信息? } } //2.重写该方法:该方法返回的View将作为Fragment显示的组件 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //a.加载/res/layout/目录下的fragment_book_detail.xml布局文件,返回一个view目的使该fragment的布局显示在Activity中 View view=inflater.inflate(R.layout.fragment_book_detail, //指明当前fragment的资源文件 container, //父容器控件 false); //表明是否连接该布局和其父容器控件(这里系统已经插入了布局到父容器中) /*将图书信息中的标题、属性显示在容器的两个文本框中*/ if(book!=null) { //b.让book_title文本框显示book对象的title属性 ((TextView) view.findViewById(R.id.book_title)).setText(book.title); //c.让book_desc文本框显示book对象的desc属性 ((TextView) view.findViewById(R.id.book_desc)).setText(book.desc); } return view; } }
package com.example.android_fragment_1; import android.app.Activity; import android.app.ListFragment; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; public class BookListFragment extends ListFragment { //1.定义一个回调接口Callback,用于实现该Fragment与它所在的Activity交互(注意:该接口的实现需要在Activit中) private Callbacks mCallbacks; //Callbacks接口对象 public interface Callbacks { public void onItemSelected(Integer id); //参数为Map集合的键 } //2.onCreate方法中为该ListFragment设置Adapter,让该ListFragment显示该Adapter所提供的多个列表项 @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setListAdapter(new ArrayAdapter<BookContent.Book>(getActivity(),// android.R.layout.simple_list_item_activated_1, android.R.id.text1, BookContent.ITEMS)); // } //3.调用该方法将Fragment添加并显示到Acitvity中 @Override public void onAttach(Activity activity) { // TODO Auto-generated method stub super.onAttach(activity); //a.如果Activity中没有实现Callbacks接口,抛出异常 if(!(activity instanceof Callbacks)) { throw new IllegalStateException("异常:BookListFragment所在的Activity必须实现Callback接口!"); } //把该Activity当成Callbacks对象(就是这一句导致出现NullPointerException错误) mCallbacks=(Callbacks)activity; } //4.当该Fragment从他所属的Acitivity中被删除时,调用该方法 @Override public void onDetach() { super.onDetach(); mCallbacks=null; //将mCallbacks赋值为null } //5.当用户单击某列表项时激发该回调方法 @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); mCallbacks.onItemSelected(BookContent.ITEMS.get(position).id);//激发mCallbacks接口的onItemSelected方法 } public void setActivateOnItemClick(boolean activateOnItemClick) { getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE:ListView.CHOICE_MODE_NONE); } }
package com.example.android_fragment_1; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BookContent { //1.定义一个内部类,作为系统的业务对象 public static class Book { public Integer id; //Map键 public String title; public String desc; public Book(Integer id,String title,String desc)//构造函数,初始化图书详情的"map键,标题,内容" { this.id=id; this.title=title; this.desc=desc; } public String toString() { return title; } } //2.使用List集合记录系统所包含的Book对象ITEMS,利用它调用其add(对象)方法项List集合中添加列表项 public static List<Book> ITEMS=new ArrayList<Book>(); //3.使用Map集合记录系统所包含的Book对象ITEM_MAP,利用它调用put(Key,Value)方法向Map集合中添加列表项 public static Map<Integer,Book> ITEM_MAP =new HashMap<Integer,Book>(); static{ //使用静态初始化代码,将Book对象添加到List集合、Map集合中 addItem(new Book(1,"疯狂Android讲义","个人评价:这本书很好,就是有点厚!")); addItem(new Book(2,"数学之美","个人评价:来自自然语音的使者")); addItem(new Book(3,"大话数据结构","个人评价:不知道怎样,听说很不错")); } private static void addItem(Book book) { // TODO Auto-generated method stub ITEMS.add(book); //添加List集合中列表项 ITEM_MAP.put(book.id,book);//添加Map集合中列表项 } }
<application .......> <activity android:name=".BookListActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".BookDetailActivity" android:label="@string/app_name" > </activity> </application> </manifest>
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。