利用Fragment編寫簡易新聞介面,佈局同時適應Android手機和平板電腦
大家好,最近從事培訓工作碰到一個練習題,利用Fragment編寫簡易新聞介面,並且佈局能同時適應手機和平板電腦,這是書本上的一個練習題,題目本身沒多大難度,個人覺得作者程式碼的模組化做得比較好,所以拿出來分享,同時自己學習也複習、鞏固一下。
首先大體介紹下介面佈局,如下圖:
分為手機、平板兩個介面:
對於手機介面是個ListView,各個項顯示新聞標題,點選某ListView的某一項跳轉到另一個Activity顯示新聞正文;
對於平板電腦介面,左邊是個ListView,用於顯示新聞標題,右邊是垂直襬放的兩個TextView,分別顯示新聞標題和新聞內容,這兩邊都是Fragment。
下面介紹程式碼,佈局的具體實現。
1、新建News.java類,用於管理儲存、獲取新聞資料的類,程式碼如下:
package com.gta.newsapptest; public class News { private String title; private String content; public News() { } public String getTitle(){ return this.title; } public String getContent(){ return content; } public void setTitle(String title){ this.title = title; } public void setContent(String content){ this.content = content; } }
2、在Layout檔案下新建new_item.xml,此檔案會被載入到ListView的單項中,裡面只是一個TextView,用於顯示新聞標題,程式碼如下:
3、新建NewsAdapter.java,此類繼承ArrayAdapter<News>介面卡,通過getView()方法給ListView的每一項填充new_item.xml佈局和新聞標題資料,程式碼如下:<?xml version="1.0" encoding="utf-8"?> <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:ellipsize="end" android:textSize="18sp" android:paddingLeft="10dp" android:paddingTop="15dp" android:paddingRight="10dp" android:paddingBottom="15dp"/> </LinearLayout>
package com.gta.newsapptest;
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 static final String TAG = "TAG";
private int resourceId;
public NewsAdapter(Context context, int resource, List<News> objects) {
super(context, resource, objects);
resourceId = resource;
// Log.d(TAG, objects.size() + "");
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// super.getView(position, convertView, parent);
View view ;
// News news = newsList.get(position);
News news = getItem(position);//獲取position位置的新聞資料
// Log.d(TAG, news.getTitle());
//如果當前項檢視沒有載入佈局,則進行載入否則直接從converView物件中獲取,防止重複載入降低效率
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
}
else {
view = convertView;
}
TextView tv = (TextView) view.findViewById(R.id.news_title);
tv.setText(news.getTitle());
return view;
}
}
4、在Layout檔案下新建news_title_frag.xml檔案,此檔案中放置一個ListView控制元件用於顯示新聞標題,下一步將在Fragment中載入此佈局檔案,程式碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/news_title_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
到這裡ListView新聞列表佈局已經完成,下面編寫新聞標題和內容佈局
5、在layout檔案下新建news_content_frag.xml檔案,此檔案的作用是為新聞的標題和正文設定佈局,分別是兩個TextView,同時下一步將會繼承Fragment載入此佈局,程式碼如下:<?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" >
<LinearLayout
android:id="@+id/visibility_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible">
<TextView
android:id="@+id/news_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="10dp"
android:textSize="20sp"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000"/>
<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:background="#000000"/>
</RelativeLayout>
6、新建NewsContentFragment.java類,此類繼承Fragment載入news_content_frag.xml佈局,同時編寫refresh()函式用於重新整理新聞標題和資料,程式碼如下:
package com.gta.newsapptest;
import android.app.Fragment;
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 {
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
//載入news_content_frag.xml佈局
view = inflater.inflate(R.layout.news_content_frag, container, false);
return view;
}
/**
* 用於重新整理新聞標題和內容
* @param newsTitle
* @param newsContent
*/
public void refresh(String newsTitle, String newsContent){
View visibilityLayout = view.findViewById(R.id.visibility_layout);
visibilityLayout.setVisibility(View.VISIBLE);
TextView title = (TextView) view.findViewById(R.id.news_title);
title.setText(newsTitle);
TextView content = (TextView) view.findViewById(R.id.news_content);
content.setText(newsContent);
}
}
7、新建news_content.xml檔案,此檔案定義了一個fragment和NewsContentFragment類相關聯,下一步將在Activity中直接設定這個佈局檔案顯示新聞內容,程式碼如下:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.gta.newsapptest.NewsContentFragment"/>
</LinearLayout>
8、新建NewsContentActivity.java類,此類用於載入news_content.xml佈局顯示新聞標題和正文內容,裡面有一個靜態的actionStart()方法用於從任意活動跳轉到當前活動,程式碼如下:
package com.gta.newsapptest;
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{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去掉標題欄
requestWindowFeature(Window.FEATURE_NO_TITLE);
//設定活動佈局
setContentView(R.layout.news_content);
//獲取傳入此活動的新聞標題
String newsTitle = getIntent().getStringExtra("news_title");
//獲取傳入此活動的新聞內容
String newsContent = getIntent().getStringExtra("news_content");
//獲取NewsContentFragment類
NewsContentFragment contentFragment = (NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);
//呼叫NewsContentFragment中refresh方法重新整理新聞內容
contentFragment.refresh(newsTitle, newsContent);
}
public static void actionStart(Context context, String newsTitle, String newsContent){
Intent intent = new Intent(context, NewsContentActivity.class);
intent.putExtra("news_title", newsTitle);
intent.putExtra("news_content", newsContent);
context.startActivity(intent);
}
}
9、新建NewsTitleFragment.java,這個類比較關鍵,繼承了Fragment重寫onCreateView()函式載入news_title_frag.xml佈局,繼承OnItemClickListener監聽器重寫onItemClick()函式設定ListView的每一項點選監聽,程式碼如下:
package com.gta.newsapptest;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.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.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class NewsTitleFragment extends Fragment implements OnItemClickListener {
private static final String TAG = "TAG";
private ListView newsTitleListView;
private List<News> newsList; //儲存所有的新聞資料
private NewsAdapter adapter;
private boolean isTwoPane; //是平板寬屏值為true,手機屏值為false
/**
* 系統回撥函式,在活動和碎片開始建立關聯時呼叫
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
newsList = getNews(); //初始化新聞資料
//將ListView單項佈局和新聞資料載入到Adapter中
adapter = new NewsAdapter(activity, R.layout.new_item, newsList);
// Log.d(TAG, "onAttach(): " + newsList.get(0).getTitle());
// Log.d(TAG, "onAttach()");
}
/**
* 載入碎片佈局時會被自動呼叫
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
//為Fragment載入佈局
View view = inflater.inflate(R.layout.news_title_frag, container, false);
newsTitleListView = (ListView) view.findViewById(R.id.news_title_list_view);
//為ListView設定介面卡,將新聞標題顯示在每一項
newsTitleListView.setAdapter(adapter);
//設定ListView每一項點選監聽事件
newsTitleListView.setOnItemClickListener(this);
Log.d(TAG, "onCreateView()");
return view;
}
/**
* 碎片和活動建立關聯完成時會被自動呼叫
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//這裡判斷news_content_layout控制元件是否存在,即可判斷是手機還是平板電腦
if(getActivity().findViewById(R.id.news_content_layout) != null){
isTwoPane = true;
}
else {
isTwoPane = false;
}
Log.d(TAG, "onActivityCreated()");
}
/**
* 此函式將返回儲存在List中的模擬新聞資料
* @return
*/
private List<News> getNews() {
List<News> newsList = new ArrayList<News>();
News news1 = new News();
news1.setTitle("Succeed in Cllege as a Learning Disabled Student");
news1.setContent("College freshmen will soon learn to live with a roomote, adjust to a new social " +
"scene and survive less-than-stellar dining hall food. Students with learning disabilities will face these" +
"transitions while also grappling with afew more hurdles.");
newsList.add(news1);
News news2 = new News();
news2.setTitle("Google Android exec poacjed byChina's Xiaomi");
news2.setContent("China's Xiaomi has poached a key Google executive involved in the tech giant's Android phones," +
"in a move seen as a coup for the rapidly growing Chinese smartphone maker.");
newsList.add(news2);
return newsList;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
News news = newsList.get(position);
if(isTwoPane){
//是平板電腦,則為右邊NewsContentFragment設定新聞標題和內容
NewsContentFragment newsContentFragment = (NewsContentFragment) getFragmentManager().findFragmentById(R.id.news_content_fragment);
newsContentFragment.refresh(news.getTitle(), news.getContent());
}
else {
//是手機,則直接跳轉到NewsContentActivity
NewsContentActivity.actionStart(getActivity(), news.getTitle(), news.getContent());
}
}
}
10、到此為止程式框架基本完成,下面編寫主介面;
11、在layout下的activity_main.xml檔案中新增fragment,程式碼如下:
<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" >
<fragment
android:id="@+id/new_title_fragment"
android:name="com.gta.newsapptest.NewsTitleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
12、判別是手機、平板電腦的螢幕需要用到限位符的概念,操作比較簡單,首先在 res/下面建立layout-sw600dp資料夾(意思是螢幕寬度大於600個畫素時呼叫其下面的佈局檔案,其中sw600dp就是限位符),然後新建activity_main.xml檔案在裡面新增如下程式碼:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:id="@+id/news_title_fragment"
android:name="com.gta.newsapptest.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.gta.newsapptest.NewsContentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
現在可以在不修改佈局的情況下同時執行在手機和平板上。
下載地址:http://download.csdn.net/detail/yanwenmuc/9202955