admin管理员组

文章数量:1033055

Android入门之旅

注:这是一个学习笔记。很可惜 Google Study Jams 活动取消了,于是就只能自己来了,幸好 Google 官方有很多面向新手的教程,那么,开干!本文基于/ 给出的教程(而且是中文教程,感觉很良心)

2018©Fu_Qingchen,Typora

本文的运行环境是:

代码语言:javascript代码运行次数:0运行复制
Android Studio 3.1
Build #AI-173.4670197, built on March 22, 2018
JRE: 1.8.0_152-release-1024-b02 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0

总体规划

参照 Google Study Jams 的活动进行

第一阶段

  • L1 (3:38:59):1A (1:04:07) 、1B (1:13:59)、1C (1:20:53)
  • L2 (5:07:02):2A (2:00:40)、2B (1:03:40)、2C (2:02:42)
  • L3 (4:25:20):3A (2:15:36)、3B (2:09:44)
  • 拓展 (2:06:44):Firebase 介绍(0:34:25) + Firebase 周末(1:32:19)

第二阶段

  • 实践教程:制作结业 App、上载结业 App 到 Google Play

总时长 15:18:05,建议 40 - 45 小时的空闲时间学习 ,比如工作日每天一个小时,周末每天两个小时。

用户界面

1C为AndroidStudio的运用,暂不介绍

View

简单来说一个展示内容的长方形,有很多,像什么TestView,ImageView,Button等等

XML

描述Android外观的语言

注:下面的代码块中,注释的写法是错误的,但是为了方便,还是这么写了

例如

代码语言:javascript代码运行次数:0运行复制
<TextView //类型
          android:text="Happy Birthday!"
          //属性名="值" 的形式
          android:background="@android:color/darker_gray"//属性值放在引号内部
          android:layout_width="150dp"
          android:layout_height="75dp"</TextView>
//当然也可以如果需要嵌套,必须使用
//</TextView>来结束
TextView
代码语言:javascript代码运行次数:0运行复制
<TextView
      android:text="Happy Birthday!"
      android:background="@android:color/darker_gray"
      android:background="#2196F3"//替换自己的颜色
      android:layout_width="150dp"
          dp代表密度无关像素,其中可以接触的东东需要至少48dp
          //用dp的原因是不同的设备点像素点的大小是不同的,dp可以使不同的设备显示相同的尺寸
      //android:layout_height="75dp"
      android:layout_height="warp_content"
          //让TextView的高度正好等于文字的高度
      //android:textSize="45sp"//大小可以按照MD的说明来弄,其中sp是比例无关像素
      android:textAppearance="?android:textAppearanceLarge"
          //用系统的文字大小进行匹配/>

相关链接:TextView官方文档

ImageView
代码语言:javascript代码运行次数:0运行复制
<ImageView
      android:src="@drawable/cake"
           //使用@符号表示在Android APP里面引用一个资源
           //drawable是一种资源类型,能将图形显示在屏幕上
           //cake是图片名,不需要添加文件的扩展名
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:scaleType="center"
           //不改变图片大小,然后居中显示
           //android:scaleType="centerCrop"//放大缩小以满足 View 的宽高要求/>

相关链接:ImageView官方文档

ViewGroup

ViewGroup是一个组,相当于是一个容器,他能管理底下的TextView,ImageView,Button等等

LinearLayout

线性布局,分为水平和竖直两种。一般竖直的比较常用

在下面的例子中会介绍线性布局的一些基础内容,还有布局权重

代码语言:javascript代码运行次数:0运行复制
<LinearLayout
    xmlns:android=";
    android:orientation="vertical"
              //线性布局的方向为"竖直"
    android:layout_width="match_parent"
              //这是一种新的标尺寸的东东,与之前的"wrap_content"类似。
              //"match_parent"的含义是:这个尺寸与父级的尺寸相同
              //此处LinearLayout宽就与设备宽度相同,下同
    android:layout_height="match_parent">
            <注意这里有一个">"/>
​
    <ImageView
        android:src="@drawable/ocean"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="5"
        android:scaleType="centerCrop" />
<
    这里出现了layout_weight="1"此处的weight就是权重。
    在这个例子中,ImageView占比5/6,TextView占比1/6
    当有权重weight出现时通常把对应的值设置为0(竖直:height)
    />
    <TextView
        android:text="You're invited!"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="54sp"
        android:layout_weight="1"
        android:background="#009688" />
​
</LinearLayout>

RelativeLayout

相对布局

顾名思义嘛,同样的,在例子中解释

代码语言:javascript代码运行次数:0运行复制
<RelativeLayout
    xmlns:android=";
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
<
   相对布局就不需要android:orientation这个方向属性了
    />
   
    <ImageView
        android:id="@+id/ocean_image_view"
               //相对的嘛,就需要参照物了,参照物需要一个名字,就是id
               //由于这里是添加属性,因此是"@+id"
               //一般习惯性的给每个View都给一个id
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ocean" />
​
    <TextView
        android:id="@+id/Pebble_Beach_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Pebble Beach"
        android:layout_toRightOf="@id/ocean_image_view"
        android:textAppearance="?android:textAppearanceMedium" />
<
    其中layout_toRightOf属性就是表示相对位置的,含义是在参照物的右边
    同理,还有layout_below,layout_above,toLeftOf,见下方
    />
​
    <TextView
        android:id="@+id/California_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="California"
        android:layout_toRightOf="@id/ocean_image_view"
        android:layout_below="@id/Pebble_Beach_text_view"
        android:textAppearance="?android:textAppearanceSmall" />
​
<
    除了把其他View当作参照物,还可以直接把父视图当作参照物,用以下的语句表示:
    android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_centerHorizontal="true"//水平居中
    android:layout_centerVertical="true"//竖直居中
    />
</RelativeLayout>

注意:为了避免过于复杂,能够使用线性视图就使用线性视图

内边距与外边距

内边距(padding)呢就是View本身往外边扩展一层,如果View有背景颜色的话,背景颜色也会扩充

外边距(margin)就是把View隔开一下,隔开的地方是没有颜色的。外边距讲究一种隔开的情况,因此需要建立在ViewGroup里面

下面的图形就是内边距和外边距的例子(PS:Google的教程截图)

其中蓝色部分代表TextView,红色部分代表ViewGroup,左边是内边距,右边是外边距

其实感觉外边距的运用广泛一些,可能跟最近卡片风格流行有关吧

控制内边距(padding)的语句有

代码语言:javascript代码运行次数:0运行复制
android:padding="8dp"   //对于全局
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"

控制外边距的语句有

代码语言:javascript代码运行次数:0运行复制
android:layout_margin="8dp" //对于全局
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"

当然,这个是可以对各个View分别设置的,也可以对ViewGroup设置

ConstraintLayout

约束布局,能够非常快速地制作自适应 UI的一种布局。

