<include>:使视图可以被抽象出来并在其他布局中使用
<ViewStub>:使用ViewStub类可以减少<include>标签的性能影响,可以通过一个Xml把主题应用到全部的应用程序
fragment API 可别进一步抽象UI,使之形成逻辑模块
1. 抽象布局
可复用组件是优秀的面向对象设计的标示,android支持抽象视图,从而提供一个雷士层级的模块儿化。通过吧UI分离成独立的组件你可以在整个应用中使用它们。
1.1 <include>标签
通过这个标签一个布局可以包含在另一个布局中。这使得可复用组件变得非常容易。
<LieanrLayout>
<include layout = "@layout/sub_layout"/>
</LieanrLayout>
<include>标签属性是layout属性(注意他并不包括android:前缀)
这个属性制定了要被包括的布局文件。 只有layout_*属性和android:id属性可以被重写。同时注意如果你想重写android:layout_*属性中的一个,那么你必须重写android:layout_width和android:layout_height属性。否则系统无法使用型布局属性。
1.2 <merge>
如果你经常使用<include>标签,布局可能会变得嵌套过多从而导致UI绘图变慢。<merge>标签可以用来解决这个问题. <merge>标签指导系统一处子布局的顶层容器。当你包含一个子布局时,里面包含的视图会被合并到主布局中去。
<LieanrLayout>
<include layout = "@layout/merge_text"/>
<include layout = "@layout/merge_text"/>
</LieanrLayout>
<merge>
<ImageView>
<TextView>
</merge>
系统合并之后的布局为:“
<LieanrLayout>
<ImageView>
<TextView>
<ImageView>
<TextView>
</LieanrLayout>
注意:使用merge标签需要构造子布局来适配父布局。例如你不可能在包含FrameLayout的布局上包含LinearLayout布局
1.3 <ViewStub>
尽管<include>标签使你能够很容易地包UI分离成可复用的组件,你可能会发现被包含的布局很少备用放到。类似进度和错误栏的布局是可用的,但是它们在正常的使用过程中并不出现。当被包含进布局之后,这些UI袁术仍然是被扩张的,它们会占用CPU周期和内存。
ViewStud类是一个不会占据布局空间的不可见的视图。像<include >标签一样,VIewStub引用一个将会被添加到UI上的外部布局。不过,与<include>标签不同,被引用的布局不会扩展,指导你发送特定的请求他才会扩张。有了ViewStud,布局的可选部分只会在你需要的时候可用,否则他们就会不可见,这将会加快UI的绘制速度。
<ViewStub
android:id = ”@+id/view_stub“
android:layout_width="match_parent"
android:layout_height= "wrap_content'
android:inflatedId= "@+id/sub"
android:layout="@layout/sub"
>
View.VISIBLE :视图对于用户可见,并其会占据布局的空间
View.INVISIBLE :视图对于用户不可见,但是还是会占用布局的空间。
View.GONE 视图对于用户不可见也不会占用布局空间
要想扩充ViewStub引用的外部布局,你可以自己扩张它或者改变它的可见性:
((ViewStub)findViewById(R.id.xx)).setVisibility(View.VISIBLE);
View v = ((ViewStub)findVIewById(R.id.xx)).inflate();
Android:id属性并没有被应用到子布局上(在使用<include>标签时应用了)。由于你需要收到扩张ViewStub,你需要能够引用它的ID,不过你荏苒可以通过使用android:inflated属性来设置括张的子布局的ID。类似地,android:layout_*属性可以通过设置ViewStub上的属性被重写。
2 抽象样式和主题
正如网站设计中你可以使用层叠样式分离布局,你也可以使用Android的样式和主题来把视图的设计从内容中分离开来。这允许你能够快速改变应用的外观而不需要更新大量的独立布局文件。
2.1 样式
样式属性允许你在视图中快速应用一套新的属性
<TextView
android:layout_width="match_parent"
android:layout_height= "wrap_content'
android:textColor= "#FF0000"
android:text= "@string/hello"
/>
把高亮的属性移到一个样式中并在res/values文件夹的XML文件中放置这个样式,这个文件可以使用任何名称,你可以有多个单独的样式文件
<resources>
<style name= "RedText">
<item name = "anroid:layout_width">match_parent</item>
<item name = "anroid:layout_height">match_parent</item>
<item name = "anroid:textColor">#FF0000</item>
</style>
<resources>
<TextView
style= "@style/RedText"
android:text= "@string/hello"
/>
注意style属性没有android:前缀。通过使用<style>标签你可以快熟改变应用的外观,而不用更新所有的布局文件。
样式可以通过网<style>标签中添加parent属性继承其他的样式,下面是一个继承自系统默认文本外观的新样式:
<style name= "GreenText" parent="@android:style/TextAppearance">
<item name= "android:textColor">#00FF00</item>
</style>
2.2 主题
应用到视图的样式只会应用到那个视图上,并不会应用到该视图的子视图上。即使妮子啊诸如LieanarLayout的ViewGroup上使用了样式,该样式也只会应用到对应的视图上,你需要为每个视图设置样式属性。
为一个活动的所有视图样式而不用为所有视图一一制定样式是可行的,你可以通过在应用清单上的<activity>或者<application>
元素上应用android:theme属性做到这一点。这杯成为一个主题。
下面是一个例子:
<activity
android:name= ".ExampleActivity"
android:theme= @android:style/Theme.Holo"><activity>
Holo是3.0版本之后的默认主题。
3. 使用Fragment
Fragment提供把UI分解成 不同组成部分的方法,从而是每一个部分都能在其运行的设备上易正确的形式被展示出来。
3.1 布局
<FrameLayout >
<fragment class ="com.example.ExampleFragment"/>
</FrameLayout>
现在<fragement>标签是小写的兵器有一个类属性。这个属性必须引用一个完整合格的继承自Fragment类的java类。不过类属性并不是必须的。当没有类属性的时候,你需要使用FragmentManager在运行是添加fragment. FragmentManager是在java代码中使用Fragment的接口,你可以使用他来查找、添加、移除以及替换Fragment。很快你将会看到更多FragmentManager的例子
3.2 Fragment生命周期
fragment总是在现有的activity之下。一个fragmen的生命周期与一个Activity类似,不过多了几个毁掉函数,用来处理诸如连接到hostActivity之类的事件。
你只需要重写fragment的onCreateView方法就可以展示他的UI
public class SimpleTextFragment extends Fragment{
@override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
TextView tv = new TextView(getActivity());
tv.setText("Hello Fragment");
return tv;
}
}
android包含一些方便的Fragment用来展示诸如列表和Web内容等常见的视图,这些Fragment负责为你创建它们的视图。当使用它们的时候你不需要重写onCreateView
3.3 Fragment事物
由于屏幕上可以一次展示多个fragment,所以在不转换的Activity的情况下添加和一处它们是可能的。例如当用户选着一个不同的视图的时候,应用的不同部分可以被替换成为一个不同的fragment。
要更改UI中现有的fragment,你必须把他们封装到一个事务中去。fragment事务与数据库事务类中,对所有会影响fragment 的操作经行批处理(例如添加或者一处fragment以及更改)并切回同时执行这些。事务使用FragmentMannager来执行
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
EampleFragment fragment = new ExampleFragment();
ft.add(R.id.fragment_container,fragment);//一个新的Fragment被放置在视图中
ft.commit();
FragmentManager同样为检索布局中已经存在的fragment提供接口。Fragment可以通过他们的ID或者通过标签字符串来引用。
fm.findFragmentById(R.id.frag);
fm.findFragmentByTag("tag");
注意:Fragment仅当activity出于ressume状态时才可以从布局中添加或者删除
3.4 Fragment回退栈
Fragment也有回退栈,这样你对哪个Fragment会被添加以及何时被添加就有了直接的控制
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
EampleFragment fragment = new ExampleFragment();
ft.add(R.id.fragment_container,fragment);//一个新的Fragment被放置在视图中
ft.addToBackStack(null);
ft.commit();
之后,当用户按下返回按钮,fragment事务将会被逆转。你同样也可以条用FragmentManager.popBackStack();方法从回退栈中弹出事务,这样做会弹出最近一个事务。