欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android编程示例:创建机场计划模拟器应用程序

程序员文章站 2022-07-06 11:46:58
在本文中,我们将演示如何使用Android Studio和Java编程语言创建一个示例Android应用程序,从“临时”实现高级响应用户界面的功能。本文中讨论的应用程序将实现机场航班时刻表模拟的功能。在开发生命周期中,我们将实现Android应用程序的响应式用户界面,用于呈现“到达”和“离开”航班的 ......

在本文中,我们将演示如何使用android studio和java编程语言创建一个示例android应用程序,从“临时”实现高级响应用户界面的功能。本文中讨论的应用程序将实现机场航班时刻表模拟的功能。在开发生命周期中,我们将实现android应用程序的响应式用户界面,用于呈现“到达”和“离开”航班的列表,并提供动态生成和更新实时模式中的航班信息的功能。

我们将大力强调几个java语言编程方面,并深入研究允许我们提供高级android应用程序的编程技术的数量,包括从一开始就创建响应app's drawer和navigation bar应用程序的方面,提供我们自己的custom views并且layouts,如custom search view bar with action button,覆盖默认功能通用app's action bar,保持tabbed layout,渲染recycler views ,不同于listviews或gridviews允许创建的自定义外观的项目lists由应用程序所呈现的数据,与创建各种布局多重嵌套fragments,使用 bottom navigation view等

除了应用程序的界面特定主题,我们还将了解如何创建一个用java编写的高效代码来实现生成和操作数据内容的功能,以及如何提供操作数据的代码和应用程序的用户界面。

具体来说,我们将实施机场航班时刻表模拟器的功能,该模拟器生成随机航班数据集并通过在实时模式中过滤掉航班来模拟航班到达和延长时间线来操纵这些数据,动态更新航班列表被渲染。为此,我们将使用和讨论诸如使用android应用程序的后台任务,使用计时器等主题。

背景

先决条件(在我们开始之前...)

在我们开始讨论之前,让我们花点时间仔细研究一下到目前为止我们特别需要的开发工具和库来构建和运行我们的第一个android应用程序。

因为,我们即将使用java编程语言来部署我们运行android的第一个应用程序,我们必须安装java se。为此,我们需要从/下载并安装java standard edition - se平台。反过来,java se平台包含在pc上构建和运行用java编写的代码所需的所有库和模块。

在我们成功安装java se平台之后,我们还需要正确安装ide和创建android应用程序项目所需的特定库,并构建运行我们正在部署的应用程序的代码。各种ide,编程语言和库的数量,例如由android开发社区授权的microsoft visual studio / c#.net xamarin或android studio,可以有效地用于创建和部署android应用程序。

在本文中,为了提供android应用程序开发生命周期的效率,平台兼容性以及开发流程,我们将特别使用android studio和java编程语言来实现此目的。

