为了适应Handset和Tablet等不同分辨率的android设备,google在android3.0之后提供了一个新的API,也就是Fragment,大家可以查阅官方SDK的详细说明。
以下是摘自官方SDK 的一张设计图,很好地展示了Fragment在兼容Tablet和Handset设备的设计理念。
首先解释一下,上述的设计原理。
1.针对Tablet,Activity A中包含了Fragment A和Fragment B,而Handset中的Activity A中只包含了Fragment A,至于Fragment B则通过对Fragment A的事件监听,来启动新的Activity B(包含Fragment B)将Fragment B显示给用户。
既然这样的话就必须用到两个布局,layout目录下默认存放的是Handset的布局,layout-large目录下存放的则是Tablet的布局。
更详细的请参考:http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html
2.接着看如何在布局中定义Fragment
参考一下配置文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <fragment class="com.test.fragment.ItemActivity" android:id="@+id/item" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="3" /> <fragment class="com.test.fragment.ContentActivity" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>
3.系统内置了3种Fragment
DialogFragment:对话框式Fragment,管理模式类似与AlertDialog等对话框,允许用户返回之前的Fragment。
ListFragment:类似于ListActivity,并且提供了类似的功能,用法基本差不多。
PreferenceFragment:类似于PreferenceActivity,用法也差不多,可用来创建类似ipad的设置界面。
这里我们使用ListFragment来显示项目栏,内容栏通过Fragment来创建自定义布局。
直接上代码:
ItemActivity.java
package com.test.fragment;
import com.test.fragment.R;
import android.app.ListFragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class ItemActivity extends ListFragment{
private ItemAdapter adapter;
private ImageView mLastIndicate = null;
private Context mContext = null;
private String [] mArr = null;
private static OnItemChangeListener onItemChangeListener;
public interface OnItemChangeListener{
void onItemChange(int position);
}
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mContext = getActivity();
mArr = new String[]{"item1","item2","item3"};
adapter = new ItemAdapter();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
setListAdapter(adapter);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
if(mLastIndicate != null){
mLastIndicate.setVisibility(View.GONE);
}
ImageView imageView = (ImageView)v.findViewById(R.id.item_indicate);
imageView.setVisibility(View.VISIBLE);
mLastIndicate = imageView;
onItemChangeListener.onItemChange(position);
}
public static void setItemChangeListener(OnItemChangeListener l){
onItemChangeListener = l;
}
public class ItemAdapter extends BaseAdapter{
private ViewHolder mHolder = null;
public ItemAdapter(){
}
public int getCount() {
// TODO Auto-generated method stub
return mArr.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView == null){
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_layout, parent, false);
mHolder = new ViewHolder();
mHolder.item_tv = (TextView)convertView.findViewById(R.id.item_tv);
mHolder.item_indicate = (ImageView)convertView.findViewById(R.id.item_indicate);
convertView.setTag(mHolder);
}else{
mHolder = (ViewHolder)convertView.getTag();
}
if(mLastIndicate == null){
if(position == 0){
mHolder.item_indicate.setVisibility(View.VISIBLE);
mLastIndicate = mHolder.item_indicate;
}
}
mHolder.item_tv.setText(mArr[position]);
return convertView;
}
class ViewHolder{
public TextView item_tv;
public ImageView item_indicate;
}
}
}
在ItemActivity中设置onItemChangeListener监听器接口,在Item改变的时候,让MainActivity通过接口来刷新界面。
ContentActivity.java
package com.test.fragment;
import com.test.fragment.R;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class ContentActivity extends Fragment {
private String [] arr = null;
private String [] arr0 = {"item1:","item1:","item1:","item1:","item1:"};
private String [] arr1 = {"item2:","item2:","item2:","item2:","item2:"};
private String [] arr2 = {"item3:","item3:","item3:","item3:","item3:"};
private ContentAdapter adapter = null;
private ListView lv = null;
private Context mContext = null;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Bundle bundle = getActivity().getIntent().getExtras();
int position = 0;
if(bundle == null){
position = 0;
}else{
position = bundle.getInt(MainActivity.KEY_POSITION);
}
switch(position){
case 0:
arr = arr0;
break;
case 1:
arr = arr1;
break;
case 2:
arr = arr2;
break;
}
mContext = getActivity();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.content_layout, container, false);
lv = (ListView)view.findViewById(R.id.contentList);
adapter = new ContentAdapter();
lv.setAdapter(adapter);
return view;
}
public void onUpdateContent(int position){
switch(position){
case 0:
arr = arr0;
break;
case 1:
arr = arr1;
break;
case 2:
arr = arr2;
break;
}
adapter.notifyDataSetChanged();
}
class ContentAdapter extends BaseAdapter{
private ViewHolder mHolder;
public ContentAdapter(){
super();
}
public int getCount() {
// TODO Auto-generated method stub
return arr.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView == null){
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.content_item_layout, parent, false);
mHolder = new ViewHolder();
mHolder.content_tv = (TextView)convertView.findViewById(R.id.content_tv);
convertView.setTag(mHolder);
}else{
mHolder = (ViewHolder)convertView.getTag();
}
mHolder.content_tv.setText(arr[position]);
return convertView;
}
class ViewHolder{
public TextView content_tv;
}
}
}
MainActivity.java
package com.test.fragment;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.test.fragment.ItemActivity.OnItemChangeListener;
import com.test.fragment.R;
public class MainActivity extends Activity implements OnItemChangeListener{
private ContentActivity contentFragment = null;
// private ItemActivity itemFragment = null;
public static final String KEY_POSITION = "position";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
contentFragment = (ContentActivity)getFragmentManager().findFragmentById(R.id.content);
ItemActivity.setItemChangeListener(this);
}
public void onItemChange(int position) {
// TODO Auto-generated method stub
if(contentFragment == null){
Intent intent = new Intent(this,Content.class);
Bundle bundle = new Bundle();
bundle.putInt(KEY_POSITION, position);
intent.putExtras(bundle);
startActivity(intent);
}else{
contentFragment.onUpdateContent(position);
}
}
}
MainActivity的实现了OnItemChangeListener监听器接口,那么首先就要在onCreate的时候将监听器注册到ItemActivity中,在实现的方法中分别针对Tablet和Handset设备做了不同的处理。
欲知更多fragment的使用技巧,请参考官方SDK。
代码下载,请看附件。