※ 构建布局的步骤

  1. 选择视图类型3 Button, 4 TextView
  2. 确定视图的位置标题下面是一行按钮和一个TextView,然后是另一个标题和TextView,最后面是一个Button
  3. 设置视图的样式内边距外边距什么的

用户交互

什么是Activity?

Activity是应用中用户可以操作的东西,有时候Activity就是应用中的一个屏幕。

比如在Google日历中,你点开时看到的就是一个Activity,让你查看日程的,而且这个Activity有一个侧边栏。Google日历的设置是另外一个Activity,让你设置一些东西的。

XML与Java在Android中有什么作用?

XML其实就是一个控制布局的,你可以在里边编辑你的UI

Java呢,就是控制程序的,实现各种各样的功能

XML如何调用Java?

在XML中,我们可以看到这样的语句:

代码语言:javascript代码运行次数:0运行复制
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="submitOrders"
    android:text="order" />

其中android:onClick="submitOrders" 就是用来调用Java中的submitOrders 方法的

如果submitOrders 方法是这样的,那么当用户点击ORDER 按钮时,就会执行相对应的display方法和displayPrice方法

代码语言:javascript代码运行次数:0运行复制
public void submitOrders(View view) {
    //将submitOrders变为submitOrder会在应用运行时报错
    int numberOfCoffee = 2;
    int price = 3;
    display(numberOfCoffee);
    displayPrice(numberOfCoffee * price);
}

Debug

debug是消除bug的调试过程

系统日志

System Log: Android开发中常用logcat这个工具来分层次、分类型地显示不同等级的日志,方便程序员查找感兴趣的信息(错误信息或者更琐碎、更底层的信息)。

断点功能

为了快速找到错误指令,我们可以在希望设备暂停的指令位置插入一个断点,类似停车标志或路障。然后我们可以让调试器从第一条指令开始全速运行应用,运行至断点时,设备一定会暂停供我们进行检查。

使用方法

进行Debugging必须首先进入debug模式,Android的debug是用一只小瓢虫代替。

进入Debug模式之后,程序会和运行时一样重新编译这个App,此时手机会弹出提示,过一会等弄好了,提示也就自己消失了。

当在手机上操作时,在Android Studio的程序框里面就会显示信息,程序运行到断点就会停止,你可以看到一些数据的值

这里非常详细的介绍了Debug模式的使用方法

Nested ViewGroups

嵌套视图组,简单的说就是可以在一个布局里面嵌套多个布局。比如说在竖直的线性布局里面嵌套水平布局。

比如说下面这个图例:

  • 图例首先是包含两个子视图一个竖直的线性布局(vertical LinearLayout)
  • 第一个子视图是一个包含3个子视图的水平线性布局(horizontal LinearLayout)
  • 第二个子视图是一个包含4个子视图的相对布局(RelativeLayout)
    • 其中一个子视图还包含着一个子视图

Java字符串

代码语言:javascript代码运行次数:0运行复制
String message = "Item count" + quantity + 3;   
//字符串还可以这么写,其中quantity是字符变量

其他的都是Java基础了,这里就不写了

控制对齐的属性

主要有两个:layout_gravity 以及 gravity

关于两者的区别:

  • layout_gravity是对整个view的布局。view整体发生变化,但是view里面的内容改咋样还是咋样
  • gravity是对view内的布局。view本身不变,变的是里面的东西

Java常量

在编程语言中,常量是指在整个程序中永远不会改变的值。在 Java 中,你可以使用关键字 final 来强制规定某个值不得被更改。例如:

代码语言:javascript代码运行次数:0运行复制
final int POINTS_FOR_FREE_THROW = 1;

Then if you wrote the following, you'd get an error:

代码语言:javascript代码运行次数:0运行复制
POINTS_FOR_FREE_THROW = 100;

注意,按照惯例,常量的名称全为大写形式。此外,单词之间用下划线连接,而不用空格或用骆驼拼写法。你可以将变量声明为常量,防止自己意外地更改了变量的值。

Android的构成

一个Android应用主要由资源文件和java代码构成。

  • java代码负责处理一些事情,比如说按按钮之后还会干啥。。。
  • 资源文件就是资源是代码使用的附加文件和静态内容,例如位图,布局定义,用户界面字符串,动画说明等。像一些什么布局文件(XML)啊,图片啊,音乐啊等等

相关资源在 这里

Java获取资源

在运用编译时,Android中有一个叫 aapt 的工具,这个工具会产生 R 类(就是一个简单的R.java文件)这个里面S目录里包含所有资源文件的ID

有两种方式使用ID:

  • 在Java代码中用 R.资源类型.资源名 的形式调用。比如 R.string.helloR.drawable.photo
  • 在XML文件中,用 @资源类型/资源名 的形式调用比如@string/hello@drawable/photo

XML&JAVA

当你点击APP的时候,它会打开MainActivity,此时什么都看不到,因为它在初始化。然后java中的onCreate方法会被自动调用,activity会被创建。

MainActivity中的 onCreate方法中有一句setContentView(R.layout.activity_main);,这个对应着布局文件的资源ID。此时XML文件与Java文件就结合起来了 。Android程序就开始解析XML文件,识别XML文件中的各种布局还有View等等。

findViewById方法

这个方法会在XML文件中找到与传入ID相对应的View,然后在onCreate方法中处理它

例如下面这个:

代码语言:javascript代码运行次数:0运行复制
View textView = findViewById(R.id.order_summary_text_view);

这个语句的意思就是:我们传入一个id参数 R.id.order_summary_text_viewfindViewById 方法。这个方法会遍历整个XML文件,直到找到id为 R.id.order_summary_text_view 的一个View,然后把这个View作为一个Java对象返回,然后把这个对象存放在名字为textView 的View类对象中。

注:如果ID为为 R.id.order_summary_text_view 的View是TextView的话,它是无法使用TextView类的方法的,因为findViewById创建的是一个View类型的对象,如果要用TextView的特殊方法,就必须要使用以下的语句

代码语言:javascript代码运行次数:0运行复制
TextView textView = (TextView) findViewById(R.id.order_summary_text_view);

向 Android 日志中写消息

注:这个是抄的Udacity上面的

本质上,你是在代码中写出类似于以下内容的 Java 语句:

代码语言:javascript代码运行次数:0运行复制
Log.i("eatCookie","Oh my God, You Killed Kenny!!!");

然后运行应用,并查看屏幕的 Android 日志部分。你将看到如下图所示的输出结果:

第一个参数是日志语句所来自的类的名称。第二个参数是你想要显示的文字

这里,我们使用了 Log.i(),表示“信息”级别的日志。其他级别的选项如下所示:

  • e(String, String)(错误)
  • w(String, String)(警告)
  • i(String, String)(信息)
  • d(String, String)(调试)
  • v(String, String) (详情)

