Dream's Blog.

Android 侧边导航栏+ListView实践

字数统计: 1.6k阅读时长: 6 min
2019/01/17 Share

Android基础项目实践

本学期学习了Android的开发课程,期末也做了一款很萌新向的App作为课程的内容输出吧。

这篇博客就拿来记录一下开发过程和相关内容吧


0x00 前言

言归正传,首先说一说做这么一款App的想法。

一个是出于完成课程报告的角度(有一些要求),另一个就是学了很多确实想做点什么。至于为什么做这个,起初也考虑过仿一些常用的App的想法,但是心里总是不太愿意,想做些没有的。(才不是嫌麻烦呢)
正好那段时间玩着一款游戏《Monster Hunter:World》(怪物猎人),于是就萌生了做一个非官方普及向的App的想法。

效果图如下



0x01 需求分析

  • PC版官方新闻信息
  • 查询(包括但不限于怪物、武器、装饰珠)
  • 图鉴(怪物、武器)
  • 配装器相关

0x02 总体设计

  1. 文件树结构及作用
    Start: 启动动画活动
    MainActivity: 应用主活动
    MyDatabaseHelper: 数据库辅助
    News: 新闻的类,规定数据类型和相关方法
    NewsAdapter: 适配器
    NewsInfo: 点击查看新闻详情的活动
    TuJian: 图鉴的类,规定数据类型和相关方法
    TuJianAdapter: 适配器
    TuJian_Activity: 显示图鉴的活动

  2. 数据库相关
    由于游戏内数据多,且除新闻外的其他资料基本不会发生变动,固采用将外置数据库写入到手机中的方式

0x03 详细设计

启动页面

利用渐变处理图片,通过一个定时器来计算时间实现主活动的跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
StartLogo = (LinearLayout) findViewById(R.id.Start_Logo);
TimerTask task = new TimerTask(){ //设置一个任务
public void run(){
Intent intent = new Intent(Start.this, MainActivity.class);
startActivity(intent);
}
};
Timer timer = new Timer();
timer.schedule(task, 2000); //2000ms后执行任务
beginAnimation();
}

private void beginAnimation() {
AlphaAnimation alpha = new AlphaAnimation(0, 1); //渐变
alpha.setDuration(2000);
StartLogo.startAnimation(alpha);
}

主活动

  • 首先,解决启动动画只在第一次打开App时启动且主活动按返回键时直接退出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override //重写返回键功能,设置为冷启动
    public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addCategory(Intent.CATEGORY_HOME);
    startActivity(intent);
    return true;
    }
    return super.onKeyDown(keyCode, event);
    }
  • 完成外置数据库的写入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public void initDB() {      //初始化数据库
    String DATABASE_PATH = "/data/data/com.example.administrator.mhw/databases/"; //这里是软件对应的数据库所在路径
    String DATABASE_NAME = "MHW.db"; //数据库名称

    File fileDB = new File(DATABASE_PATH + DATABASE_NAME); //拼接完整的路径
    if( !fileDB.exists() ) { //检测是否已存在数据库
    File file = new File(DATABASE_PATH);
    if(!file.exists())
    file.mkdirs();

    try { //写入数据
    InputStream is = getBaseContext().getAssets().open(DATABASE_NAME);
    OutputStream os = new FileOutputStream(DATABASE_PATH + DATABASE_NAME);

    byte[] buffer = new byte[1024];
    int len;
    while((len = is.read(buffer)) > 0) {
    os.write(buffer, 0, len);
    }
    os.flush();
    os.close();
    is.close();
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
  • 官方活动信息的ListView
    原本是想通过爬虫来爬取官方活动信息,存储在数据库中再进行读写,但是我真的菜,只会一点Python的,Java不会,就暂且搁置了
    这里直接录入了几条新闻来替代。但是这一块的设计完全能支持上述想法,有很好的内聚性。
    (代码就是很基础的ListView代码,就不放出来了,文末有项目连接,可下载查看)

新闻详情页

这个是从主页活动通过点击某个新闻,跳转到该新闻的详情页面。
在主活动中获取对应的item,将其中的内容通过活动之间的传值来交给这个活动,避免了此活动再次遍历数据库查找所需的数据,优化了性能

图鉴页

目前做的也是很普通,也只是一个简单的ListView,没什么特别的
(后续还会进行优化 我自己也有点看不下去

0x04 侧边栏

  1. 这个效果需要DrawerLayout的支持,要在build.gradle中添加

    implementation ‘com.android.support:design:27.1.1’

  2. 在对应的layout中采用

    android.support.v4.widget.DrawerLayout 的布局格式

  3. 在layout布局中需要声明

    xmlns:app=”http://schemas.android.com/apk/res-auto"

  4. 进行设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <android.support.design.widget.NavigationView
    android:id="@+id/nav"
    android:layout_width="200dp"
    android:layout_height="match_parent"
    android:layout_gravity="start" //这里常用start,也有left和right可选,可自行尝试。但是必须设置此属性
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    //下述两个属性需要申明3中的app才能正常编译
    app:menu="@menu/nav_menu" //侧边栏导航样式
    app:headerLayout="@layout/nav_header"> //侧边栏头图样式
    </android.support.design.widget.NavigationView>
  5. 对应活动的Java代码中设置点击事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav);
    navigationView.setItemIconTintList(null); //设置导航小图标背景为空
    navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(MenuItem menuItem) {
    switch (menuItem.getItemId()) {
    case ...: break;
    ...
    return true;
    }
    });

0x05 动态绑定图片

理想情况是,新闻是由爬虫进行爬取,存储后读取并显示,对应的图片也转存在drawable文件夹下。
此时无法通过固定的方式将图片绑定到对应的ListView项中去,只能通过下述方法完成此操作。
爬取图片时命名与标题相关,就可以通过标题字符串来一对一的查找该新闻的图片

1
2
3
String str = "news"+news.getId();   //拼接字符串
int resid = context.getResources().getIdentifier(str, "drawable", "com.example.administrator.mhw"); //获取所需图片的id号
NewsImage.setImageResource(resid); //给对应的图片控件设置图片

0x06 相关提示

  • Start.java为启动动画,这是一个活动,因此因将Ta设为 Launch Activity

  • 关于隐藏软件标题栏
    在values文件夹下的styles.xml中设置 <item name="windowNoTitle">true</item>

  • 侧边栏的头图布局nav_header.xml放在layout文件夹下
    导航栏布局nav_menu.xml需要在res文件夹下新建menu文件夹进行存放

0x07 项目地址

https://github.com/LemonJuice98/Android
欢迎评论留言~

0x08 后续

这个成品是个半成品,后续会努力做出首页活动的爬虫,完成这个模块应该有的样子
其次,首页活动列表会考虑别的样式。纯ListView太丑了
其他各个方面也会完成更多的优化

CATALOG
  1. 1. Android基础项目实践
    1. 1.1. 0x00 前言
    2. 1.2. 0x01 需求分析
    3. 1.3. 0x02 总体设计
    4. 1.4. 0x03 详细设计
      1. 1.4.1. 启动页面
      2. 1.4.2. 主活动
      3. 1.4.3. 新闻详情页
      4. 1.4.4. 图鉴页
    5. 1.5. 0x04 侧边栏
    6. 1.6. 0x05 动态绑定图片
    7. 1.7. 0x06 相关提示
    8. 1.8. 0x07 项目地址
    9. 1.9. 0x08 后续