課程實踐 2: 制作 Court Counter App

這是 Android 開發(fā)(入門)課程 的第一部分《布局和交互》的第二次課程實踐哼鬓,導(dǎo)師是 Lyla Fujiwara音婶,主要內(nèi)容是變量練習(xí)和 Court Counter App竞慢。

變量練習(xí)

這節(jié)課通過代碼找茬來練習(xí)變量的使用骑冗,可總結(jié)出兩種類型的錯誤:編譯期錯誤和邏輯錯誤拙泽。

編譯期錯誤
Android Studio 能夠識別并字體標(biāo)紅窖张,右側(cè)紅色方塊指示錯誤位置,在聲明和初始化變量時常犯豹障。

聲明變量可理解為創(chuàng)建一個新變量冯事,如

int total;

初始化變量則為新變量設(shè)定一個初始值,如

total = 10;

通常習(xí)慣將聲明和初始化變量寫在一起血公,如

int total = 10;

這兩項操作有嚴(yán)格的格式規(guī)范:

數(shù)據(jù)類型 變量名 = 初始值;
  1. 數(shù)據(jù)類型應(yīng)與系統(tǒng)設(shè)定完全相同桅咆,如整型 int 不能是 Integer、integer 和 INT坞笙,字符串 String 首字母大寫岩饼。數(shù)據(jù)類型在 Android Studio 中默認(rèn)為藍(lán)色。

  2. 數(shù)據(jù)類型與變量名之間的空格不能省略薛夜,也不允許其他任何字符籍茧,如 _ 或 - 。

  3. 變量名應(yīng)遵循命名規(guī)則梯澜,可 Google 搜索 "variable names java" 找到 Oracle 的說明文檔 寞冯。通常變量名不能太長也不能短到一兩個字母;若是一個單詞則全小寫晚伙;若是多個單詞則用小駝峰命名法吮龄。變量名不能與數(shù)據(jù)類型相同,也不能有符號和空格咆疗。

  4. 初始值要與數(shù)據(jù)類型匹配漓帚,如字符串的值應(yīng)在雙引號內(nèi),不允許出現(xiàn)

     int total = “10”;
    
  5. 分號結(jié)束午磁。

邏輯錯誤
非 XML 或 Java 語法錯誤尝抖,而是代碼功能無法實現(xiàn)的錯誤,所以 Android Studio 無法識別迅皇∶亮桑可關(guān)注以下幾點:

  1. 運(yùn)算符優(yōu)先級,可 Google 搜索 "arithmetic operators java" 找到 Oracle 的說明文檔 登颓。例如乘除的優(yōu)先級比加減的高搅荞,邏輯與的比邏輯或的高。若無法確定運(yùn)算符優(yōu)先級時用小括號分隔框咙,如

     // 最先做加法咕痛,然后乘法,最后減法
     total = 1 * ( 2 + 3 ) - 5; 
    
  2. 變量僅在賦值時改變值扁耐,運(yùn)算不會暇检。

  3. 局部變量在 method 內(nèi)聲明产阱,只在 method 內(nèi)部有效婉称,在 Android Studio 中為黑色。
    全局變量在 method 外聲明,在 method 之間有效王暗,可以保存數(shù)據(jù)悔据,在 Android Studio 中為紫色。
    若變量不跨 method 使用時用局部變量即可俗壹。

  4. 代碼按從上到下的順序運(yùn)行科汗,先前執(zhí)行過的代碼不會受后面的影響。

Court Counter App

首先構(gòu)建布局绷雏,按步驟進(jìn)行:分解 Views→畫 Views 層級圖→寫 XML 草稿→代碼實現(xiàn)头滔。

  1. 分解 Views。下圖為應(yīng)用最終布局圖涎显。