它们对应的是不同的日志级别,当你运行应用时可以在下图所示位置进行设置:

当你设置日志级别时,它将显示该日志级别及更高级别的所有日志消息,所以“详情 (verbose)”日志级别显示的消息最多,而“错误”日志级别仅显示最严重的日志。

本地化

在Android中,你可以把所有的字符内容都储存在一个文件里面,每一个字符都有一个唯一的ID。这样的话,当你创建一个想要翻译这个APP是,就只需要改变这个文件里面的东西了,而不用跑到每个文件里更改。这个文件就是 res/values/strings.xml 文件。

看上去是下面这个样子的

代码语言:javascript代码运行次数:0运行复制
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="name"> 姓名</string>
    <string name="toppings">配料</string>
    <string name="order">预定</string>
    ...
</resources>

其中第一个" " 里的就是id,后面的那个就是翻译的内容。

注:除了编写 string.xml 文件外,还可以使用 Android Studio 自身的 Translations Editor ,用起来很舒服。界面简单易懂,这里就不做介绍了。

调用这个文件的方式还是使用id进行调用,具体实现方式如下

  • Java: getString(R.string.name) ,得到字符串
  • XML: @string/name

Style & Theme

emmmmmm不想写了,有生之年再来填坑吧

到时候看官方文档得了

让你的应用连接到别的应用?

这里是运用 Intent 知识。Intent 是要求其他应用组件完成的一个信息,让我们的应用调用其他的应用,比如说连接到邮箱啊,相机啊日历啊等等。当然必须要确保有应用可以实现这个功能,要不然程序就会崩溃。

一般的 Intent 的里面有动作、数据URI、目录还有一些其他的消息等等

在 这里 有一个比较基础的介绍。

例如,你想链接到邮件,就可以在 Java 文件中写入下面类似的语句

代码语言:javascript代码运行次数:0运行复制
public void composeEmail(String[] addresses, String subject) {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:")); // only email apps should handle this
    intent.putExtra(Intent.EXTRA_EMAIL, addresses);
    //收件人地址,不过好像没效果
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);//主题
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);}
    //这个是为了防止没有应用可以外链而避免程序的崩溃
}

多屏应用

Android资源文件

这里只说 res 文件夹里的东西。这个里面的一般都是控制程序外观的文件,包括一些XML文件、图片、还有其他媒体文件

  • layout文件夹:这个里面存放着的就是一些 activity 的XML文件,定义了应用的布局
  • mipmap文件夹:放应用图标的文件夹
  • value 文件夹
    • color.xml:定义了应用的颜色,反正是各种颜色
    • dimensions.xml:包括不同的维度,高度,宽度等等,这一系列的
    • strings.xml:放置字符的,让我们很容易的将应用翻译成其他语言,以及更改文字等等
    • style.xml:包含主题和样式

AndroidManifest.xml

每个文件都必须有的一个文件。这个里面存放着应用的一些重要信息,比如java的包名、应用组件、Intent权限等等,以及所有的activity。

在这个里面,有一个 intent-filter 代码。具体长这样:

代码语言:javascript代码运行次数:0运行复制
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

这个Intent是一种代码,用来要求其他应用执行操作;这个Intent-filter就厉害些,它相当于表明程序的入口。当点击应用图标时,Android将会发送一个Intent来启动我们的应用

当然在这里还可以更改每一个 Activity 的 lable 名称

代码语言:javascript代码运行次数:0运行复制
android:label="@string/category_about"

使用Intent打开其他Activity

要使用Intent必须首先要创建一个Intent对象。然后传入两个值,一个 context 和一个 class 组件

代码语言:javascript代码运行次数:0运行复制
Intent intentName = new Intent(this, ActivityName.class)

其中 this 表示当前 Activity 的 context

然后呢,打开这个Activity

代码语言:javascript代码运行次数:0运行复制
startActivity(intentName);

这样的话安卓就会启动我们的Activity,应用也就相对应的切换到 ActivityName 这个里面了。

当然这个与上文 让你的应用连接到别的应用 的Intent是有所不同的。因此Intent可以被分为两类:显式的 intent隐式的 intent

显式的 intent 是指知道执行那个操作的是谁,是十分具体的指向。就是 本块 中的示例

隐式的 intent 是指你不知道执行那个操作的是谁,只要是可以执行的都可以执行操作。到最后是谁执行还不清楚。 让你的应用连接到别的应用 中的就是隐式的 intent

事件监视器Listener

之前点击应用,完成一系列的操作,我们是在 XML 文件中进行的

代码语言:javascript代码运行次数:0运行复制
android:onclick = "methodInJava"

下面介绍的这个可以不用 XML 文件执行(其实也就是探究 onclick 的本质)

首先了解一下 过程,在用户点击按钮时(用户输入事件),物理设备会检测到一些数据,然后通知Android发生了这个事件,安卓就会通过点击的位置信息定位到相对应的View上。事件监视器 就是来获取这些信息的,如果有特定的信息传入[比如点击],你知道这个事件发生了,就可以执行一些交互了,如 methodInJava 方法。

注:事件监视器在Java中其实是一个接口类。接口类中,方法全为抽象方法,也没有数据成员。

了解了过程,接下来就是要使用了,使用事件监视器可以按照以下3步走:

  1. 建立一个事件监视器类在 Name.java文件:public class ClickTest implements View.OnClickListener { @Override public void onClick(View view) { //做你想做的事情 } }
  2. 创建事件监视器的实例ClickTest cickTest = new ClickTest();
  3. 连接你的事件监视器和对应的 ViewTextView about = (TextView) findViewById(R.id.about); //首先要构造一个TextView的实例才能对它进行操作嘛 about.setOnClickListener(cickTest) //连接你的事件监视器和对应的 View

这样的话,事件监视器就被使用了。当然,为了代码的可读性,还可以进行简化,该文件为 MainActivity.java

代码语言:javascript代码运行次数:0运行复制
// 将活动的内容设置为使用activity_main.xml布局文件,一般系统会自动生成
// 也就是说下面的内容定义在了 activity_main.xml 中
// 如果注释掉就会使 setOnClickListener 报错:NullPointerException
setContentView(R.layout.activity_main);
​
//创造出一个about的TextView实例出来,这样就可以对它进行操作了
TextView about = (TextView) findViewById(R.id.about);
​
//用户点击about这个文字的时候做出一些操作的方法
//使用事件监视器(Listener)需要调用set...Listener方法
//set...Listener方法需要传入一个...Listener对象
//此处本来应该构造一个有OnClickListener接口的aboutOnClickListener类的对象,然后将他示例化,但是本例中把这个简化了
about.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
    //下面,创建一个Intent类对象,并直接把这个当做参数传递给startActivity方法
    //用来打开AboutActivity
        startActivity(new Intent(MainActivity.this, AboutActivity.class));
        }
    }//直接创建一个OnClickListener的类,然后实例化当做setOnClickListener的参数
);
//以后可以看谁不爽直接 new 一个类出来

