模块4:主视图UI布局 - 天气视图(4)

现在来添加各项信息所对应的视图元素:

模块4:主视图UI布局 - 天气视图(4)_第1张图片

图中红色矩形框标出的信息自上而下分别是:

  • 当前天气状况,由一个天气图标和文字描述构成
  • 本日最高和最低气温,分别由对应的图标和温度值构成
  • 当前即时气温,由大字体文字显示

在上一节中,我们在fragment_weather.xml布局文件中添加了id为weather_info_bg的垂直方向线性布局。现在以此为基础,分别加入以上几项元素。


当前天气状况

这一行应当是一个ImageView和一个TextView水平方向排列。因此还需要为它们先添加一个水平方向的LinearLayout进行约束,如下:

模块4:主视图UI布局 - 天气视图(4)_第2张图片

其中将android:gravity属性的值设置为center_vertical,意思是让本布局内部的元素在垂直方向上居中对齐,而水平方向上则保持默认的左对齐。

然后再向其中分别加入ImageViewTextView,设置参数分别如下图所示:

模块4:主视图UI布局 - 天气视图(4)_第3张图片

其中:

  • 将图片视图的宽度和高度限定为32个单位
  • 在文本视图与图片视图留出10个单位的空白以免布局过于密集
  • 将文本设为白色(如果@color/white颜色值不存在可自行添加)
  • 文字大小设为20sp

以上的各种字号、颜色、间距等取值在实际开发中都会由设计师提供

为了更加直观的展示界面效果,我们引入一个图标文件并设置给图片视图iv_condition。将图标文件ic_w104.png拷贝到res/drawable-xxhdpi文件夹下:

模块4:主视图UI布局 - 天气视图(4)_第4张图片
天气图标

然后将其设置给图标视图:

模块4:主视图UI布局 - 天气视图(4)_第5张图片

此时图标已经可以在左侧边条上预览了。将布局文件切换到设计视图亦可实时查看效果:

模块4:主视图UI布局 - 天气视图(4)_第6张图片

最高/最低气温

此行信息视图的逻辑与前一行类似,先增加水平方向的LinearLayout,位置是在前一行布局的下方:

模块4:主视图UI布局 - 天气视图(4)_第7张图片

此处多出来几个设置:

  • android:layout_marginLeft:左边距,设为5个单位
  • android:layout_marginTop:顶部边距,设置为8个单位,使其与上一行信息保持足够的间距,减轻视觉上的压迫感

接下来分别添加最高和最低气温对应的图标和文本视图:

模块4:主视图UI布局 - 天气视图(4)_第8张图片

注意其中各个元素的边距、文本格式设置。两个图标视图分别引用了目前尚未添加到项目中的图标文件。将这两个文件拷贝到drawable-xxhdpi文件夹下即可。进入设计视图查看效果应当跟下图类似:

模块4:主视图UI布局 - 天气视图(4)_第9张图片

当前气温

对应当前气温信息的是一个单独的文本视图,它具有较大的字号。按下图的设定将其加入到前一条信息的下方:

模块4:主视图UI布局 - 天气视图(4)_第10张图片

其中,android:includeFontPadding属性设置为false,表示去掉字体中额外的空白。切换到设计视图查看效果:

模块4:主视图UI布局 - 天气视图(4)_第11张图片

可见这个气温数字的字体与我们设计效果图中的纤细字体差的很远。这个问题需要通过其它手段来解决。我们先把剩下的布局完成。


更新时间

视图右下角用较小的文字显示了数据更新的时间。它提示用户当前显示的数据是否过期。如果过期太久则没有参考价值了,需要进行更新。这次我们在id为weather_data_containerRelativeLayout布局内部添加一个文本视图来表示它:

模块4:主视图UI布局 - 天气视图(4)_第12张图片

其中蓝色方框标出的内容表示该文本视图与父视图的右下角对齐。

再次从设计视图查看效果:

模块4:主视图UI布局 - 天气视图(4)_第13张图片

使用自定义字体

Android系统自带的字体较少,特别是中文字体更加贫乏。想要实现设计效果常常需要在应用程序中自行导入并使用字体。

在我们的设计中,对当前天气文字使用了苹果苹方极细体:

模块4:主视图UI布局 - 天气视图(4)_第14张图片

现在我们来尝试导入该字体并运用于温度文字的显示。在src/main文件夹下创建名为assets的新文件夹:

模块4:主视图UI布局 - 天气视图(4)_第15张图片
创建assets文件夹

然后将字体文件HelveticaNeue-UltraLight.otf拷贝过来:

模块4:主视图UI布局 - 天气视图(4)_第16张图片

下面的工作需要通过编写代码来完成。打开WeatherFragment.java,为类WeatherFragment添加温度视图对应的成员变量mTempCur

模块4:主视图UI布局 - 天气视图(4)_第17张图片

然后修改声明周期方法onCreateView(),添加如下代码:

模块4:主视图UI布局 - 天气视图(4)_第18张图片

逐行解释一下代码:

  • 第一行从布局文件中获取温度值对应的文本视图对象
  • 第二行中,用TypeFace类来导入我们需要的字体
  • 第三行将导入的字体设置给温度视图

代码中进行的设置只有在程序执行过程中才能生效,因此无法在布局文件的设计视图中查看。运行App看效果:

模块4:主视图UI布局 - 天气视图(4)_第19张图片
运用自定义字体

温度值的字体已经更改为我们设计使用的苹方极细体。然而还是有点其它问题——视图的最底部与系统的虚拟导航栏重叠在一起了,带来了不好的用户体验。需要解决这个问题。解决问题的思路设法得到系统虚拟导航栏的高度,然后使整个天气信息区域向上移动这么多位置,从而使二者不再冲突。

编写名为getVirtualBarHeight()的私有成员函数以获取以像素为单位的虚拟导航栏的高度值。这段代码不作要求,大家直接引用:

    private int getVirtualBarHeight(Context context) {
        // 取得全屏高度值
        WindowManager windowManager =
                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);
        int height = dm.heightPixels;
        // 如果系统版本大于5.0,则获取除虚拟栏之外的高度
        // 系统版本如果在5.0之前,则不存在这个问题
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            display.getRealMetrics(dm);
        }
        int realHeight = dm.heightPixels;
        // 二者相减得到虚拟栏高度
        int virtualbarHeight = realHeight - height;
        if (virtualbarHeight < 0) {
            virtualbarHeight = 0;
        }
        return virtualbarHeight;
    }

接下来回到onCreateView()方法,首先获取整个全景布局对象,然后调用setPadding()方法设置其下方留白为虚拟按键栏高度即可:

模块4:主视图UI布局 - 天气视图(4)_第20张图片

运行程序查看效果:

模块4:主视图UI布局 - 天气视图(4)_第21张图片

这样,天气信息视图的布局基本上就完成了。在下一阶段,我们将通过添加位置来获取真正的天气信息并通过天气视图来进行展示。


本小节变更的文件:

new file:   app/src/main/assets/HelveticaNeue-UltraLight.otf
new file:   app/src/main/res/drawable-xxhdpi/ic_temp_max.png
new file:   app/src/main/res/drawable-xxhdpi/ic_temp_min.png
new file:   app/src/main/res/drawable-xxhdpi/ic_w104.png
modified:   app/src/main/java/com/dmtech/iw/WeatherFragment.java
modified:   app/src/main/res/layout/fragment_weather.xml
modified:   app/src/main/res/values/colors.xml

你可能感兴趣的:(模块4:主视图UI布局 - 天气视图(4))