這里用到了嵌套ViewGroups坤检,有兩對水平對稱的 TextView 和三個 Button,每對垂直排列期吓,通過 vertical 的 LinearLayout 實現(xiàn)早歇;中間有一個 View 呈垂直線條狀,三者用 horizontal 的 LinearLayout 能實現(xiàn)讨勤;底部居中一個 Button箭跳,因此根 Views 應(yīng)為 RelativeLayout。

  1. 畫 Views 層級圖潭千,即樹狀圖
  1. 寫XML草稿谱姓,清晰條理
<RelativeLayout...>
    <LinearLayout...>
        <LinearLayout...>
            <TextView... />
            <TextView... />
            <Button.../>
            <Button.../>
            <Button.../>
        </LinearLayout>
        <View... />
        <LinearLayout...>
            <TextView... />
            <TextView... />
            <Button... />
            <Button... />
            <Button.../>
        </LinearLayout>
    </LinearLayout>
    <Button... />
</RelativeLayout>
  1. 代碼實現(xiàn)

In activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal"
       tools:context="com.example.android.courtcouter.MainActivity">

       <LinearLayout
           android:layout_width="0dp"
           android:layout_height="wrap_content"
           android:layout_weight="1"
           android:orientation="vertical">

           <TextView
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:fontFamily="sans-serif-medium"
               android:gravity="center_horizontal"
               android:padding="16dp"
               android:text="Team A"
               android:textColor="#616161"
               android:textSize="14sp" />

           <TextView
               android:id="@+id/team_a_score"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:fontFamily="sans-serif-light"
               android:gravity="center_horizontal"
               android:paddingBottom="24dp"
               android:text="0"
               android:textColor="#000000"
               android:textSize="56sp" />

           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginBottom="8dp"
               android:layout_marginLeft="24dp"
               android:layout_marginRight="24dp"
               android:onClick="addThreeForTeamA"
               android:text="+3 Points" />

           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginBottom="8dp"
               android:layout_marginLeft="24dp"
               android:layout_marginRight="24dp"
               android:onClick="addTwoForTeamA"
               android:text="+2 Points" />

           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginBottom="8dp"
               android:layout_marginLeft="24dp"
               android:layout_marginRight="24dp"
               android:onClick="addOneForTeamA"
               android:text="Free Throw" />
       </LinearLayout>

       <View
           android:layout_width="1dp"
           android:layout_height="match_parent"
           android:layout_marginTop="16dp"
           android:background="@android:color/darker_gray" />

       <LinearLayout
           android:layout_width="0dp"
           android:layout_height="wrap_content"
           android:layout_weight="1"
           android:orientation="vertical">

           <TextView
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:fontFamily="sans-serif-medium"
               android:gravity="center_horizontal"
               android:padding="16dp"
               android:text="Team B"
               android:textColor="#616161"
               android:textSize="14sp" />

           <TextView
               android:id="@+id/team_b_score"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:fontFamily="sans-serif-light"
               android:gravity="center_horizontal"
               android:paddingBottom="24dp"
               android:text="0"
               android:textColor="#000000"
               android:textSize="56sp" />

           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginBottom="8dp"
               android:layout_marginLeft="24dp"
               android:layout_marginRight="24dp"
               android:onClick="addThreeForTeamB"
               android:text="+3 Points" />

           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginBottom="8dp"
               android:layout_marginLeft="24dp"
               android:layout_marginRight="24dp"
               android:onClick="addTwoForTeamB"
               android:text="+2 Points" />

           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginBottom="8dp"
               android:layout_marginLeft="24dp"
               android:layout_marginRight="24dp"
               android:onClick="addOneForTeamB"
               android:text="Free Throw" />
       </LinearLayout>
   </LinearLayout>

   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       android:layout_centerHorizontal="true"
       android:layout_marginBottom="8dp"
       android:layout_marginLeft="22dp"
       android:layout_marginRight="22dp"
       android:onClick="resetScore"
       android:text="reset" />