ArrayList[数组列表]

其实跟数组差不多。与数组的区别有以下几个方面:

  1. 数组列表的长度是可以改变的,数组列表中有多少元素其长度就是多少
  2. 数组列表是一种类型,数组的话,就比较基本
  3. 既然是一种类型,就可以调用各种各样的方法,你还可以继承它,覆盖一些方法等等(可玩性更高吧)
  4. 数组列表只能包含对象数据类型,向 int 这种就只能使用它们的包装类了

注:一般来说固定长度的使用数组,不固定长度的使用数组列表

ArrayList 的文档在:这里

在 Java 中,ArrayList 继承自AbstractList<E>,实现implements List<E>接口,是一个泛型类

代码语言:javascript代码运行次数:0运行复制
注:泛型类有主要以下类型参数:
    E:元素    K:键     N:数字    T:类型    V:值

下面列举一些常见的ArrayList使用方法

用途

Java

创建数组列表

ArrayList<Word> familyList = new ArrayList<Word>();

增加元素

familyList.add(new Word(getString(R.string.phrase_Where), "minto wuksus"));

去除元素

familyList.remove(new Word(getString(R.string.phrase_Where), "minto wuksus"));

查看元素

familyList.get(0);、familyList.get(1);、familyList.get(2);

查看元素数量

familyList.size();

内存优化——ListView+ArrayAdapter

我们之前要创建一串列表时,肯定是这样的

代码语言:javascript代码运行次数:0运行复制
LinearLayout number_LinearLayout = (LinearLayout) findViewById(R.id.numbers_LinearLayout);//先建立一个LinearLayout
TextView[] textViews = new TextView[restaurantsToTry.size()];
for (int i = 0; i < restaurantsToTry.size(); i++) {
    textViews[i] = new TextView(this);
    textViews[i].setText(restaurantsToTry.get(i));
    number_LinearLayout.addView(textViews[i]);
}//然后填上TextView

但是随着数据的增大,一次显示的东西也曰来越多,所占用的内存也会越来越大,从而导致卡顿。这个是我们很不愿意看到了。为了解决这个问题,有以下的思路:

我们不一次显示所有的啊东西,只是显示屏幕上需要的东西。就是根据屏幕,创建所需要的视图。如果屏幕不需要,我们就不显示,把它抛弃了;如果需要就建立一个。这样成了一个可循环的了,屏幕上不需要的循环到屏幕上需要的。

做到这一步需要 一个可循环的ViewGroup + 一个配适器(ArrayAdapter) 。可循环的ViewGroup有:ListView、GridView、RecylcerView 等等

下面来以ListView为例说原理:

ArrayAdapter会处理数据,将他们调用或传输到ListView上,然后在上面显示

ListView可以看成是用户界面,ArrayAdapter是处理数据的。

ListView首先会向ArrayAdapter询问数据的长度。然后ListView会向ArrayAdapter调用一个方法(相当于一个请求),传入一个position,即用户正在查看的列表的位置。得到了请求之后,ArrayAdapter会查看数据结构,然后创造出一个View出来。当屏幕占满的时候,ListView就会停止请求。当屏幕滚动的时候,不在可见的View就会到一个 Scrap Views 的地方,然后ListView请求新的东西,传入 Scrap Views 的position,然后达到循环利用。

原理部分说明完毕。(其实最后还是有些不清楚。。。)

实现这个还是要三步走:

  1. 构造一个ListView对象ListView listview = (ListView) findViewById(R.id.list)这样才能对ListView进行操作嘛。当然,为了实现这个必须想要建立一个id为R.id.list的ListView在xml文件中,比如这个<ListView xmlns:android="; android:id="@+id/list" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_vertical_margin"/>
  2. 构造一个ArrayAdapter对象ArrayAdapter arrayAdapter = new WordAdapter(this, arrayListName);第一个参数为context,第二个参数为要传入其中的arrayList,数组啊等等
  3. 将ListView对象与ArrayAdapter对象联系起来listView.setAdapter(arrayAdapter);

这样的话,一个列表就形成了。不过目前还有一个问题:ArrayList一次只能传入一个参数。ArrayAdapter只能生成一个TextView。如果想要产生一个比较复杂的列表(比如通讯录既有图片又有文字),采用刚刚那样就会报错。

