代码可能有点长,需要耐心看几遍。前前后后我看了5遍才把整个流程吃透,相信你一定比我聪明!!!
新建一个FragmentBestPractice项目 (让ADT帮我们自动创建活动--活动名:MainActivity 布局名:activity_main.xml)
1、准备好一个新闻的实体类: News
代码如下 :
package com.example.fragmentbestpractice;
public class News {
private String title;
private String content;
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title=title;}
public String getContent(){
return content;
}
public void setContent(String content){
this.content=content;
}
}
(title 字段表示新闻标题,content字段表示新闻内容。)
2、新建一个news_item.xml布局,用于作为新闻列表中子项的布局(ListView 中子项目的布局)。
代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/news_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true" // android:singleLine设置为True表示让这个TextView只能单行显示
android:ellipsize="end" // android:ellipsize 设定当文本内容超出控件宽度时,文本的缩略方式,这里指定成end表示在尾部进行缩略。
android:textSize="18sp" // android:textSize 设定文本字体大小
android:paddingLeft="10dp" // android:padding 表示给控件的周围加上补白,不至于让文本内容紧靠边缘。
android:paddingRight="10dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"/>
</LinearLayout>
3、创建新闻列表的适配器,让这个适配器继承ArrayAdapter,并泛型为News类
(由于News的数据无法直接传递给ListView,所以需要借助适配器)
代码如下:
package com.example.fragmentbestpractice;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class NewsAdapter extends ArrayAdapter<News> {
private int resourceId;
public NewsAdapter (Context context,int textViewResourceId,List<News>objects){
super(context,textViewResourceId,objects);
resourceId=textViewResourceId; // 重写父类ArrayAdapter的方法 ,textViewResourceId即为news_item.xml布局的id(ListView子项布局的id)
}
@Override
public View getView(int position,View convertView,ViewGroup parent){ //重写父类ArrayAdapterd的getView方法
News news=(News) getItem(position); // 得到当前ListView中子项的实例
View view;
if(convertView==null){
view=LayoutInflater.from(getContext()).inflate(resourceId,null ); //为实例加载布局(即为news_item.xml的布局,ListView子项的布局)
}
else{
view=convertView; //convertView参数:这个参数用于将之前加载好的布局进行缓存,提高ListView的运行效率
}
TextView newsTitleText=(TextView) view.findViewById(R.id.news_title); //实例化新闻标题
newsTitleText.setText(news.getTitle()); //让新闻的标题在列表中进行显示
return view;
}
}
4、编写新闻内容,新建news_content_frag.xml (为下文碎片NewsContentFragment提供布局)
(新闻内容的布局主要分为两部分:头部显示完整的新闻标题,正文部分显示新闻内容。)
代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/visibility_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible" > //android:visibility 设置布局的可见性,invisibe为不可见
<TextView
android:id="@+id/news_title" // 新闻标题的控件
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:textSize="20sp" />
<TextView
android:id="@+id/news_content" //新闻内容的控件
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="15dp"
android:textSize="18sp"/>
</LinearLayout>
<ImageView
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:scaleType="fitXY"
android:src="@drawable/ic_launcher" />"
</RelativeLayout>
5、新建一个NewsContentFragment类,继承自Fragment (碎片)
代码如下:
package com.example.fragmentbestpractice;
import android.app.Fragment; //注意这里可能会有两个不同包下的Fragment供你选择,建议使用android.app.Fragment(面向4.0以上系统的)
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class NewsContentFragment extends Fragment { //重写父类Fragment的方法
private View view;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
view=inflater.inflate(R.layout.news_content_frag, container,false); //为碎片加载布局news_content_frag.xml
return view;
}
public void refresh (String newsTitle, String newsContent){ //创建refresh()方法,这个方法用于将新闻的标题和内容显示在界面上
View visibilityLayout=view.findViewById(R.id.visibility_layout);
visibilityLayout.setVisibility(View.VISIBLE);
TextView newsTitleText=(TextView) view.findViewById(R.id.news_title); //得到新闻标题控件的实例
TextView newsContentText=(TextView) view.findViewById(R.id.news_content); //得到新闻内容控件的实例
newsTitleText.setText(newsTitle); //刷新新闻的标题
newsContentText.setText(newsContent); //刷新新闻的内容
}
}
6、创建一个在活动中使用的新闻内容布局,新建news_content.xml,为下文NewContentActivity提供布局(给小尺寸的android手机用的)
代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="@+id/news_content_fragment"
android:name="com.example.fragmentbestpractice.NewsContentFragment" //在布局中引入了com.example.fragmentbestpractice.NewsContentFragment
android:layout_width="match_parent" // (充分发挥了代码的复用性,相当于把new_content_frag.xml布局的内容自动加进来了)
android:layout_height="match_parent"/>
</LinearLayout>
7、新建一个活动,NewsContentActivity,作为显示新闻内容的活动(给小尺寸的手机用的)
代码如下:
package com.example.fragmentbestpractice;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
public class NewsContentActivity extends Activity {
public static void actionStart(Context context,String newsTitle,String newsContent){ //actionStart()方法,将启动NewsActivity所需要的参数导入进来
Intent intent=new Intent(context,NewsContentActivity.class);
intent.putExtra("news_title", newsTitle); //将参数新闻标题、新闻内容(参数)保存到intent中
intent.putExtra("news_content", newsContent);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState){ //重写父类Activity的onCreate方法
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //隐藏该活动自带的标题
setContentView(R.layout.news_content); //加载news_content.xml的布局
String newsTitle=getIntent().getStringExtra("news_title"); //取出Intent中保存的参数(即为新闻的标题、新闻的内容)
String newsContent=getIntent().getStringExtra("news_content");
NewsContentFragment newsContentFragment=(NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(newsTitle,newsContent); // 通过findFragment()方法,在活动中得到碎片NewsContentFragment的实例,从而调用其refresh()
}
}
8、创建新闻列表的布局,新建news_title_frag.xml
(这个布局并不是给活动使用的,而是给碎片使用的。)
代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView //定义了一个ListView控件 (作为显示新闻列表)
android:id="@+id/news_title_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
9、创建一个碎片加载news_title_frag.xml的布局 。新建NewsTitleFragment类,继承自Fragment
代码如下:
package com.example.fragmentbestpractice;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class NewsTitleFragment extends Fragment implements OnItemClickListener {
private ListView newsTitleListView;
private List<News> newsList;
private NewsAdapter adapter;
private boolean isTwoPane;
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
newsList=getNews(); //初始化新闻数据
adapter=new NewsAdapter(activity,R.layout.news_item,newsList);
}
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
View view=inflater.inflate(R.layout.news_title_frag, container,false); //加载news_title_frag.xml 布局
newsTitleListView=(ListView) view.findViewById(R.id.news_title_list_view); //得到ListView的实例
newsTitleListView.setAdapter(adapter); //启动ListView的适配器,这样ListView就能与适配器的数据相关联了
newsTitleListView.setOnItemClickListener(this); //为ListView中的子项设置监听器
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
if (getActivity().findViewById(R.id.news_content_layout) !=null){ //判断是平板还是手机,即为双页模式还是单页模式
isTwoPane=true; // isTwoPane=true ,表示双页模式
}
else{
isTwoPane=false; //isTwoPane=false,表示单页模式
}
}
@Override
public void onItemClick(AdapterView<?> parent,View view,int position,long id){ //ListView子项目的点击事件
News news=newsList.get(position);
if(isTwoPane){
NewsContentFragment newsContentFragment=(NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(news.getTitle(),news.getContent()); //如果是双页模式(平板),就更新新闻内容碎片里数据
}
else{
NewsContentActivity.actionStart(getActivity(),news.getTitle(),news.getContent()); //如果是单页模式(手机),就启动一个新的活动去显示新闻内容。
}
}
private List<News> getNews(){
List<News> newsList=new ArrayList<News>(); //初始化新闻标题及内容
News news1=new News();
news1.setTitle("Succeed in College as a Learning Disabled Student");
news1.setContent("College freshmen will soon learn to live with a roommate,adjust to a new social scene and survive less-than-stellae dining ball food.Students with learning disabilities will face these transitions while also grappling with a few more hurdles.");
newsList.add(news1);
News new2=new News();
new2.setTitle("Google Android exec poached by China's Xiaomi");
new2.setContent("China's Xiaomi has poached a key google executive involed in the tech giant's Android phones,in a move seen as a coup for the rapidly growing Chinese smartphone market.");
newsList.add(new2);
return newsList;
}
}
10、修改主活动的布局文件 activity_main.xml (如果是单页模式,只会加载一个新闻标题的碎片)
代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="@+id/news_title_fragment"
android:name="com.example.fragmentbestpractice.NewsTitleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
11、在res 下新建一个文件夹layout-sw600dp ,在这个文件夹下新建一个activity_main.xml布局文件。(如果是双页模式,则会加载两个碎片)
(使用最小宽度限定符Smallest-width Qualifier,ws600dp表示:屏幕宽度大于600dp的设备就加载这个文件下的布局)
代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false" >
<fragment
android:id="@+id/news_title_fragment" //新闻标题的碎片
android:name="com.example.fragmentbestpractice.NewsTitleFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="@+id/news_content_layout" //新闻内容的碎片
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" >
<fragment
android:id="@+id/news_content_fragment"
android:name="com.example.fragmentbestpractice.NewsContentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
12、最后再将MainActivity稍做修改,把标题栏去掉。
代码如下:
package com.example.fragmentbestpractice;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //去掉自带的标题
setContentView(R.layout.activity_main);
}
}
13、最后记得在AndroidManifest.xml 注册新建的NewsContentActivity活动。(凡是活动,都必须在AndroidManifest.xml注册,才可以用)
代码如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.fragmentbestpractice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter> //<intent-filter>里面的两句话表示MainActivity为主活动
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".NewsContentActivity" > //注册NewsContentActivity活动
</activity>
</application>
</manifest>
这样,一个简易版的新闻应用就大功告成了!!!