这就是为什么,在我们在之前的配置步骤中安装java se平台之后,需要并强烈建议在开发机器上下载并安装android studio(https://developer.android.com/studio/)。

我们可能已经注意到,安装的android studio包含许多开发工具,包括ide,java sdk和ndk库,android系统模拟器,gradle / maven - java编译器的“make”实用程序,可以更轻松地编译和编译用java编程语言编写的链接代码。

反过来,android studio的ide是一个高效且响应迅速的工具,用于轻松创建和编辑android源码以及实现基本应用程序功能的java代码。

除了高效便捷的ide之外,android studio软件包还包括为各种目标(手机,平板电脑,可穿戴设备,android电视......)开发android应用程序所需的java sdk库。具体来说,android studio ide允许通过sdk管理器下载和安装适用于各种android系统版本的sdk,sdk manager是android studio的一部分,或者可选地定期使用java sdk发行版中的本机sdk管理器。

为了编译和链接正在创建的应用程序,android studio的软件包还包括上面提到的gradle / maven'make'实用程序。在android studio中创建我们的第一个android应用程序项目时,gradle组件已下载并配置为与android studio的ide一起使用。每次,当我们构建和运行android应用程序的项目时,gradle实用程序正在执行编译和链接特定的任务,例如创建包含内置android应用程序的apk包,可以在模拟器上运行或者一个android设备。在开发生命周期中,由于已经创建和配置了项目,因此我们可以使用gradle实用程序的多个版本,就像在本文的项目创建部分中讨论的那样。 

为了能够在调试开发阶段运行应用程序,android studio还包括一个支持各种android系统版本的android设备模拟器,可通过android studio的模拟器管理器从google和android开发社区。在模拟器上运行应用程序与在目标android设备上运行应用程序非常相似。

在本文的下一部分中,我们将演示如何在安装的android studio环境中创建我们的第一个android应用程序项目。

摘要

创建您的第一个android app项目

在我们成功满足上面讨论的所有安装和配置要求之后,我们要做的第一件事就是运行android studio并创建一个项目来实现我们的机场航班时刻表模拟android应用程序功能。为此,我们将使用android studio主对话框切换启动新的android studio项目选项:

Android编程示例:创建机场计划模拟器应用程序

在此之后,android项目创建对话框将出现在屏幕上:

Android编程示例:创建机场计划模拟器应用程序

在这个对话框中,我们必须指定一个应用程序名称(在这种情况下,它是` airportapp`),公司域(例如,` epsilon.com`)来正确配置应用程序包,项目位置,特别是包name,在我们的例子中是` com.epsilon.airportapp`。在我们提供了创建项目所需的所有信息后,单击此对话框底部的下一个按钮。

在此步骤之后,我们必须正确选择并指定我们的应用程序的目标设备,包括正确的外形(“手机”或“平板电脑”),最小的sdk及其版本,以及android系统发布版本:

Android编程示例:创建机场计划模拟器应用程序

在我们成功选择了目标设备和android发布版本之后,我们还必须选择一种应用程序的活动。活动通常是java类实现功能,负责应用程序的主窗口创建,事件处理以及完成其他用户交互特定任务。实际上,扩展泛型activity类或其他派生类的java 类是任何现有android应用程序的主类:

Android编程示例:创建机场计划模拟器应用程序

在这种特殊情况下,我们开始我们的第一个android应用程序开发生命周期,选择一个空活动作为我们的机场计划模拟器应用程序的主要活动。此外,我们将定制和增强默认的空活动,以提供执行机场计划模拟任务所需的功能。

android应用程序创建阶段的最后一步是配置基于活动的java类别名,生成特定的活动布局,以及配置应用程序的向后兼容库。为此,我们必须继续下一个配置对话框:

Android编程示例:创建机场计划模拟器应用程序

在最后一步中,我指定一个应用程序基于活动的java类名称,该名称将对应于正在生成的特定活动布局xml文件名。此外,我们必须指定是否要提供应用程序与旧版android的向后兼容性。

由于我们已经配置了应用程序的活动,因此在最后阶段生成特定项目并打开android studio的ide主窗口:

Android编程示例:创建机场计划模拟器应用程序

在本文的下一部分中,我们将简要介绍使用android studio创建的android应用程序的项目结构。

android app的项目结构

在这一点上,让我们仔细看看应用程序项目创建后打开的android studio ide主窗口左上角的应用程序解决方案树。通常,解决方案树显示正在创建的项目的内容,该内容与保存到特定位置的目录结构完全对应(例如,“ d:\ airportapp ”)。

androidmanifest.xml中

文件夹“清单”是显示在应用解决方案树顶部的第一个文件夹。它基本上只包含一个文件' androidmanifest.xml '。以下文件主要包含运行正在创建的应用程序所需的xml格式的所有配置数据。androidmanifest.xml文件具有以下结构,对于所有android应用程序都完全相同:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

  package="com.epsilon.arthurvratz.airportapp">
  <application

     android:allowbackup="true"

     android:icon="@mipmap/ic_launcher"

     android:label="@string/app_name"

     android:roundicon="@mipmap/ic_launcher_round"

     android:supportsrtl="true"

     android:theme="@style/apptheme.noactionbar">
     <activity android:name=".airportactivity"

        android:theme="@style/apptheme.noactionbar"

        android:windowsoftinputmode="statehidden"

        android:configchanges="orientation|screensize|keyboard|keyboardhidden">
        <intent-filter>
           <action android:name="android.intent.action.main" />
           <category android:name="android.intent.category.launcher" />
        </intent-filter>
     </activity>
  </application>
</manifest>

 

androidmanifest.xml文件的第二行包含manifest标记,其属性提供命名空间和应用程序的包名称信息。它还包含一个嵌套标签application ,该标签具有定义标签,文本方向和创建的应用程序的一对图标的属性数。由应用程序标签的属性指定的图标和标签基本上显示在应用程序的主窗口中。应用程序标记还包含一个定义默认应用程序主题的属性(例如,android:theme="@style/apptheme")。或者,我们可能希望修改现有的或向应用程序标记添加更多属性,以便提供应用程序主窗口的自定义外观和行为。例如,我们可能想要更改值android:theme属性,以便我们的应用程序将覆盖默认的泛型并使用其自己的应用程序操作栏实现。为此,我们需要将以下标记的值更改为android:theme="@style/apptheme.noactionbar".

通常,application标记具有嵌套标记的数量,例如activity标记,用于提供主应用程序活动的一组配置属性。默认情况下,activity标记只有一个属性,用于定义主应用程序活动的名称(例如android:name=".airportactivity")。要修改应用程序的主要活动配置参数,我们可能需要向以下标记添加更多属性:

android:theme="@style/apptheme.noactionbar"
android:windowsoftinputmode="statehidden"
android:configchanges="orientation|screensize|keyboard|keyboardhidden">

 

在这种特殊情况下,我们将以下配置属性添加到activity上面列出的机场计划模拟器应用主标签中。第一个属性是我们之前在application 上面标记中指定的属性的副本。以下属性用于指定将显示正在运行的应用程序中的默认通用应用程序操作栏。第二个属性android:windowsoftinputmode="statehidden"用于指定在启动应用程序时不会自动呈现的软输入方法。最后一个属性 android:configchanges="orientation|screensize|keyboard|keyboardhidden"提供应用程序覆盖的配置更改列表。这意味着应用程序将处理以下更改,而不是android系统。具体来说,应用程序将处理屏幕旋转并根据当前屏幕方向呈现正确的界面布局变化(例如' portrait'或' landscape')。

应用程序标记还包含最内层嵌套标记的数量,例如intent-filter,action和category。在action和category里面的意图标签intent-filter标签指定的主应用程序的入口点。特别是,这些标签指定当前'.airportactivity' 是主应用程序的活动:

<intent-filter>
   <action android:name="android.intent.action.main" />
   <category android:name="android.intent.category.launcher" />
</intent-filter>

 

gradle脚本

现在,让我们来看看位于应用解决方案树底部的' gradle scripts '兄弟。以下文件夹包含配置上一节中提到的gradle'make'实用程序所需的所有脚本文件,包括项目' '或' '模块的两个' build.gradle '文件实例。第一个build.gradle文件包含以下内容:airportappapp

// top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
   
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'
       

        // note: do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: delete) {
    delete rootproject.builddir
}

 

以下文件是包含gradle存储库的基本配置的非xml文件,包括其构建版本(例如 'com.android.tools.build:gradle:3.1.3')。在项目配置期间,以下文件的内容通常保持不变。
 
但是,第二个build.gradle文件特别感兴趣。第二个build.gradle文件基本上包含应用程序的项目模块依赖项的定义。例如:
apply plugin: 'com.android.application'