如果需要解决就必须要自定义一些内容,下面介绍自定义的东西:

  • 数据类这是由于ArrayList造成的。ArrayList一次只能传入一个参数。如果一个列有两个项目(比如一个单词的翻译放在List就有中文和英文两项),就必须要自己创造一种类型。这种类型包含两个项目。比如说这里就可以创造一个 Word 类型public class Word { private String defaultWord; private String anotherWord; ​ //获取default语言 public String getDefaultWord() {return defaultWord;} ​ //获取另外一种语言 public String getAnotherWord() {return anotherWord;} ​ //构造函数无返回值 Word(String defaultWord, String anotherWord) { this.defaultWord = defaultWord; this.anotherWord = anotherWord; } }
  • 配适器(Adapter)类这回是要创建自己的Adapter,让它能够一次生成多个View出来(改写getView方法)public class WordAdapter extends ArrayAdapter<Word> { ​ //构造函数,不写这个不给用ArrayAdapter WordAdapter(Activity context, ArrayList<Word> wordArrayList) { //第二个参数设置,在 getView 方法中会得到,因此可以是任何数字 super(context, 0, wordArrayList); } ​ //为 AdapterView 提供(构件)View @Override public View getView(int position, View convertView, ViewGroup parent) { // Check if the existing view is being reused, otherwise inflate the view View listItemView = convertView; if (listItemView == null) { listItemView = LayoutInflater.from(getContext()).inflate( R.layout.list_item, parent, false); } ​ // 获取 restaurantsToTry[ArrayList类] 在position这个位置上的值 // 在这个例子中,这个值是一个 Word 类型的 Word currentAndroidFlavor = getItem(position); ​ // 建立一个指定id的 TextView 的实例,并且命名为 nameTextView // 注意:findViewById方法在 View中有,在这里没有 //因此要通过 listItemView.findViewById调用 TextView nameTextView = (TextView) listItemView.findViewById(R.id.numbers_translate_TextView); nameTextView.setText(currentAndroidFlavor.getDefaultWord()); ​ TextView numberTextView = (TextView) listItemView.findViewById(R.id.numbers_micwok_TextView); numberTextView.setText(currentAndroidFlavor.getMiwokWord()); ​ return listItemView; } }

这样的话一些自定义也结束了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2020-04-08 ,如有侵权请联系 cloudcommunity@tencent 删除入门事件android布局对象

Android入门之旅

注:这是一个学习笔记。很可惜 Google Study Jams 活动取消了,于是就只能自己来了,幸好 Google 官方有很多面向新手的教程,那么,开干!本文基于/ 给出的教程(而且是中文教程,感觉很良心)

2018©Fu_Qingchen,Typora

本文的运行环境是:

代码语言:javascript代码运行次数:0运行复制
Android Studio 3.1
Build #AI-173.4670197, built on March 22, 2018
JRE: 1.8.0_152-release-1024-b02 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0

总体规划

参照 Google Study Jams 的活动进行

第一阶段

  • L1 (3:38:59):1A (1:04:07) 、1B (1:13:59)、1C (1:20:53)
  • L2 (5:07:02):2A (2:00:40)、2B (1:03:40)、2C (2:02:42)
  • L3 (4:25:20):3A (2:15:36)、3B (2:09:44)
  • 拓展 (2:06:44):Firebase 介绍(0:34:25) + Firebase 周末(1:32:19)

第二阶段

  • 实践教程:制作结业 App、上载结业 App 到 Google Play

总时长 15:18:05,建议 40 - 45 小时的空闲时间学习 ,比如工作日每天一个小时,周末每天两个小时。

用户界面

1C为AndroidStudio的运用,暂不介绍

View

简单来说一个展示内容的长方形,有很多,像什么TestView,ImageView,Button等等

XML

描述Android外观的语言

注:下面的代码块中,注释的写法是错误的,但是为了方便,还是这么写了

例如

代码语言:javascript代码运行次数:0运行复制
<TextView //类型
          android:text="Happy Birthday!"
          //属性名="值" 的形式
          android:background="@android:color/darker_gray"//属性值放在引号内部
          android:layout_width="150dp"
          android:layout_height="75dp"</TextView>
//当然也可以如果需要嵌套,必须使用
//</TextView>来结束
TextView
代码语言:javascript代码运行次数:0运行复制
<TextView
      android:text="Happy Birthday!"
      android:background="@android:color/darker_gray"
      android:background="#2196F3"//替换自己的颜色
      android:layout_width="150dp"
          dp代表密度无关像素,其中可以接触的东东需要至少48dp
          //用dp的原因是不同的设备点像素点的大小是不同的,dp可以使不同的设备显示相同的尺寸
      //android:layout_height="75dp"
      android:layout_height="warp_content"
          //让TextView的高度正好等于文字的高度
      //android:textSize="45sp"//大小可以按照MD的说明来弄,其中sp是比例无关像素
      android:textAppearance="?android:textAppearanceLarge"
          //用系统的文字大小进行匹配/>

相关链接:TextView官方文档

ImageView
代码语言:javascript代码运行次数:0运行复制
<ImageView
      android:src="@drawable/cake"
           //使用@符号表示在Android APP里面引用一个资源
           //drawable是一种资源类型,能将图形显示在屏幕上
           //cake是图片名,不需要添加文件的扩展名
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:scaleType="center"
           //不改变图片大小,然后居中显示
           //android:scaleType="centerCrop"//放大缩小以满足 View 的宽高要求/>

相关链接:ImageView官方文档

ViewGroup

ViewGroup是一个组,相当于是一个容器,他能管理底下的TextView,ImageView,Button等等

LinearLayout

线性布局,分为水平和竖直两种。一般竖直的比较常用

在下面的例子中会介绍线性布局的一些基础内容,还有布局权重

代码语言:javascript代码运行次数:0运行复制
<LinearLayout
    xmlns:android=";
    android:orientation="vertical"
              //线性布局的方向为"竖直"
    android:layout_width="match_parent"
              //这是一种新的标尺寸的东东,与之前的"wrap_content"类似。
              //"match_parent"的含义是:这个尺寸与父级的尺寸相同
              //此处LinearLayout宽就与设备宽度相同,下同
    android:layout_height="match_parent">
            <注意这里有一个">"/>
​
    <ImageView
        android:src="@drawable/ocean"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="5"
        android:scaleType="centerCrop" />
<
    这里出现了layout_weight="1"此处的weight就是权重。
    在这个例子中,ImageView占比5/6,TextView占比1/6
    当有权重weight出现时通常把对应的值设置为0(竖直:height)
    />
    <TextView
        android:text="You're invited!"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="54sp"
        android:layout_weight="1"
        android:background="#009688" />
​
</LinearLayout>

RelativeLayout

相对布局

顾名思义嘛,同样的,在例子中解释

代码语言:javascript代码运行次数:0运行复制
<RelativeLayout
    xmlns:android=";
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
<
   相对布局就不需要android:orientation这个方向属性了
    />
   
    <ImageView
        android:id="@+id/ocean_image_view"
               //相对的嘛,就需要参照物了,参照物需要一个名字,就是id
               //由于这里是添加属性,因此是"@+id"
               //一般习惯性的给每个View都给一个id
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ocean" />
​
    <TextView
        android:id="@+id/Pebble_Beach_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Pebble Beach"
        android:layout_toRightOf="@id/ocean_image_view"
        android:textAppearance="?android:textAppearanceMedium" />
<
    其中layout_toRightOf属性就是表示相对位置的,含义是在参照物的右边
    同理,还有layout_below,layout_above,toLeftOf,见下方
    />
​
    <TextView
        android:id="@+id/California_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="California"
        android:layout_toRightOf="@id/ocean_image_view"
        android:layout_below="@id/Pebble_Beach_text_view"
        android:textAppearance="?android:textAppearanceSmall" />
​
<
    除了把其他View当作参照物,还可以直接把父视图当作参照物,用以下的语句表示:
    android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_centerHorizontal="true"//水平居中
    android:layout_centerVertical="true"//竖直居中
    />
</RelativeLayout>

注意:为了避免过于复杂,能够使用线性视图就使用线性视图

内边距与外边距

内边距(padding)呢就是View本身往外边扩展一层,如果View有背景颜色的话,背景颜色也会扩充

外边距(margin)就是把View隔开一下,隔开的地方是没有颜色的。外边距讲究一种隔开的情况,因此需要建立在ViewGroup里面

下面的图形就是内边距和外边距的例子(PS:Google的教程截图)

其中蓝色部分代表TextView,红色部分代表ViewGroup,左边是内边距,右边是外边距

其实感觉外边距的运用广泛一些,可能跟最近卡片风格流行有关吧

控制内边距(padding)的语句有

代码语言:javascript代码运行次数:0运行复制
android:padding="8dp"   //对于全局
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"

控制外边距的语句有

代码语言:javascript代码运行次数:0运行复制
android:layout_margin="8dp" //对于全局
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"

当然,这个是可以对各个View分别设置的,也可以对ViewGroup设置

ConstraintLayout

约束布局,能够非常快速地制作自适应 UI的一种布局。

※ 构建布局的步骤

  1. 选择视图类型3 Button, 4 TextView
  2. 确定视图的位置标题下面是一行按钮和一个TextView,然后是另一个标题和TextView,最后面是一个Button
  3. 设置视图的样式内边距外边距什么的

用户交互

什么是Activity?

Activity是应用中用户可以操作的东西,有时候Activity就是应用中的一个屏幕。

比如在Google日历中,你点开时看到的就是一个Activity,让你查看日程的,而且这个Activity有一个侧边栏。Google日历的设置是另外一个Activity,让你设置一些东西的。

XML与Java在Android中有什么作用?

XML其实就是一个控制布局的,你可以在里边编辑你的UI

Java呢,就是控制程序的,实现各种各样的功能

XML如何调用Java?

在XML中,我们可以看到这样的语句:

代码语言:javascript代码运行次数:0运行复制
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="submitOrders"
    android:text="order" />

其中android:onClick="submitOrders" 就是用来调用Java中的submitOrders 方法的

如果submitOrders 方法是这样的,那么当用户点击ORDER 按钮时,就会执行相对应的display方法和displayPrice方法

代码语言:javascript代码运行次数:0运行复制
public void submitOrders(View view) {
    //将submitOrders变为submitOrder会在应用运行时报错
    int numberOfCoffee = 2;
    int price = 3;
    display(numberOfCoffee);
    displayPrice(numberOfCoffee * price);
}

Debug

debug是消除bug的调试过程

系统日志

System Log: Android开发中常用logcat这个工具来分层次、分类型地显示不同等级的日志,方便程序员查找感兴趣的信息(错误信息或者更琐碎、更底层的信息)。

断点功能

为了快速找到错误指令,我们可以在希望设备暂停的指令位置插入一个断点,类似停车标志或路障。然后我们可以让调试器从第一条指令开始全速运行应用,运行至断点时,设备一定会暂停供我们进行检查。

使用方法

进行Debugging必须首先进入debug模式,Android的debug是用一只小瓢虫代替。

进入Debug模式之后,程序会和运行时一样重新编译这个App,此时手机会弹出提示,过一会等弄好了,提示也就自己消失了。

当在手机上操作时,在Android Studio的程序框里面就会显示信息,程序运行到断点就会停止,你可以看到一些数据的值

这里非常详细的介绍了Debug模式的使用方法

Nested ViewGroups

嵌套视图组,简单的说就是可以在一个布局里面嵌套多个布局。比如说在竖直的线性布局里面嵌套水平布局。

比如说下面这个图例:

  • 图例首先是包含两个子视图一个竖直的线性布局(vertical LinearLayout)
  • 第一个子视图是一个包含3个子视图的水平线性布局(horizontal LinearLayout)
  • 第二个子视图是一个包含4个子视图的相对布局(RelativeLayout)
    • 其中一个子视图还包含着一个子视图

Java字符串

代码语言:javascript代码运行次数:0运行复制
String message = "Item count" + quantity + 3;   
//字符串还可以这么写,其中quantity是字符变量

其他的都是Java基础了,这里就不写了

控制对齐的属性

主要有两个:layout_gravity 以及 gravity

关于两者的区别:

  • layout_gravity是对整个view的布局。view整体发生变化,但是view里面的内容改咋样还是咋样
  • gravity是对view内的布局。view本身不变,变的是里面的东西

Java常量

在编程语言中,常量是指在整个程序中永远不会改变的值。在 Java 中,你可以使用关键字 final 来强制规定某个值不得被更改。例如:

代码语言:javascript代码运行次数:0运行复制
final int POINTS_FOR_FREE_THROW = 1;

Then if you wrote the following, you'd get an error:

代码语言:javascript代码运行次数:0运行复制
POINTS_FOR_FREE_THROW = 100;

注意,按照惯例,常量的名称全为大写形式。此外,单词之间用下划线连接,而不用空格或用骆驼拼写法。你可以将变量声明为常量,防止自己意外地更改了变量的值。

Android的构成

一个Android应用主要由资源文件和java代码构成。

  • java代码负责处理一些事情,比如说按按钮之后还会干啥。。。
  • 资源文件就是资源是代码使用的附加文件和静态内容,例如位图,布局定义,用户界面字符串,动画说明等。像一些什么布局文件(XML)啊,图片啊,音乐啊等等

相关资源在 这里

Java获取资源

在运用编译时,Android中有一个叫 aapt 的工具,这个工具会产生 R 类(就是一个简单的R.java文件)这个里面S目录里包含所有资源文件的ID

有两种方式使用ID:

  • 在Java代码中用 R.资源类型.资源名 的形式调用。比如 R.string.helloR.drawable.photo
  • 在XML文件中,用 @资源类型/资源名 的形式调用比如@string/hello@drawable/photo

XML&JAVA

当你点击APP的时候,它会打开MainActivity,此时什么都看不到,因为它在初始化。然后java中的onCreate方法会被自动调用,activity会被创建。

MainActivity中的 onCreate方法中有一句setContentView(R.layout.activity_main);,这个对应着布局文件的资源ID。此时XML文件与Java文件就结合起来了 。Android程序就开始解析XML文件,识别XML文件中的各种布局还有View等等。

findViewById方法

这个方法会在XML文件中找到与传入ID相对应的View,然后在onCreate方法中处理它

例如下面这个:

代码语言:javascript代码运行次数:0运行复制
View textView = findViewById(R.id.order_summary_text_view);

这个语句的意思就是:我们传入一个id参数 R.id.order_summary_text_viewfindViewById 方法。这个方法会遍历整个XML文件,直到找到id为 R.id.order_summary_text_view 的一个View,然后把这个View作为一个Java对象返回,然后把这个对象存放在名字为textView 的View类对象中。

注:如果ID为为 R.id.order_summary_text_view 的View是TextView的话,它是无法使用TextView类的方法的,因为findViewById创建的是一个View类型的对象,如果要用TextView的特殊方法,就必须要使用以下的语句

代码语言:javascript代码运行次数:0运行复制
TextView textView = (TextView) findViewById(R.id.order_summary_text_view);

向 Android 日志中写消息

注:这个是抄的Udacity上面的

本质上,你是在代码中写出类似于以下内容的 Java 语句:

代码语言:javascript代码运行次数:0运行复制
Log.i("eatCookie","Oh my God, You Killed Kenny!!!");

然后运行应用,并查看屏幕的 Android 日志部分。你将看到如下图所示的输出结果:

第一个参数是日志语句所来自的类的名称。第二个参数是你想要显示的文字

这里,我们使用了 Log.i(),表示“信息”级别的日志。其他级别的选项如下所示:

  • e(String, String)(错误)
  • w(String, String)(警告)
  • i(String, String)(信息)
  • d(String, String)(调试)
  • v(String, String) (详情)

它们对应的是不同的日志级别,当你运行应用时可以在下图所示位置进行设置:

当你设置日志级别时,它将显示该日志级别及更高级别的所有日志消息,所以“详情 (verbose)”日志级别显示的消息最多,而“错误”日志级别仅显示最严重的日志。

本地化

在Android中,你可以把所有的字符内容都储存在一个文件里面,每一个字符都有一个唯一的ID。这样的话,当你创建一个想要翻译这个APP是,就只需要改变这个文件里面的东西了,而不用跑到每个文件里更改。这个文件就是 res/values/strings.xml 文件。

看上去是下面这个样子的

代码语言:javascript代码运行次数:0运行复制
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="name"> 姓名</string>
    <string name="toppings">配料</string>
    <string name="order">预定</string>
    ...
</resources>

其中第一个" " 里的就是id,后面的那个就是翻译的内容。

注:除了编写 string.xml 文件外,还可以使用 Android Studio 自身的 Translations Editor ,用起来很舒服。界面简单易懂,这里就不做介绍了。

调用这个文件的方式还是使用id进行调用,具体实现方式如下

  • Java: getString(R.string.name) ,得到字符串
  • XML: @string/name

Style & Theme

emmmmmm不想写了,有生之年再来填坑吧

到时候看官方文档得了

让你的应用连接到别的应用?

这里是运用 Intent 知识。Intent 是要求其他应用组件完成的一个信息,让我们的应用调用其他的应用,比如说连接到邮箱啊,相机啊日历啊等等。当然必须要确保有应用可以实现这个功能,要不然程序就会崩溃。

一般的 Intent 的里面有动作、数据URI、目录还有一些其他的消息等等

在 这里 有一个比较基础的介绍。

例如,你想链接到邮件,就可以在 Java 文件中写入下面类似的语句

代码语言:javascript代码运行次数:0运行复制
public void composeEmail(String[] addresses, String subject) {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:")); // only email apps should handle this
    intent.putExtra(Intent.EXTRA_EMAIL, addresses);
    //收件人地址,不过好像没效果
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);//主题
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);}
    //这个是为了防止没有应用可以外链而避免程序的崩溃
}

