Android入门之Fragment

    工作主要做Android开发,所以也就开始了Android学习之旅,其实之前也是接触过一点Android的东西,但是都是浅尝辄止,但是现在开始要好好研究啦,好了,下面开始这篇文章的重点,Android之Fragment。这次主要是通过 开发一个记账的app来熟悉android的各个部分,这次是界面准备工作,并通过这个来熟悉fragment。

1. 为什么用Fragment

    Android中UI管理一般都靠activity,虽然activity视图可以在运行时切换,但是控制视图的代码必须在activity中实现,因此每个activity还是得和特定的用户屏幕绑定在一起,即每个屏幕只能显示一个activity,因此当我们想几个不同界面组装显示在屏幕上时,activity就无法满足需求了,这时,我们就需要使用Fragment,采用Fragment来进行应用的UI管理可以避免activity的界面显示上的限制。

2. 什么是Fragment

    Fragment是一种控制器对象,activity可以委派他完成一些任务,而通常这些任务就是管理用户界面,受管的用户界面可以使整个屏幕或者屏幕的一部分,Fragment也有自己产生于布局文件的视图,视图中包含一些用户可以交互的UI元素,所以可以把Fragment想象成activity中一个模块化的部分,它拥有自己的生命周期,接收自己的输入事件,可以在acvitity运行过程中添加或者移除(有点像"子activity",你可以在不同的activities里面重复使用)。activity视图中需要提供可供Fragment视图插入的位置,这样的位置也可以有多个来提供多个Fragment显示。因此可以实现联合使用Fragment和activity来组装或重新组装用户界面,而此时activity的视图是保持不变的。

3. 版本兼容

    由于Fragment是后来版本中添加(API版本11),因此当应用在Android1.6这样的低版本上时应该使用Support libary中的Fragment来达到兼容的目的。 但是如果的你的APP的最低API版本是11或以上,你不必使用Support Library,可以直接使用API中的Fragment。此外因为Fragment是由activity来管理的,所以也需要activity的支持,但是在Honeycomb之前的版本的activity不支持Fragment管理,因此可以让activity继承自Support Library中的FragmentActivity

4. Fragment开发

    创建一个Fragment和创建一个activity差不多,首先我们得继承自Fragment类,然后在关键的生命周期方法中插入我们的APP逻辑,但是有一点不同的是我们还需要重写OnCreateView()回调方法来定义布局,实际上这也是让Fragment运行起来唯一必须的方法。下面用一个例子来详细描述下Fragment开发过程。

5. App说明

    首先我们开发的项目是一个记录债务的app,每次出去吃饭一般都是某一个人来付账,然后其他人事后再还,一个记录债务的app可以及时记录下欠谁多少钱,已方便事后忘了还钱。当然整体这个项目需要的知识不仅仅只有Fragment,后面将会慢慢开发,这篇文章只先开发简单界面。

6. 开发步骤

    首先我们需要建立model类,一个债务包括债主姓名,欠款数量,日期,是否归还,债务内容等等。下面是个简单的model类:

public class Debt {
	private UUID _id;
	private String _name;
	private int _num;
	private String _detail;
	private Date _date;
	private boolean _payed;
	
	public Debt(){
		_id = UUID.randomUUID();
		setDate(new Date());
		setIsPayed(false);
	}

	public UUID getId() {
		return _id;
	}

	public String getName() {
		return _name;
	}

	public void setName(String _name) {
		this._name = _name;
	}

	public int getNum() {
		return _num;
	}

	public void setNum(int _num) {
		this._num = _num;
	}

	public String getDetail() {
		return _detail;
	}

	public void setDetail(String _detail) {
		this._detail = _detail;
	}

	public Date getDate() {
		return _date;
	}

	public void setDate(Date _date) {
		this._date = _date;
	}

	public boolean isPayed() {
		return _payed;
	}

	public void setIsPayed(boolean _payed) {
		this._payed = _payed;
	}

}

    然后,我们需要创建一个Activity类,创建activity类之前,我们首先需要给它写界面配置文件,因为现在我们用fragment来做UI控件的容器,所以activity界面只是充当一个fragment容器的作用,所以我们创建如下的activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools" android:id="@+id/fragmentContainer"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              tools:context="com.baidu.android.activity.DebtActivity">