android {
    compilesdkversion 28
    defaultconfig {
        applicationid "com.epsilon.arthurvratz.airportapp"
        minsdkversion 24
        targetsdkversion 28
        versioncode 1
        versionname "1.0"
        testinstrumentationrunner "android.support.test.runner.androidjunitrunner"
    }
    buildtypes {
        release {
            minifyenabled false
            proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation filetree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
    implementation 'com.android.support:support-v4:28.0.0-alpha3'
    implementation 'com.android.support:support-v13:28.0.0-alpha3'
    implementation 'com.android.support:design:28.0.0-alpha3'
    implementation 'com.android.support:recyclerview-v7:28.0.0-alpha3'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testimplementation 'junit:junit:4.12'
    androidtestimplementation 'com.android.support.test:runner:1.0.2'
    androidtestimplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'org.jetbrains:annotations-java5:15.0'
}

 

为了能够使用android支持库,我们必须v.4,v.7,v.13将以下行添加到此文件的部分:recyclerviewconstraintlayout dependencies
 
<span courier new",courier,mono; font-size: 12px; font-size-adjust: none; font-stretch: 100%; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; line-height: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-shadow: none; text-transform: none; -webkit-text-stroke-width: 0px; white-space: pre; word-spacing: 0px;">    
implementation 'com.android.support:appcompat-v7:28.0.0-alpha3' implementation 'com.android.support:support-v4:28.0.0-alpha3' implementation 'com.android.support:support-v13:28.0.0-alpha3' implementation 'com.android.support:design:28.0.0-alpha3' implementation 'com.android.support:recyclerview-v7:28.0.0-alpha3' implementation 'com.android.support.constraint:constraint-layout:1.1.2'</span>

 

反过来,' gradle-wrapper.properties '和' local.properties '文件都是另一个特别的兴趣:
 
gradle-wrapper.properties:
#thu jul 26 06:49:16 eest 2018
distributionbase=gradle_user_home
distributionpath=wrapper/dists
zipstorebase=gradle_user_home
zipstorepath=wrapper/dists
distributionurl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

 

local.properties:
## this file must *not* be checked into version control systems,
# as it contains information specific to your local configuration.
#
# location of the sdk. this is only used by gradle.
# for customization when using a version control system, please read the
# header note.
#thu jul 26 15:02:12 eest 2018
sdk.dir=c\:\\androidsdk

在此文件中,我们可以指定gradle实用程序版本或android sdk位置的绝对路径。为此,我们必须修改这两个文件的以下行:

distributionurl=https\://services.gradle.org/distributions/gradle-4.9-all.zip
sdk.dir=c\:\\android\androidstudio\sdk
注意:如果您的gradle更改的版本> gradle-4.6-all.zip,,那么你就还需要禁用“ 配置需求 ”中的“选项文件”>“ 设置 ”>“ 建立,实施,部署 “> 编译器 ”。

应用程序的活动和布局文件

在我们完全符合所有应用程序的项目配置步骤之后,让我们看看我们未来应用程序的活动java实现文件和主应用程序的布局xml文件。主应用程序的布局文件位于“ res / layout ”文件夹下,名称为“ activity_airport.xml ”。以下文件最初包含' android.support.constraint.constraintlayout'标记,这是空应用程序的默认布局。
要修改的主要应用程序的布局,并添加我们的android应用程序的界面组件,如其他直列布局或控制(即“若干意见”),我们必须使用android studio的布局设计或手动编辑以下布局文件:

 Android编程示例:创建机场计划模拟器应用程序

为了能够在android studio的设计器中编辑布局,您还必须修改可以位于应用程序项目的“ res / values ”文件夹中的“ styles.xml ” :
 
<resources>

    <!-- base application theme. -->
    <style name="apptheme" parent="base.theme.appcompat.light.darkactionbar">
        <!-- customize your theme here. -->
        <item name="colorprimary">@color/colorprimary</item>
        <item name="colorprimarydark">@color/colorprimarydark</item>
        <item name="coloraccent">@color/coloraccent</item>
    </style>

</resources>

 

 
具体来说,您必须parent将' style'标签的' '属性值更改parent="theme.appcompat.light.darkactionbar"为  parent="base.theme.appcompat.light.darkactionbar"。
 
以下布局是默认的空应用程序布局,将在讨论应用程序的开发生命周期期间进行更改。或者,我们可以通过手动编辑' activity_airport.xml '布局文件来添加对应用程序布局内容的更改:
 
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"

    tools:context=".airportactivity">

    <textview

        android:layout_width="wrap_content"

        android:layout_height="19dp"

        android:text="hello world!"

        app:layout_constraintbottom_tobottomof="parent"

        app:layout_constraintleft_toleftof="parent"

        app:layout_constraintright_torightof="parent"

        app:layout_constrainttop_totopof="parent" />

</android.support.constraint.constraintlayout>

 

此外,我们将在本文的后续部分之一中提供有关如何使用约束布局来构建响应式应用程序界面的详细指南。
 
我们此时要讨论的最后一个方面是应用程序的主要活动实现文件' com.epsilon.airportapp / airportactivity.java':
package com.epsilon.airportapp;

import android.support.v7.app.appcompatactivity;
import android.os.bundle;

public class airportactivity extends appcompatactivity {

    @override
    protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_airport);
    }
}

 

以下文件包含在第一个' com.epsilon.airportapp '文件夹中,并包含' airportactivity'扩展泛型appcompatactivity'类的java类的声明。最初,airportactivity类只包含一个重写方法' oncreate',实现将应用程序布局呈现为正在创建的应用程序的主内容视图的功能。以下方法实现了调用oncreate超类中的' '方法,或者接受主应用程序的布局resource-id' r.layout.activity_airport'的setcontentview方法,并为主应用程序的布局提供了基本的呈现功能。将来,我们会修改' airportactivity''
 

应用程序的主要布局bluep rint

此时,我们的主要目标是创建机场计划模拟应用程序的主要布局设计草图。更具体地说,主应用程序的布局将具有以下外观:

Android编程示例:创建机场计划模拟器应用程序

从上图中可以看出,整个主要机场应用程序的布局包括'searchview'最顶层的高级变体'tablayout',其中将呈现两个到达和离开航班列表。每个选项卡将呈现一个'recyclerview'显示航班列表,' bottomnavigationview'允许导航将在'昨天','现在'和'tommorow'发生的航班列表中。“tablayout”和“recyclerview”由特定片段布局呈现,这些布局在切换应用程序的抽屉项或选择其中一个特定选项卡后显示。
 
主应用程序的布局主要基于' drawerlayout'模式,这意味着应用程序的抽屉将在用户切换应用程序主窗口左上角的操作栏按钮时呈现。应用程序的抽屉定期可能包含基于'navigationview',应用程序主菜单等的抽屉标题。 
 
在此之前,让我们回想一下,这不是项目创建向导生成的标准应用程序布局。此外,我们将讨论如何以编程方式实现机场应用程序的自定义布局。

设计应用程序的主要布局