多屏应用

Android资源文件

这里只说 res 文件夹里的东西。这个里面的一般都是控制程序外观的文件,包括一些XML文件、图片、还有其他媒体文件

  • layout文件夹:这个里面存放着的就是一些 activity 的XML文件,定义了应用的布局
  • mipmap文件夹:放应用图标的文件夹
  • value 文件夹
    • color.xml:定义了应用的颜色,反正是各种颜色
    • dimensions.xml:包括不同的维度,高度,宽度等等,这一系列的
    • strings.xml:放置字符的,让我们很容易的将应用翻译成其他语言,以及更改文字等等
    • style.xml:包含主题和样式

AndroidManifest.xml

每个文件都必须有的一个文件。这个里面存放着应用的一些重要信息,比如java的包名、应用组件、Intent权限等等,以及所有的activity。

在这个里面,有一个 intent-filter 代码。具体长这样:

代码语言:javascript代码运行次数:0运行复制
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

这个Intent是一种代码,用来要求其他应用执行操作;这个Intent-filter就厉害些,它相当于表明程序的入口。当点击应用图标时,Android将会发送一个Intent来启动我们的应用

当然在这里还可以更改每一个 Activity 的 lable 名称

代码语言:javascript代码运行次数:0运行复制
android:label="@string/category_about"