</RelativeLayout>
  1. 寫完代碼后可在 activity_main.xml 文件的 Design 標(biāo)簽下的 component Tree 驗證嵌套 ViewGroups 層次是否正確。
  2. TextView 中的文字使用了 gravity 屬性實現(xiàn)居中對齊刨晴,這種方式使得在 LinearLayout 中實現(xiàn)類似 RelativeLayout 中的對齊布局逝段。TextView 的邊界較大時效果更明顯。
  3. 兩個第二層 LinearLayout 使用了 layout_weight 屬性實現(xiàn)水平平分寬度割捅,注意此時雙方的初始寬度應(yīng)為 0dp奶躯,否則不為零的一方將多占一部分寬度。
  4. 中間的垂直線條可用寬度為 1dp 的 Views 來實現(xiàn)亿驾。
  5. 注意內(nèi)邊距 padding 與外邊距 margin 的區(qū)別嘹黔。padding 會使 Views 內(nèi)的內(nèi)容距離指定位置有間隔,而 margin 會使子 Views 距離父 Views 中的指定位置有間隔莫瞬,不會改變子 Views儡蔓。

styles.xml 文件能控制 App 的基本樣式,統(tǒng)一修改布局疼邀。文件在左側(cè) Project 標(biāo)簽 Android 視圖中 app→res→values 路徑下喂江。以下代碼將 Court Counter App 的主色調(diào)改為橙色。

<resources>

   <!-- Base application theme. -->
   <style name="AppTheme" parent="Theme.AppCompat.Light">
       <!-- Customize your theme here. -->
       <item name="colorPrimary">#FF9800</item>
       <item name="android:colorButtonNormal">#FF9800</item>
   </style>

</resources>

最后通過 Button 的 android:onClick 屬性連接 XML 與 Java旁振,在 Java 中通過 method 實現(xiàn)功能获询。

In MainActivity.java

package com.example.android.courtcouter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


   int scoreTeamA = 0, scoreTeamB = 0;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
   }

   /**
    * Increase the score for Team A by 3 points.
    */
   public void addThreeForTeamA(View view) {
       scoreTeamA = scoreTeamA + 3;
       displayForTeamA(scoreTeamA);
   }

   /**
    * Increase the score for Team A by 2 points.
    */
   public void addTwoForTeamA(View view) {
       scoreTeamA = scoreTeamA + 2;
       displayForTeamA(scoreTeamA);
   }

   /**
    * Increase the score for Team A by 1 points.
    */
   public void addOneForTeamA(View view) {
       scoreTeamA = scoreTeamA + 1;
       displayForTeamA(scoreTeamA);
   }

   /**
    * Increase the score for Team B by 3 points.
    */
   public void addThreeForTeamB(View view) {
       scoreTeamB = scoreTeamB + 3;
       displayForTeamB(scoreTeamB);
   }

   /**
    * Increase the score for Team B by 2 points.
    */
   public void addTwoForTeamB(View view) {
       scoreTeamB = scoreTeamB + 2;
       displayForTeamB(scoreTeamB);
   }

   /**
    * Increase the score for Team B by 1 points.
    */
   public void addOneForTeamB(View view) {
       scoreTeamB = scoreTeamB + 1;
       displayForTeamB(scoreTeamB);
   }

   /**
    * Increase the score for Team B by 1 points.
    */
   public void resetScore(View view) {
       scoreTeamA = 0;
       scoreTeamB = 0;
       displayForTeamA(0);
       displayForTeamB(0);
   }

   /**
    * Displays the given score for Team A.
    */
   public void displayForTeamA(int score) {
       TextView scoreView = (TextView) findViewById(R.id.team_a_score);
       scoreView.setText(String.valueOf(score));
   }

   /**
    * Displays the given score for Team B.
    */
   public void displayForTeamB(int score) {
       TextView scoreView = (TextView) findViewById(R.id.team_b_score);
       scoreView.setText(String.valueOf(score));
   }
}
  1. 用全局變量保存兩隊的總分涨岁。
  2. 打開 "Add unambiguous imports on the fly" 功能,在發(fā)現(xiàn)未知量時立即添加清晰的 imports吉嚣,通常導(dǎo)入 Java 的庫或包梢薪。
  3. 在 Android Studio 中變量名默認(rèn)為紫色。
  4. 養(yǎng)成寫注釋的習(xí)慣尝哆。