现在,我们终于维护了机场应用程序的主要布局蓝图,现在是时候创建和编辑一个或多个应用程序的布局文件了。我们要修改的第一个文件是' activity_airport.xml '。由于我们的机场应用程序旨在拥有应用程序的抽屉,我们选择' drawerlayout'作为主应用程序的布局类型:
 
<?xml version="1.0" encoding="utf-8"?>
<!-- use drawerlayout as root container for activity -->
<android.support.v4.widget.drawerlayout xmlns:android="http://schemas.android.com/apk/res/android"

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

    android:id="@+id/airport_drawer_layout"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:fitssystemwindows="true">

    <include layout="@layout/content_frame"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"/>

    <android.support.design.widget.navigationview        

        android:id="@+id/airport_navigation_view"

        android:layout_width="wrap_content"

        android:layout_height="match_parent"

        android:layout_gravity="start"

        android:fitssystemwindows="true"

        app:menu="@menu/main_menu"

        app:headerlayout="@layout/nav_header_frame"/>

</android.support.v4.widget.drawerlayout>

 

在这种情况下,我们android.support.v4.widget.drawerlayout在activity_airport.xml文件中使用' '作为根标记。在此之后,我们还需要创建两个嵌套标签,例如' include'标签,它将包含单独文件' content_frame.xml'中包含的以下布局的另一部分,或' android.support.design.widget.navigationview'标签,声明机场应用程序的标签抽屉布局。遗憾的是,由于使用了抽屉布局,我们无法使用android studio的布局设计器修改上面显示的布局,但我们可以使用android studio的ide文本编辑器手动编辑此布局。
应用程序主要布局的包含片段存储在内容框架文件中,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent">

    <linearlayout

        android:id="@+id/search_bar"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:layout_constraintbottom_totopof="@+id/airport_fragment_container"

        app:layout_constraintend_toendof="parent"

        app:layout_constrainthorizontal_bias="1.0"

        app:layout_constraintstart_tostartof="parent"

        app:layout_constrainttop_totopof="parent"

        app:layout_constraintvertical_bias="0.02"

        android:focusable="true"

        android:focusableintouchmode="true">

        <requestfocus />

        <android.support.v7.widget.searchview

            android:id="@+id/searchable"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"/>

    </linearlayout>

    <framelayout

        android:id="@+id/airport_fragment_container"

        android:layout_width="match_parent"

        android:layout_height="0dp"

        android:layout_marginend="8dp"

        android:layout_marginstart="8dp"

        app:layout_constraintbottom_totopof="@+id/flights_navigation"

        app:layout_constraintend_toendof="parent"

        app:layout_constrainthorizontal_bias="0.0"

        app:layout_constraintstart_tostartof="parent"

        app:layout_constrainttop_tobottomof="@+id/search_bar">

    </framelayout>

    <android.support.design.widget.bottomnavigationview

        android:id="@+id/flights_navigation"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:layout_constraintbottom_tobottomof="parent"

        app:layout_constraintend_toendof="parent"

        app:layout_constrainthorizontal_bias="1.0"

        app:layout_constraintstart_tostartof="parent"

        app:layout_constrainttop_tobottomof="@+id/airport_fragment_container"

        app:menu="@menu/flights_navigation"

        android:theme="@style/apptheme"/>
</android.support.constraint.constraintlayout>

 

在这个文件中,我们通常使用' android.support.constraint.constraintlayout'标签作为此布局的根标签。以下标记具有内联标记的数量,包括' linearlayout',其中' android.support.v7.widget.searchview'标记被声明',framelayout'实际上声明了一个框架,将以编程方式替换为特定的片段渲染' recyclerview',显示一个航班列表,'bottomnavigationview'按时间过滤掉航班的渲染选项。由于我们使用约束布局作为整个内容框架的根,因此必须正确约束所有嵌套视图和布局。与之前的布局不同,可以使用android studio的布局设计器成功编辑内容框架布局。这就是我们选择是否编辑特定内容框架文件或使用布局设计器为以下布局中的所有视图提供特定约束的原因。 
 
在这种情况下,互连内容框架中视图的最佳方法是app:layout_constrainttop_tobottomof向每个视图标记添加特定属性,例如' ',如上面的源代码所示。在这段代码中,我们从最上面的'linearlayout'视图标签开始垂直和水平地向每个视图标签添加布局约束属性,以垂直方向链接所有这些属性。
 
在这一点上,让我们回到定义应用程序抽屉布局的代码片段。在' drawerlayout'标签内部声明的另一个视图是' android.support.design.widget.navigationview'。以下视图主要用于渲染应用程序的抽屉及其菜单,如上图所示。使用导航视图通常需要我们创建另一个应用程序的抽屉布局和特定菜单,为应用程序的抽屉菜单声明项目。
 
要创建这些布局,我们基本上需要在项目的' / res '文件夹中创建一个子文件夹,并创建名为' main_menu.xml ' 的特定菜单布局资源文件:
 
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <group android:checkablebehavior="single">
        <item

            android:id="@+id/flights"

            android:icon="@drawable/ic_flight_black_24dp"

            android:title="@string/flights" />
        <item

            android:id="@+id/about"

            android:icon="@drawable/ic_star_black_24dp"

            android:title="@string/about" />
    </group>
</menu>

 

在这个文件中,我们必须声明' menu'标签,并在其中创建group项目的' '。在这种情况下,以下布局包含每个“航班”或“关于”菜单选项的两个项目组,显示在应用程序的抽屉中,标题下方。
 
另一个布局文件' nav_header_frame.xml '包含用户切换时在应用程序抽屉中呈现的布局:
 
<?xml version="1.0" encoding="utf-8"?>
<linearlayout 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="240dp"

    android:background="@drawable/airport_nav_header"

    android:gravity="bottom"

    android:orientation="vertical"

    android:padding="16dp"

    android:theme="@style/themeoverlay.appcompat.dark">

    <imageview

        android:id="@+id/imageview"

        android:layout_width="103dp"

        android:layout_height="99dp"

        app:srccompat="@mipmap/ic_launcher_round" />

    <space

        android:layout_width="352dp"

        android:layout_height="10dp" />

    <textview

        android:id="@+id/airport_app_title"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:fontfamily="verdana"

        android:text="@string/nav_header"

        android:textcolor="@android:color/background_light"

        android:textisselectable="false"

        android:textsize="30sp" />

    <textview

        android:id="@+id/airport_app_author"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="@string/airport_app_author" />