使用Intent打开其他Activity

要使用Intent必须首先要创建一个Intent对象。然后传入两个值,一个 context 和一个 class 组件

代码语言:javascript代码运行次数:0运行复制
Intent intentName = new Intent(this, ActivityName.class)

其中 this 表示当前 Activity 的 context

然后呢,打开这个Activity

代码语言:javascript代码运行次数:0运行复制
startActivity(intentName);

这样的话安卓就会启动我们的Activity,应用也就相对应的切换到 ActivityName 这个里面了。

当然这个与上文 让你的应用连接到别的应用 的Intent是有所不同的。因此Intent可以被分为两类:显式的 intent隐式的 intent

显式的 intent 是指知道执行那个操作的是谁,是十分具体的指向。就是 本块 中的示例

隐式的 intent 是指你不知道执行那个操作的是谁,只要是可以执行的都可以执行操作。到最后是谁执行还不清楚。 让你的应用连接到别的应用 中的就是隐式的 intent

事件监视器Listener

之前点击应用,完成一系列的操作,我们是在 XML 文件中进行的

代码语言:javascript代码运行次数:0运行复制
android:onclick = "methodInJava"

下面介绍的这个可以不用 XML 文件执行(其实也就是探究 onclick 的本质)

首先了解一下 过程,在用户点击按钮时(用户输入事件),物理设备会检测到一些数据,然后通知Android发生了这个事件,安卓就会通过点击的位置信息定位到相对应的View上。事件监视器 就是来获取这些信息的,如果有特定的信息传入[比如点击],你知道这个事件发生了,就可以执行一些交互了,如 methodInJava 方法。

注:事件监视器在Java中其实是一个接口类。接口类中,方法全为抽象方法,也没有数据成员。

了解了过程,接下来就是要使用了,使用事件监视器可以按照以下3步走:

  1. 建立一个事件监视器类在 Name.java文件:public class ClickTest implements View.OnClickListener { @Override public void onClick(View view) { //做你想做的事情 } }
  2. 创建事件监视器的实例ClickTest cickTest = new ClickTest();
  3. 连接你的事件监视器和对应的 ViewTextView about = (TextView) findViewById(R.id.about); //首先要构造一个TextView的实例才能对它进行操作嘛 about.setOnClickListener(cickTest) //连接你的事件监视器和对应的 View

这样的话,事件监视器就被使用了。当然,为了代码的可读性,还可以进行简化,该文件为 MainActivity.java

代码语言:javascript代码运行次数:0运行复制
// 将活动的内容设置为使用activity_main.xml布局文件,一般系统会自动生成
// 也就是说下面的内容定义在了 activity_main.xml 中
// 如果注释掉就会使 setOnClickListener 报错:NullPointerException
setContentView(R.layout.activity_main);
​
//创造出一个about的TextView实例出来,这样就可以对它进行操作了
TextView about = (TextView) findViewById(R.id.about);
​
//用户点击about这个文字的时候做出一些操作的方法
//使用事件监视器(Listener)需要调用set...Listener方法
//set...Listener方法需要传入一个...Listener对象
//此处本来应该构造一个有OnClickListener接口的aboutOnClickListener类的对象,然后将他示例化,但是本例中把这个简化了
about.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
    //下面,创建一个Intent类对象,并直接把这个当做参数传递给startActivity方法
    //用来打开AboutActivity
        startActivity(new Intent(MainActivity.this, AboutActivity.class));
        }
    }//直接创建一个OnClickListener的类,然后实例化当做setOnClickListener的参数
);
//以后可以看谁不爽直接 new 一个类出来