</FrameLayout>
    使用Framelayout可以将整个界面作为备用区域,各个fragment相互覆盖的显示。

    然后我们需要创建activity类:DebtActivity。一般activity类名都以activity作为后缀来加以区分,新建activity类,当前我们只需要override onCreate方法即可,如下:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    这样我们就创建了一个空的activity,它使用activity_main.xml作为布局文件。

    然后,我们需要来创建我们的主要界面显示容器fragment,创建fragment我们可以采用和activity类似的方法,首先继承自Fragment基类,然后override相关的生命周期方法即可,正如前面提到的,我们主要需要override的方法是onCreateView()方法,通过这个方法fragment来定义自己的布局,下面同样的,我们需要为fragment写相应的布局xml文件:fragment_debt.xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_marginLeft="18dp"
              android:layout_marginRight="18dp" tools:context="com.baidu.android.activity.DebtActivity">
    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:orientation="horizontal"
                  android:layout_marginBottom="10dp"
                  android:layout_marginTop="10dp">
        <TextView android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:textSize="16sp"
                  android:text="@string/debt_name_label"/>
        <EditText android:id="@+id/debt_name"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="@string/debt_name_hint"/>
    </LinearLayout>

    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:orientation="horizontal"
                  android:layout_marginBottom="10dp">
        <TextView android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:textSize="16sp"
                  android:text="@string/debt_num_label"/>
        <EditText android:id="@+id/debt_num"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="@string/debt_num_hint"/>
    </LinearLayout>

    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginBottom="10dp">
        <TextView android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:textSize="16sp"
                  android:text="@string/debt_date_label"/>
        <Button  android:id="@+id/debt_date"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
    </LinearLayout>

    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginBottom="10dp">
        <CheckBox android:id="@+id/debt_payed"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="@string/debt_payed_label"/>
    </LinearLayout>

</LinearLayout>

    由于控件较多,这个xml文件较长,可以看到大部分的布局定义都差不多,需要注意的是@+id处,加号表示新建资源id,如果已经有了相应的id则不用加号,直接引用即可。

    然后我们创建我们的fragment类:

public class DebtFragment extends Fragment {
    private Debt _debt;
    private EditText _nameField;
    private EditText _numField;
    private Button _dateField;
    private EditText _detailField;
    private CheckBox _payedField;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        _debt = new Debt();
    }

    ...
}
    其中先声明了相关的控件,然后在onCreate方法中创建debt实例,因为现在还没有数据存储相关的,所以直接在fragment类中新建实例。

    然后我们需要override onCreateView方法,如下:

public View onCreateView(LayoutInflater inflater, ViewGroup parent,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_debt,parent,false);
        _nameField = (EditText)v.findViewById(R.id.debt_name);
        _nameField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                _debt.setName(_nameField.getText().toString());
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

        _numField = (EditText)v.findViewById(R.id.debt_num);
        _numField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(TextUtils.isDigitsOnly(s)){
                    _debt.setNum(Integer.parseInt(_numField.getText().toString()));
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        _dateField = (Button)v.findViewById(R.id.debt_date);

        _dateField.setText(new SimpleDateFormat("yyyy-MM-dd hh-mm-ss").format(_debt.getDate()));
        _dateField.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Date _date = new Date();
                _debt.setDate(_date);
                _dateField.setText(new SimpleDateFormat("yyyy-MM-dd hh-mm-ss").format(_debt.getDate()));
            }
        });

        _payedField = (CheckBox)v.findViewById(R.id.debt_payed);
        _payedField.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                _debt.setPayed(isChecked);
            }
        });
        return v;
    }



    可以看到,我们首先实例化每个控件,然后给某些的控件添加相应的listener,如金额的EditText控件,通过addTextChangedListener方法设置当数据发生变化时将实例的金额值变更。

    现在我们已经有自己的fragment类了,下面要做的就是在activity中使用fragment类,下面我们要修改我们的DebtActivity类的onCreate方法,修改后如下:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        FragmentManager fm = getSupportFragmentManager();
        Fragment _fragment = fm.findFragmentById(R.id.fragmentContainer);
        if(_fragment==null){
            _fragment = new DebtFragment();
            fm.beginTransaction()
                    .add(R.id.fragmentContainer,_fragment)
                    .commit();
        }

    }
    可以看到我们声明了一个FragmentManager类。FragmentManager类主要负责对Fragment的管理,并将它们的视图添加到activity的视图层级结构中去。FragmentManager类主要管理fragment队列已经fragment事务的回退栈,而现在我们只需要关系对fragment队列的管理,如上,我们新建了一个fragmentmanager实例后,去获取fragments实例,如果container中没有相应的fragment实例则创建一个实例。

    然后我们调用beginTransaction()方法返回一个FragmentTransaction实例,FragmentTransaction使用fluent interface接口方法,所以以上的操作可以看做是创建一个fragment事务,然后添加一个fragment,然后提交它。

    此时我们已经创建完毕,运行程序即可得到如下:

  

    至此,开发的准备工作已经做好,软件还有bug,比如没有override onSaveInstanceState方法,所以每次横屏后都会出问题,后续再做改进,下次开发将主要实现列表显示债务并点击查看功能并以此来熟悉adapter和listview。























  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值