</linearlayout>

 

要创建应用程序的抽屉布局,我们将使用特定的' linearlayout'标签。与其他布局(例如' costraintlayout')不同,线性布局允许仅在垂直方向上定位所有视图,并且不需要在视图之间设置任何约束。 
 
要定义正确的抽屉布局,我们必须将以下视图标记放置在线性布局内,以及为应用程序的抽屉标题提供背景图像。为此,我们指定以下线性布局属性:' android:background="@drawable/airport_nav_header"'。通常,我们创建的线性布局将包含以下内联视图:
  • ' imageview' - 用于显示机场应用程序的图标;
  • ' space' - 在线性布局中创建特定视图之间的间隙;
  • ' textview' - 打印机场应用程序的标题或作者的详细信息;

最后,由' navigationview'及其蓝图呈现的应用程序的抽屉布局将具有以下外观:

Android编程示例:创建机场计划模拟器应用程序

在本文的下一部分中,我们将了解如何实现主要机场应用程序活动的功能。

使用操作按钮创建自定义searchview

searchview是出现在主应用程序窗口顶部的机场计划模拟器应用程序的第一个控件。此时,让我们回到他标记的'content_frame.xml片段,声明搜索视图位于以下布局文件的所有其他视图之前,由' :包裹起来:'.tandroid.support.v7.widget.searchviewlinearlayout<font color="#007000" face=""segoe ui",arial,sans-serif">'</font>

<linearlayout
    android:id="@+id/search_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintbottom_totopof="@+id/airport_fragment_container"
    app:layout_constraintend_toendof="parent"
    app:layout_constrainthorizontal_bias="1.0"
    app:layout_constraintstart_tostartof="parent"
    app:layout_constrainttop_totopof="parent"
    app:layout_constraintvertical_bias="0.02"
    android:focusable="true"
    android:focusableintouchmode="true">

    <requestfocus />

    <android.support.v7.widget.searchview
        android:id="@+id/searchable"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</linearlayout>

 

我们使用线性布局用于确保应用程序启动后搜索视图不会获得焦点。
由于我们searchview在内容框架中声明了' '标签,因此我们的目标是通过在java中实现特定代码来提供功能和行为(例如,使搜索视图响应),这些代码将即时处理和处理事件。我们的搜索视图。
 
我们可能知道,在这个项目中我们不会使用通用搜索视图和应用程序栏,但会创建我们自己的自定义搜索视图,它结合了通用搜索视图的基本功能和应用程序的操作栏。
 
要使用操作按钮创建自定义搜索视图,我们需要创建一个新的java类,并将其命名为“ searchablewithbuttonview扩展泛型view”类:
 
public class searchablewithbuttonview extends view {
 
         // searchview basic functionality implementation java-code goes here...

}

 

在本课程中,我们需要实现以下方法。setupsearchablewithbutton()是我们需要实现的第一个方法,以便为我们的自定义搜索视图提供特定的外观和行为:
 
public void setupsearchablewithbutton() {

    // set background color of the search view
    ((viewgroup)m_searchview.findviewbyid(android.support.v7.appcompat.r.id.search_mag_icon).
            getparent()).setbackgroundcolor(color.parsecolor("#ffffff"));


    // set default custom search of the search view button icon and look of the custom search view
    this.setdefaultsearchicon(); this.setupiconifiedbydefault();

    // set default search hint displayed in the search view's edit text view
    m_searchview.setqueryhint("type here...");

    // set default query text and remove focus from the search view
    m_searchview.setquery("", false); getrootview().requestfocus();

    // instantinate the search view object and set default action button click event listener
    m_searchview.findviewbyid(android.support.v7.appcompat.r.id.search_mag_icon).
            setonclicklistener(new searchableviewlistener());

    // instantinate the search view object
    viewgroup llsearchview = ((viewgroup)m_searchview.findviewbyid(
            android.support.v7.appcompat.r.id.search_mag_icon).getparent());

    // instantinate object of the text editable inside the search view
    edittext searchedittext = llsearchview.findviewbyid(
            android.support.v7.appcompat.r.id.search_src_text);

    // remove the search view text editable default selection
    searchedittext.setselected(false);

    // set text editable click event listener
    searchedittext.setonclicklistener(new searchableviewlistener());

    // set text editable ontextchange listener
    searchedittext.addtextchangedlistener(new searchableviewlistener());
}

 

在此方法中,我们通过修改背景颜色,搜索视图按钮图标,在应用程序启动时从搜索视图中删除默认选择和焦点来更改通用搜索视图的外观和行为,并且还设置处理程序(即侦听器)各种搜索视图事件,例如单击用作应用程序主操作按钮的搜索视图按钮,文本编辑和文本可编辑视图点击等。
 
这些事件处理程序实现为' searchablewithbuttonview '子类,在其中声明:
 
public class searchableviewlistener
            implements onclicklistener, textwatcher {
        @override
        public void onclick(view view) {

            // check if the custom search view button was clicked
            if (android.support.v7.appcompat.r.
                    id.search_mag_icon == view.getid()) {

                // if so, perform a check if the default action bar icon was set
                if (!isdefaulticon) {

                    // if not, set the default icon by invoking setdefaultsearchicon() method
                    setdefaultsearchicon();

                    // terminate the onclick handler method execution
                    return;
                }


                // invoke onclick(...) method from the main app's activity class
                m_clicklistener.onclick(view);
            }

            // otherwise, set navigation-back search icon
            else setnavbacksearchicon();
        }

        @override
        public void beforetextchanged(charsequence charsequence, int i, int i1, int i2) {

            // invoke the beforetextchange(...) method from app's activity class (e.g. its parent)
            m_textwatcherlistener.beforetextchanged(charsequence, i, i1, i2);
        }

        @override
        public void ontextchanged(charsequence charsequence, int i, int i1, int i2) {
<span segoe ui",arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-shadow: none; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">                     // set navigation-back icon and invoke the ontextchanged(...) method </span>
            <span segoe ui",arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-shadow: none; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">// from app's activity class (e.g. its parent)</span>
            setnavbacksearchicon(); m_textwatcherlistener.ontextchanged(charsequence, i, i1, i2);
        }

        @override
        public void aftertextchanged(editable editable) {

            // perform a check if the editable string is empty
            if (editable.tostring().isempty())

                // if so, set default search view icon
                setdefaultsearchicon();

            // invoke the aftertextchanged(...) method from its parent 
            m_textwatcherlistener.aftertextchanged(editable);
        }
    }

 