ArrayList[数组列表]

其实跟数组差不多。与数组的区别有以下几个方面:

  1. 数组列表的长度是可以改变的,数组列表中有多少元素其长度就是多少
  2. 数组列表是一种类型,数组的话,就比较基本
  3. 既然是一种类型,就可以调用各种各样的方法,你还可以继承它,覆盖一些方法等等(可玩性更高吧)
  4. 数组列表只能包含对象数据类型,向 int 这种就只能使用它们的包装类了

注:一般来说固定长度的使用数组,不固定长度的使用数组列表

ArrayList 的文档在:这里

在 Java 中,ArrayList 继承自AbstractList<E>,实现implements List<E>接口,是一个泛型类

代码语言:javascript代码运行次数:0运行复制
注:泛型类有主要以下类型参数:
    E:元素    K:键     N:数字    T:类型    V:值

下面列举一些常见的ArrayList使用方法

用途

Java

创建数组列表

ArrayList<Word> familyList = new ArrayList<Word>();

增加元素

familyList.add(new Word(getString(R.string.phrase_Where), "minto wuksus"));

去除元素

familyList.remove(new Word(getString(R.string.phrase_Where), "minto wuksus"));

查看元素

familyList.get(0);、familyList.get(1);、familyList.get(2);

查看元素数量

familyList.size();

内存优化——ListView+ArrayAdapter

我们之前要创建一串列表时,肯定是这样的

代码语言:javascript代码运行次数:0运行复制
LinearLayout number_LinearLayout = (LinearLayout) findViewById(R.id.numbers_LinearLayout);//先建立一个LinearLayout
TextView[] textViews = new TextView[restaurantsToTry.size()];
for (int i = 0; i < restaurantsToTry.size(); i++) {
    textViews[i] = new TextView(this);
    textViews[i].setText(restaurantsToTry.get(i));
    number_LinearLayout.addView(textViews[i]);
}//然后填上TextView

但是随着数据的增大,一次显示的东西也曰来越多,所占用的内存也会越来越大,从而导致卡顿。这个是我们很不愿意看到了。为了解决这个问题,有以下的思路:

我们不一次显示所有的啊东西,只是显示屏幕上需要的东西。就是根据屏幕,创建所需要的视图。如果屏幕不需要,我们就不显示,把它抛弃了;如果需要就建立一个。这样成了一个可循环的了,屏幕上不需要的循环到屏幕上需要的。

做到这一步需要 一个可循环的ViewGroup + 一个配适器(ArrayAdapter) 。可循环的ViewGroup有:ListView、GridView、RecylcerView 等等

下面来以ListView为例说原理:

ArrayAdapter会处理数据,将他们调用或传输到ListView上,然后在上面显示

ListView可以看成是用户界面,ArrayAdapter是处理数据的。

ListView首先会向ArrayAdapter询问数据的长度。然后ListView会向ArrayAdapter调用一个方法(相当于一个请求),传入一个position,即用户正在查看的列表的位置。得到了请求之后,ArrayAdapter会查看数据结构,然后创造出一个View出来。当屏幕占满的时候,ListView就会停止请求。当屏幕滚动的时候,不在可见的View就会到一个 Scrap Views 的地方,然后ListView请求新的东西,传入 Scrap Views 的position,然后达到循环利用。

原理部分说明完毕。(其实最后还是有些不清楚。。。)

实现这个还是要三步走:

  1. 构造一个ListView对象ListView listview = (ListView) findViewById(R.id.list)这样才能对ListView进行操作嘛。当然,为了实现这个必须想要建立一个id为R.id.list的ListView在xml文件中,比如这个<ListView xmlns:android="; android:id="@+id/list" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_vertical_margin"/>
  2. 构造一个ArrayAdapter对象ArrayAdapter arrayAdapter = new WordAdapter(this, arrayListName);第一个参数为context,第二个参数为要传入其中的arrayList,数组啊等等
  3. 将ListView对象与ArrayAdapter对象联系起来listView.setAdapter(arrayAdapter);

这样的话,一个列表就形成了。不过目前还有一个问题:ArrayList一次只能传入一个参数。ArrayAdapter只能生成一个TextView。如果想要产生一个比较复杂的列表(比如通讯录既有图片又有文字),采用刚刚那样就会报错。

如果需要解决就必须要自定义一些内容,下面介绍自定义的东西:

  • 数据类这是由于ArrayList造成的。ArrayList一次只能传入一个参数。如果一个列有两个项目(比如一个单词的翻译放在List就有中文和英文两项),就必须要自己创造一种类型。这种类型包含两个项目。比如说这里就可以创造一个 Word 类型public class Word { private String defaultWord; private String anotherWord; ​ //获取default语言 public String getDefaultWord() {return defaultWord;} ​ //获取另外一种语言 public String getAnotherWord() {return anotherWord;} ​ //构造函数无返回值 Word(String defaultWord, String anotherWord) { this.defaultWord = defaultWord; this.anotherWord = anotherWord; } }
  • 配适器(Adapter)类这回是要创建自己的Adapter,让它能够一次生成多个View出来(改写getView方法)public class WordAdapter extends ArrayAdapter<Word> { ​ //构造函数,不写这个不给用ArrayAdapter WordAdapter(Activity context, ArrayList<Word> wordArrayList) { //第二个参数设置,在 getView 方法中会得到,因此可以是任何数字 super(context, 0, wordArrayList); } ​ //为 AdapterView 提供(构件)View @Override public View getView(int position, View convertView, ViewGroup parent) { // Check if the existing view is being reused, otherwise inflate the view View listItemView = convertView; if (listItemView == null) { listItemView = LayoutInflater.from(getContext()).inflate( R.layout.list_item, parent, false); } ​ // 获取 restaurantsToTry[ArrayList类] 在position这个位置上的值 // 在这个例子中,这个值是一个 Word 类型的 Word currentAndroidFlavor = getItem(position); ​ // 建立一个指定id的 TextView 的实例,并且命名为 nameTextView // 注意:findViewById方法在 View中有,在这里没有 //因此要通过 listItemView.findViewById调用 TextView nameTextView = (TextView) listItemView.findViewById(R.id.numbers_translate_TextView); nameTextView.setText(currentAndroidFlavor.getDefaultWord()); ​ TextView numberTextView = (TextView) listItemView.findViewById(R.id.numbers_micwok_TextView); numberTextView.setText(currentAndroidFlavor.getMiwokWord()); ​ return listItemView; } }

这样的话一些自定义也结束了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2020-04-08 ,如有侵权请联系 cloudcommunity@tencent 删除入门事件android布局对象

本文标签: Android入门之旅