課程至此秉撇,我做了第二個實戰(zhàn)項目——計分器應(yīng)用。這同樣是個簡單練習(xí)秋泄,在 Court Counter App 的基礎(chǔ)上稍作修改琐馆,達(dá)到如下圖的效果。

這次項目提交上去由導(dǎo)師審閱后恒序,給出了關(guān)于 App 資源文件相關(guān)的優(yōu)化建議啡捶,如

  1. 將 sp & dp 等尺寸相關(guān)的聲明放入 dimens.xml 內(nèi),而不是將 Views 的高度和寬度奸焙,以及字體的大小硬編碼 (hard coding)瞎暑;
  2. 將字符串變量放入了 strings.xml 內(nèi),方便應(yīng)用內(nèi)多處引用与帆,在翻譯應(yīng)用時也可以大大減少工作量了赌。
  3. 將 color 顏色值放入 colors.xml 內(nèi),統(tǒng)一管理顏色資源玄糟,而不是對顏色硬編碼勿她;
  4. 將樣式重復(fù)的 TextView、Button阵翎、LinearLayout 在 styles.xml 封裝調(diào)用逢并,使 XML 代碼簡潔易讀。

對 Android App 資源文件的介紹會在以后的課程中出現(xiàn)郭卫,在此先有個概念砍聊,不多作解釋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贰军,一起剝皮案震驚了整個濱河市玻蝌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌词疼,老刑警劉巖俯树,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贰盗,居然都是意外死亡许饿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門舵盈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陋率,“玉大人球化,你說我怎么就攤上這事∏讨” “怎么了赊窥?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵爆惧,是天一觀的道長狸页。 經(jīng)常有香客問我,道長扯再,這世上最難降的妖魔是什么芍耘? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮熄阻,結(jié)果婚禮上斋竞,老公的妹妹穿的比我還像新娘。我一直安慰自己秃殉,他們只是感情好坝初,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钾军,像睡著了一般鳄袍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吏恭,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天拗小,我揣著相機(jī)與錄音,去河邊找鬼樱哼。 笑死哀九,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搅幅。 我是一名探鬼主播阅束,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼茄唐!你這毒婦竟也來了围俘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤琢融,失蹤者是張志新(化名)和其女友劉穎界牡,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漾抬,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宿亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纳令。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挽荠。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡克胳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出圈匆,到底是詐尸還是另有隱情漠另,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布跃赚,位于F島的核電站笆搓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纬傲。R本人自食惡果不足惜满败,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叹括。 院中可真熱鬧算墨,春花似錦、人聲如沸汁雷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凌彬。三九已至灾挨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間继低,已是汗流浹背熬苍。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留袁翁,地道東北人柴底。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像粱胜,于是被迫代替她去往敵國和親柄驻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,111評論 25 707
  • afinalAfinal是一個android的ioc焙压,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評論 2 45
  • 你總說畢業(yè)遙遙無期野哭,轉(zhuǎn)眼就各奔東西。我的那些年就像這句老狼的歌詞幻件。有些人拨黔,一旦錯過了,就變成了陌路绰沥。匆匆那年里篱蝇,陳...
    可憶閱讀 310評論 0 0
  • 年初贺待,沫沫的額頭長出了小痘痘,起初以為是吃什么過敏零截,后來越來越多麸塞,發(fā)現(xiàn)是青春痘;某天涧衙,帶沫沫去洗澡哪工,發(fā)現(xiàn)乳...
    蘇日娜_ab97閱讀 1,331評論 10 12
  • 春寒料峭中,我走進(jìn)河北從南至北一個又一個村莊绍撞。到處塵土飛揚(yáng)正勒,滿地枯枝敗葉得院。絲毫不見春意盎然傻铣。越往北,到沽源祥绞,越荒涼...
    白龍珠閱讀 298評論 0 1