另外,  “ searchablewithbuttonview”类有以下方法:

下面列出的方法将自定义搜索视图的外观更改为uniconfied:

private void setupiconifiedbydefault() {
     // disable the iconfied mode to make the search view fill the entire area horizontally
     m_searchview.seticonified(false);
     m_searchview.seticonifiedbydefault(false);
 }

 

以下方法使用应用程序操作栏按钮的自定义图标替换通用搜索视图的默认图标

private void setdefaultsearchicon() {
    // replace the default search view icon with the action button icon
    this.isdefaulticon = true;
    this.replacesearchicon(r.drawable.ic_dehaze_white_24dp);
}

 

以下方法使用导航后退图标替换默认操作栏按钮图标:

private void setnavbacksearchicon() {
    // check if the default icon was set
    if (this.isdefaulticon == true) {
        // if so, replace search view icon with navigation-back icon
        this.isdefaulticon = false;
        this.replacesearchicon(r.drawable.ic_arrow_back_black_24dp);
        // run the search view icon animation
        this.setupanimation();
    }
}

 

以下方法将默认搜索视图按钮图标替换为从应用程序资源中检索到的图标:

private void replacesearchicon(int resdefaulticon) {
    // instantinate search view button icon object and set the custom icon
    // by calling setimagedrawable method that accepts the icon object retrieved
    // from the app's resources by calling the context's getdrawable(...) method
    ((imageview)m_searchview.findviewbyid(android.support.v7.appcompat.r.id.search_mag_icon)).
            setimagedrawable(m_context.getdrawable(resdefaulticon));
    // start animating icon
    this.setupanimation();
}

 

此方法用于设置搜索视图图标的动画

private void setupanimation() {

    // instantinate search view icon object
    final imageview searchiconview = m_searchview.findviewbyid(
            android.support.v7.appcompat.r.id.search_mag_icon);

    // compute the icon's width and height values
    int searchiconwidth = searchiconview.getwidth();
    int searchiconheight = searchiconview.getheight();

    // instantinate rotateanimation class object and specify the rotation params
    rotateanimation searchiconanimation = new rotateanimation(0f, 360f,
            searchiconwidth / 2, searchiconheight / 2);
    // set animation interpolator
    searchiconanimation.setinterpolator(new linearinterpolator());
    // set animation repeat count
    searchiconanimation.setrepeatcount(animation.infinite);
    // set animation duration
    searchiconanimation.setduration(700);

    // start animating the icon
    searchiconview.startanimation(searchiconanimation);

    // perform a delay for 700ms after the icon animation ends
    new handler().postdelayed(new runnable() {
        @override
        public void run() {
            searchiconview.setanimation(null);
        }
    }, 700);

}

 

通过使用以下方法,我们覆盖了与搜索视图对象一起使用的findviewbyid(...)方法的基本功能:

// override the default findviewbyid method to be used to instantinate
// search view object
private searchview findsearchviewbyid(int resid) {
    return ((activity)m_context).findviewbyid(resid);
}

 

通过调用这两个方法,我们设置了主应用程序的activity类中使用的click事件监听器和文本更改事件监听器:

public void setsearchbuttonclicklistener(@nullable onclicklistener clicklistener) {
    // set click listener class object of its parent
    m_clicklistener = clicklistener;
}
public void settextwatchlistener(@nullable textwatcher textwatchlistener) {
    // set text change watcher listener class object of its parent
    m_textwatcherlistener = textwatchlistener;
}

 

现在,由于我们已经使用操作按钮实现了自定义搜索视图,现在是时候将其功能添加到主应用程序的活动中,如下所示:

@override
protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_airport);

    // instantinating the drawer layout object
    m_drawerlayout = findviewbyid(r.id.airport_drawer_layout);
    // instantinating the navigation view object
    m_navigationview = findviewbyid(r.id.airport_navigation_view);

    // instantinating our custom search view object
    m_searchablewithbuttonview =
            new searchablewithbuttonview(airportactivity.this, r.id.searchable);

    // setting up our custom search view
    m_searchablewithbuttonview.setupsearchablewithbutton();
    // adding the text change watcher listener
    m_searchablewithbuttonview.settextwatchlistener(new searchablewithbuttonlistener());
    // adding the search view action button click event listener
    m_searchablewithbuttonview.setsearchbuttonclicklistener(new searchablewithbuttonlistener());

    // setup app's drawer menu click event listener
    m_navigationview.setnavigationitemselectedlistener(m_navigationbarlistener);

    // ...

 

在overriden oncreate方法中,我们通常执行抽屉布局和导航视图对象的即时化,设置我们的自定义搜索视图并添加特定的事件处理程序。要处理各种搜索视图的事件,我们必须声明一个子类' searchablewithbuttonlistener'实现' view.onclicklistener'或' textwatcher'事件处理泛型类:

public class searchablewithbuttonlistener implements view.onclicklistener, textwatcher
    {
        @override
        public void beforetextchanged(charsequence charsequence, int i, int i1, int i2) {
        }

        @override
        public void ontextchanged(charsequence charsequence, int i, int i1, int i2) {
        }

        @override
        public void aftertextchanged(editable editable) {

        }

        @override
        public void onclick(view view) {
            // perform a check if the app's drawer open
            if (!m_drawerlayout.isdraweropen(gravitycompat.start))
                // if not, open the app's drawer
                m_drawerlayout.opendrawer(gravitycompat.start);
        }
    }

 

通过本文下一节中讨论的以下类的方法实现的功能。在这种情况下,我们将仅讨论onclick(...)此类中方法的一种实现。以下方法通过调用方法实现应用程序的抽屉打开功能drawerlayout.opendrawer(...) 。

