原型图
首先复盘一下原型图,常规的上中下结构,即标题、内容、导航栏,不同的页面切换不同的标题栏,所以这个标题栏可能会跟内容并在一起,也可能单独放在最外层,这个不重要。分页的逻辑是将四个页面作为四个子view,放置在当前activity下,简单的点击哪个显示哪个,再隐藏其他的,因为主页可能会做一些手势滑动切换之类的动作,所以页面切换就不用ViewPager做左右滑动切换页面了。
布局框架
框架就是简单的把中间内容和底部导航的位置固定一下,这里采用的是线性布局,然后内容显示的容器设置layout_weight自适应撑开,底部导航就是直接写死46dp的高度。因为是沉浸式状态栏,所以需要这两条:android:clipToPadding="true" android:fitsSystemWindows="true"
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="true"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/app_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="46dp"
android:background="@color/white"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
底部导航栏
首先需要准备4个图标,每个图标是两种颜色,如果有条件的话设计师会帮你切好图,没条件的就跟我一起去白嫖吧,白嫖网址:https://www.iconfont.cn/search/index
可以预估一下图标大概多大,这里的话可以用20dp,我习惯性是采用4x的图标,也就是20dp的图标需要的像素大小大概是80X80像素,放在drawable-xxxhdpi中。
drawable文件夹的话一般不放图片,放一些颜色、状态之类的xml文件。字体颜色的话就是txt_开头,纯色(通常是描边、圆角、填充色)只有1中状态的就是bg_开头,如果是多种状态,如按钮这种,就是btn_开头。
将图标导入进来,再写好颜色、状态xml之后,资源如下图所示:
效果为:
布局的话尽量不要写得太生硬,尽量灵活一些,多用些自适应的布局逻辑,因为Android的屏幕的比例千奇百怪,如果写得太生硬的话,16:9可能正常,20:9的时候就严重变形,那就不太美丽了。
其他需要注意的地方我都写代码里面注释了。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="true"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rly_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/app_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="46dp"
android:background="@color/white"
android:orientation="horizontal">
<!-- 如果觉得写在同一个xml里面会显得太过臃肿的话,也可以新建一个xml,然后通过include标签引用进来(一些复用性比较多的布局都可以这么处理)-->
<!-- Space用于占位,以保证每个图标之间的间隔是一样的-->
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<RelativeLayout
android:id="@+id/rly_task"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<!-- 用RelativeLayout再嵌套一个LinearLayout的意思是让LinearLayout上下居中,从而可以上下的位置一致,会随着图片和文字的高度而动态调整-->
<LinearLayout
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical">
<!-- 把LinearLayout宽度固定60,高度自适应,这样可以固定宽度不会变形,高度也可以根据imageView和TextView的高度自适应-->
<!-- ImageView的宽度写最大,高度自适应,然后高度会根据图标的真是高度进行显示,并且是居中的-->
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/btn_home_bar_task" />
<!-- 文字正常是用sp单位,但是sp会随着系统设置的字体大小发生改变,会导致部分页面变形,所以我不太想他自己定义,就用dp写死-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="任务"
android:textColor="@drawable/txt_home_bar"
android:textSize="12dp" />
</LinearLayout>
</RelativeLayout>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<RelativeLayout
android:id="@+id/rly_tool"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/btn_home_bar_tool" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="工具"
android:textColor="@drawable/txt_home_bar"
android:textSize="12dp" />
</LinearLayout>
</RelativeLayout>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<RelativeLayout
android:id="@+id/rly_table"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/btn_home_bar_tablel" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="统计数据"
android:textColor="@drawable/txt_home_bar"
android:textSize="12dp" />
</LinearLayout>
</RelativeLayout>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<RelativeLayout
android:id="@+id/rly_personal"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/btn_home_bar_personal" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="我的"
android:textColor="@drawable/txt_home_bar"
android:textSize="12dp" />
</LinearLayout>
</RelativeLayout>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
编写切换页面的代码
新建HomeActivity继承BaseAppActivity,新建4个子页面的View,继承BaseAppView,并在MainActivity中编写跳转逻辑,跳转到HomeActivity。
HomeActivity代码:
package com.imxiaoyu.tomorrowplan.module.home;
import android.view.View;
import android.widget.RelativeLayout;
import com.imxiaoyu.tomorrowplan.R;
import com.imxiaoyu.tomorrowplan.common.base.BaseAppActivity;
import com.imxiaoyu.tomorrowplan.module.home.view.PersonalView;
import com.imxiaoyu.tomorrowplan.module.home.view.TableView;
import com.imxiaoyu.tomorrowplan.module.home.view.TaskView;
import com.imxiaoyu.tomorrowplan.module.home.view.ToolView;
public class HomeActivity extends BaseAppActivity implements View.OnClickListener {
/**
* 常量
*/
public final static int PAGE_TASK = 0;
public final static int PAGE_TOOL = 1;
public final static int PAGE_TABLE = 2;
public final static int PAGE_PERSONAL = 3;
/**
* view
*/
private TaskView taskView;
private ToolView toolView;
private TableView tableView;
private PersonalView personalView;
/**
* ui
*/
private RelativeLayout rlyContent;
private RelativeLayout rlyTask;
private RelativeLayout rlyTool;
private RelativeLayout rlyTable;
private RelativeLayout rlyPersonal;
@Override
protected int getLayoutId() {
return R.layout.activity_home;
}
@Override
protected void initData() {
}
@Override
protected void initView() {
//找控件的话,我更喜欢这种近乎原始的方式,不太喜欢用注解的方式,1是并不会比现在更省事,也会增加内容支出。
rlyContent = findView(R.id.rly_content);
rlyTask = findView(R.id.rly_task, this);
rlyTool = findView(R.id.rly_tool, this);
rlyTable = findView(R.id.rly_table, this);
rlyPersonal = findView(R.id.rly_personal, this);
taskView = new TaskView(getActivity());
toolView = new ToolView(getActivity());
tableView = new TableView(getActivity());
personalView = new PersonalView(getActivity());
rlyContent.addView(taskView.getView());
rlyContent.addView(toolView.getView());
rlyContent.addView(tableView.getView());
rlyContent.addView(personalView.getView());
switchPage(PAGE_TASK);//初始化页面
}
@Override
protected void onCreateActivity() {
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.rly_task:
switchPage(PAGE_TASK);
break;
case R.id.rly_tool:
switchPage(PAGE_TOOL);
break;
case R.id.rly_table:
switchPage(PAGE_TABLE);
break;
case R.id.rly_personal:
switchPage(PAGE_PERSONAL);
break;
}
}
/**
* 切换页面
*
* @param page
*/
private void switchPage(int page) {
rlyTask.setSelected(false);
rlyTool.setSelected(false);
rlyTable.setSelected(false);
rlyPersonal.setSelected(false);
taskView.dismiss();
toolView.dismiss();
tableView.dismiss();
personalView.dismiss();
switch (page) {
case PAGE_TASK:
rlyTask.setSelected(true);
taskView.show();
break;
case PAGE_TOOL:
rlyTool.setSelected(true);
toolView.show();
break;
case PAGE_TABLE:
rlyTable.setSelected(true);
tableView.show();
break;
case PAGE_PERSONAL:
rlyPersonal.setSelected(true);
personalView.show();
break;
}
}
}
其他
码云地址:https://gitee.com/imxiaoyu_admin/tomorrow
本次提交时间:2020年7月17日
本次完成的预览包apk:http://file.doutugongchang.com/app/upload/tomorrow-plan-debug-2020-7-17.apk