使用布局与组件创建用户界面
本章,我们来给RecycLerView列表项添加一些样式,借此学习更多有关布局和组件的知识。同时,我们还会重点学习使用一个叫作ConstraintLayout的新工具。至本章结束时, CrimeListFragment视图会有明显改观(图9-1),整个应用看起来更加大气漂亮。
图9-1 美观大气的Criminallntent应用
首先把图9-1中漂亮的手铐图像复制一份放入项目。浏览随书文件,找到并打开09 LayoutsAndWidgets/ Criminallntent/app/src/main/res目录,把各个版本的ic_solved.png复制到项目对应的drawable目录里。
打开list_item_crime.xml布局文件,然后选择窗口底部的Design标签页。
图形布局工具界面的中间区域是布局的界面预览窗口。右边紧挨的是蓝图(blueprint)视图。
图形布局工具界面的左边是组件面板视图,它包含了所有你可能用到的组件,按类别组织(如图9-2所示)。
组件面板
图9-2 图形布局工具中的视图
引入 ConstraintLayout
首先转换list item_crime.xml布局,改用ConstraintLayout。在组件树窗口,右键单击根LinearLayout,然后选择Convert LinearLayout to ConstraintLayout菜单项。
随后Android Studio会弹出一个窗口,让你确认如何转换。lit item_crime.xml是个简单布局,不需要深度优化。所以,接受默认值,点击OK按钮确认。
最后,你需要确认在项目里添加约束布局依赖项。和RecycLerView类似, ConstraintLayout也包含在某个库里。所以,若要使用它,要么手动添加,要么点击OK按钮确认,让Android Studio帮你添加。
依赖项
查看appbuild.gradle文件,可以看到依赖项已经添加成功,如下代码所示。
内边距属性的实际应用(fragment_crime.xml)
dependencies {
…
compile’com.android.support.constraint:constraint-Layout;1.0.0-beta4’
}
靠近布局预览窗口顶部的工具栏上,你可以看到一些约束编辑选项。转换list item_crime使用ConstraintLayout时,根据原布局的视图布置,Android Studio已经自动添加了约束。
腾出空间
在组件树里,选中crime_titLe,然后查看右边的属性视图窗口水平方向和竖直方向的尺寸是分别由宽度设置和高度设置决定的。能设置的值有以下三种,每种值都对应Layout_width或Layout_height的一个值。
当前,crime_titLe和crime_date都设定了一个最大的固定宽度值,所以占据了整个屏幕。选中crime_title,把宽度值设为wrap_content,如果有必要,把高度值也设为wrap_content,
重复上述步骤,设置crime_date的宽高值。现在这两个组件小一些了,并且还重叠在一起了。
处首先添加一个ImageView视图。在组件面板里找到ImageView组件,把它拖入组件树,并作为ConstraintLayout的子组件,放在crime_date下面。
在随后弹出的对话框里,选择ic_soLved作为ImageView组件的资源
ImageView组件添加完了,但它还没有任何约束。虽然它现在有个位置,但这个位置没有任何意义。
现在为它添加约束。在组件树或者预览界面里选中ImageView组件,可看到它的四边都有圆点。
随后来设置ImageView组件顶部和ConstraintLayout组件顶部之间的约束。就在Criminallntent蓝色工具栏的下面。在预览界面,拖住ImageView组件顶部的约束柄,将其拖向ConstraintLayout组件顶部。ConstraintLayout里摆放的方式——设置和删除约束。
ImageView
按同样的方式,拖住ImageView组件底部的约束柄,拖到根视图的底部。同样,不要拖到 TextView上。最后,向根视图右边拖曳ImageView的右约束柄,设置右边约束。完成后,将鼠标悬停在 ImageView组件上,确认所有的约束都正确设置,
将布局切换到XML文件模式,看看刚刚为ImageView创建的三个约束都向XML文件里添加了什么内容,如代码所示。
ImageView约束的XML形式(layout/list_item_crime.xml)
<android.support.constraint.Constraintlayout
xmLns:android=“http://schemas.android.com/apk/res/android”
xmLns:app=“http://schemas.android.com/apk/res-auto”
xmLns:tools=“http://schemas.android.com/tooLs”
android:layout_width=“match_parent”
android:Layout_height=“wrap_content”>
…
<imageView
android:id="@+id/imageView"
android;Layout_width=“wrap_content”
android;Layout_height=“wrap_content”
app:srcCompat="@drawable/ic_solved"
android:Layout_marginTop="L6dp"
app;layout_constraintTop_toTopOf=“parent”
app;ayout_constraintBottom_toBottomOf=“parent”
android;Layout_marginBottom=“16dp”
android:Layout_marginEnd="L6dp"
app:Layout_constraintRight_toRightOf=“parent”/</android.support.constraint.Constraintlayout>
现在,ImageView组件已经摆放正确了。接下来的任务是布置和调整标题TextView组件。
首先,在组件树里选中crime_date,把它拖曳到别处
。
随后在组件树里选中crime_titLe视图。它的目标位置是布局的左上角,ImageView组件的左边。这需要添加以下三个约束∶
从crime_title视图的左边到其父组件的左边,带16dp的边距;
从crime_title视图的顶部到其父组件的顶部,带16dp的边距;
从crime_title视图的右边到ImageView组件的左边,带8dp的边距。
创建上述约束。
搞定了crime_titLe的约束,现在设置视图尺寸。视图宽度设置为动态适应(0dp),这样标
题文字就可以占满约束间的空间。视图高度设置为wrap_content,以便刚好显示出crime标题。最后,确认设置结果。
接下来处理crime_date视图。在组件树里选中它,为其添加以下三个约束∶
从crime_date视图的左边到其父组件的左边,带16dp的边距;
从crime_date视图的顶部到crime_titLe视图的底部,带8dp的边距;
从crime date视图的右边到ImageView组件的左边,带8dp的边距。
完成约束设置后,开始设置视图尺寸。和crime_titte视图一样,设置视图宽度为动态适应(0dp),高度为wrap_content。最后,确认设置结果现在,查看预览,应该能看到类似图9-1的显示效果。
运行Criminallntent应用,确认三个组件在RecyclerView视图都显示得上下齐整、疏落有致,如图9-3所示。
图9-3 图形布局工具中的视图
动态设置列表项 当前,应用运行时,每行都显示了手铐图片。这和实际不符,需要修改ImageView组件解决。首先,更新ImageView组件的ID(组件添加时已设置了默认名)。在组件树里选中它,然后在视图属性窗口将ID修改为crime_soLved。Android Studio会询问是否更新所有用到该ID的地方,点Yes确认。
更新完ID,代码也要做对应更新。打开CrimeListFragmentjava文件,在CrimeHoLder类中,添加一个ImageView实例变量。然后,根据crime记录的解决状态,控制图片的显示,如下代码所示。
控制图片显示(CrimeListFragment.java)
private cLass CrimeHolder extends RecyclerView.ViewHolder
implements View.OncClicklistener {
private TextView mDateTextView;
private ImageView mSoLvedImageView;
public CrimeHoLder(layoutinflater inflater,ViewGroup parent){
super(inflater.infLate(R.Layout.ist_item_crime,parent,false));
itemView.setOnClicklistener(this);
mTitLeTextView =(TextView)itemView.findViewByid(R.id.crime_titLe); mDateTextView =
(TextView)itemView.findViewByid(R.id.crime_date); mSoLvedImageView =
(ImageView)itemView.findViewById(R.id.crime_soLved);]
public void bind(Crime crime
)
{
mCrime = C rime;
mTitleTextView.setText(mCrime.getTitle());
mDateTextView.setText(
mCrime.getDate().
toString());
mSoLvedImageView.setVisibitity(crime.isSoLved()? View.VISIBLE : View.GONE);
…
}
运行Criminallntent应用。确认手铐图片能按问题解决情况正确显示。