正如我们在opendrawer(...)处理自定义操作栏单击事件后触发该方法时已经讨论的那样,应用程序的抽屉打开,显示应用程序的主菜单。此时我们还必须通过调用'm_navigationview.setnavigationitemselectedlistener(m_navigationbarlistener)'接受侦听器类对象作为其单个参数的方法来提供菜单项单击事件处理。以下代码实现了重写导航菜单项click事件监听器类:

private class navigationbarlistener implements
        navigationview.onnavigationitemselectedlistener
{
    // this method handles the navigation menu item click events
    public boolean onnavigationitemselected(menuitem menuitem) {
        // set item as selected to persist highlight
        menuitem.setchecked(true);

        //...

        if (m_drawerlayout.isdraweropen(gravitycompat.start))
            m_drawerlayout.closedrawers();

        return true;
    }
}

 

创建选项卡式应用程序的布局

正如我们已经讨论过的,机场应用程序旨在响应用户的输入并显示各种内容,具体取决于应用程序的抽屉导航菜单中的选项或用户切换的选项卡。特别是在应用程序的抽屉导航菜单中切换“飞行”菜单项后,它通常会呈现选项卡式布局。每个选项卡基本上显示由回收者视图呈现的航班列表。为实现这一点,我们将使用片段。' fragment'是应用程序布局的动态创建和渲染部分,包含其他布局或视图,或两者兼而有之。

在这种情况下,到目前为止我们要做的是创建特定的片段布局和我们自己的实现内容呈现功能的java类。正如我们已经讨论过的那样,两个标签“到达”和“离开”将出现在主应用程序的窗口中。在每个选项卡中,我们将呈现' recyclerview'显示已安排的航班列表。为了提供选项卡式布局功能,我们将使用' tabbedlayout'inside inside' linearlayout',这是flightsfragment当用户在应用程序的抽屉导航菜单中切换第一个菜单项'flight'时显示的根布局。航班片段布局在' res / layout / fragment_flights.xml '文件中实现:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

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

    android:id="@+id/flights_fragment"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    tools:context=".flightsfragment">

    <android.support.design.widget.tablayout

        android:id="@+id/flights_destination_tabs"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:tabmaxwidth="0dp"

        app:tabmode="fixed"

        app:tabgravity="fill">

    <android.support.design.widget.tabitem

        android:id="@+id/arrivals_tab"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:icon="@drawable/ic_flight_land_black_24dp"

        android:text="@string/arrivals_tab" />

    <android.support.design.widget.tabitem

        android:id="@+id/departures_tab"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:icon="@drawable/ic_flight_takeoff_black_24dp"

        android:text="@string/departures_tab" />

    </android.support.design.widget.tablayout>

    <android.support.v4.view.viewpager

        android:id="@+id/flights_destination_pager"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

    <requestfocus/>
</linearlayout>

 

在航班片段线性布局中,我们声明了两个标签:' android.support.design.widget.tablayout'和' android.support.v4.view.viewpager'。第一个标签基本上定义了标签式布局,其中包含两个选项卡,用于“到达”或“离开”航班渲染,显示在主应用程序窗口的搜索视图下方。通过声明第二个标签' viewpager'我们提供了在一个整个屏幕之间滑动渲染到另一个屏幕的功能。
 
由于选项卡式布局和视图分页器呈现为片段,我们必须创建一个单独的java类flightsfragment“扩展泛型android.support.v4.app.fragment”类:
 
flightsfragmentimpl.java:
 
package com.epsilon.arthurvratz.airportapp;

import android.net.uri;
import android.support.v7.widget.linearlayoutmanager;
import android.support.v7.widget.recyclerview;

import java.util.arraylist;

public class flightsfragmentimpl extends android.support.v4.app.fragment implements
        arrivalsfragment.onfragmentinteractionlistener,
        departuresfragment.onfragmentinteractionlistener
{
        public recyclerview m_recyclerview;
        public recyclerview.adapter m_recycleradapter;
        public recyclerview.layoutmanager m_layoutmanager;

        public void setupflightsrecyclerview(recyclerview recyclerview, arraylist<airportdatamodel> dataset)
        {

            // setting the recycler view object
            m_recyclerview = recyclerview;

            // setting the recycler view has a fixed size
            m_recyclerview.sethasfixedsize(true);

            // instantinating the linear layout manager object
            m_layoutmanager = new linearlayoutmanager(getcontext());

            // setting up the recycler view's layout manager
            m_recyclerview.setlayoutmanager(m_layoutmanager);

            // instantinating the flights recycler view's adapter object
            // and adding the flights dataset to the flights recycler view's adapter
            m_recycleradapter = new flightsrecycleradapter(dataset, getcontext());

            // setting up the <span segoe ui",arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-shadow: none; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">flights recycler view's adapter object</span>
            m_recyclerview.setadapter(m_recycleradapter);
    }

    @override
    public void onfragmentinteraction(uri uri) {

    }
}

 

 
flightsfragment.java:
 
package com.epsilon.arthurvratz.airportapp;

import android.content.context;
import android.net.uri;
import android.os.bundle;
import android.support.design.widget.tablayout;
import android.support.v4.view.viewpager;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;

public class flightsfragment extends flightsfragmentimpl
{
    private tablayout m_tablayout;
    private viewpager m_viewpager;

    final private tabselectedlistener
            m_tabsellistener = new tabselectedlistener();

    public arrivalsfragment m_arrivalsfragment;
    public departuresfragment m_departuresfragment;

    private class tabselectedlistener implements tablayout.ontabselectedlistener
    {
        @override
        public void ontabselected(tablayout.tab tab) {
            m_viewpager.setcurrentitem(tab.getposition());
        }

        @override
        public void ontabunselected(tablayout.tab tab) {

        }

        @override
        public void ontabreselected(tablayout.tab tab) {

        }
    }

    private onfragmentinteractionlistener mlistener;

    public flightsfragment() {
        // required empty public constructor
    }

    public static flightsfragment newinstance() {
        return new flightsfragment();
    }

    @override
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
    }

    @override
    public view oncreateview(layoutinflater inflater, viewgroup container,
                bundle savedinstancestate) {

        // inflating the flights fragment view's object
        view flightsfragmentview =
                    inflater.inflate(r.layout.fragment_flights, container, false);

        // instantinating the tab layout object
        m_tablayout = flightsfragmentview.findviewbyid(r.id.flights_destination_tabs);

        // instantinating view pager object
        m_viewpager = flightsfragmentview.findviewbyid(r.id.flights_destination_pager);

        // instantinating the tab layout's pager adapter
        flightsdestpageradapter pageradapter = new flightsdestpageradapter(
              getchildfragmentmanager(), m_tablayout.gettabcount());

        // instantinating the arrivals fragment object
        m_arrivalsfragment = arrivalsfragment.newinstance();

        // instantinating the departures fragment object 
        m_departuresfragment = departuresfragment.newinstance();

        // adding the arrivals and departure fragment objects to the view pager adapter
        pageradapter.add(m_arrivalsfragment);
        pageradapter.add(m_departuresfragment);

        // setting up the view pager adapter
        m_viewpager.setadapter(pageradapter);

        // adding the generic page sliding event listener
        m_viewpager.addonpagechangelistener(
                new tablayout.tablayoutonpagechangelistener(m_tablayout));
        m_tablayout.addontabselectedlistener(m_tabsellistener);

        return flightsfragmentview;
    }

    public void onbuttonpressed(uri uri) {
        if (mlistener != null) {
            mlistener.onfragmentinteraction(uri);
        }
    }

    @override
    public void onattach(context context) {
        super.onattach(context);
        if (context instanceof onfragmentinteractionlistener) {
            mlistener = (onfragmentinteractionlistener) context;
        } else {
            throw new runtimeexception(context.tostring()
                    + " must implement onfragmentinteractionlistener");
        }
    }

    @override
    public void ondetach() {
        super.ondetach();
        mlistener = null;
    }

    @override
    public void onfragmentinteraction(uri uri) {

    }

    public interface onfragmentinteractionlistener {
        // todo: update argument type and name
        void onfragmentinteraction(uri uri);
    }
}

 

为了实现航班片段功能,我们实际上定义了两个java类。第一个类' flightsfragmentimpl'扩展了泛型' android.support.v4.app.fragment '并实现了下面讨论的onfragmentinteractionlistener' arrivalsfragment'和' departurefragment'类的' '功能。下面的类只实现了一个方法' setupflightsrecyclerview(...)',它接受了一个回收器视图对象或arraylist本文后面讨论的数据集对象的两个参数。此方法的主要目的是设置回收器视图的适配器,该适配器用于保存在其中一个选定选项卡中显示的回收器视图中呈现的数据。
 
另一个类' flightsfragment'扩展' flightsfragmentimpl '的功能,并oncreateview通过向视图页面适配器添加特定的到达和离开片段对象,提供动态设置选项卡布局和在'覆盖方法中查看寻呼机的基本功能。' flightsdestpageradapter'java-class实现了view pager适配器的基本功能:
 
package com.epsilon.arthurvratz.airportapp;

import android.support.v4.app.fragment;
import android.support.v4.app.fragmentmanager;
import android.support.v4.app.fragmentpageradapter;

import java.util.arraylist;

public class flightsdestpageradapter extends fragmentpageradapter {

    private arraylist<fragment> m_fragments = new arraylist<fragment>();

    public flightsdestpageradapter(fragmentmanager fragmentmgr, int numberoftabs) {
        super(fragmentmgr);
    }

    public void add(fragment fragment)
    {
        m_fragments.add(fragment);
    }

    @override
    public fragment getitem(int position) {
        return m_fragments.get(position);
    }

    @override
    public int getcount() {
        return m_fragments.size();
    }
}

 

以下类的实现主要基于使用' arraylist<fragment>'用于存储通用' fragment'类对象数组的功能。
 
最后,要渲染航班片段,我们必须覆盖onnavigationitemselected(...)' airportactivity.navigationbarlistener'类中的' '方法。以下方法主要用于处理应用程序抽屉导航菜单中的事件,并具有以下实现:
 
private class navigationbarlistener implements
        navigationview.onnavigationitemselectedlistener
{
    public boolean onnavigationitemselected(menuitem menuitem) {
        // set item as selected to persist highlight
        menuitem.setchecked(true);

        // instantinate the fragment manager transaction coordinator object
        m_fragmenttran = m_fragmentmgr.begintransaction();

        // perform a check if the flights menu item was selected
        if (menuitem.getitemid() == r.id.flights)

            // if so, replace the airport_fragment_container frame layout
            // with specific flight fragment by using its object.
            m_fragmenttran.replace(r.id.airport_fragment_container,
                flightsfragment.newinstance());

        else if (menuitem.getitemid() == r.id.about) {}

        m_fragmenttran.addtobackstack(null); m_fragmenttran.commit();

        // check if the app's drawer is still open
        if (m_drawerlayout.isdraweropen(gravitycompat.start))

            // if so, close the app's drawer
            m_drawerlayout.closedrawers();

        return true;
    }

    public void setupinitialfragment()
    {
        if (m_fragmentmgr == null)

            // instantinate the support fragment manager object
            m_fragmentmgr = getsupportfragmentmanager();

            // begin fragments transaction
            m_fragmenttran = m_fragmentmgr.begintransaction();

            // add the default flights fragment object and commit transaction
            m_fragmenttran.add(r.id.airport_fragment_container,
                  flightsfragment.newinstance()).commit();
    }
}

 

以下类还实现了另一个方法' setupinitialfragment(...)',用于在应用程序的主活动代码中调用初始片段时,在重写方法' oncreate(...)'中,当主应用程序的活动被即时化时:
 
protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_airport);

        //m_actiontoolbar = findviewbyid(r.id.airport_actionbar);
        m_drawerlayout = findviewbyid(r.id.airport_drawer_layout);
        m_navigationview = findviewbyid(r.id.airport_navigation_view);
        m_flightsnavigationview = findviewbyid(r.id.flights_navigation);

        //setsupportactionbar(m_actiontoolbar);
        //this.setupactionbar(r.drawable.ic_dehaze_white_24dp);

        m_searchablewithbuttonview =
                new searchablewithbuttonview(airportactivity.this, r.id.searchable);

        m_searchablewithbuttonview.setupsearchablewithbutton();
   

                    
                
(0)
打赏 Android编程示例:创建机场计划模拟器应用程序 微信扫一扫

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

Android编程示例:创建机场计划模拟器应用程序
验证码: Android编程示例:创建机场计划模拟器应用程序