打造一款計算器(1)界面設計
學習android有一段時間了,計划打造一款簡單易用的計算器,界面及功能從最基礎的樣式開始,后續實現的過程中再慢慢進行完善。
歡迎感興趣的朋友一起討論、學習,大家共同進步。
寫這篇文章時,還沒有對計算器界面上按鈕對應的功能進行實現,只是給出界面設計及布局生成(xml代碼的編寫)過程中需要注意的地方。
1、界面設計布局代碼
1 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:id="@+id/tablelayout_calculator" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:stretchColumns="*" > 6 7 <TextView android:id="@+id/text_input" 8 android:layout_weight="3" 9 android:layout_height="0dp" 10 android:layout_width="match_parent" 11 android:hint="input something" 12 android:gravity="bottom|right" 13 android:textSize="@dimen/text_size" 14 android:textColor="#0000ff" /> 15 16 <TableRow android:layout_weight="1" > 17 <Button android:id="@+id/btn_sin" 18 android:layout_height="match_parent" 19 android:layout_width="wrap_content" 20 android:text="sin" 21 android:textSize="@dimen/text_size" 22 android:textAllCaps="false" /> 23 <Button android:id="@+id/btn_cos" 24 android:layout_height="match_parent" 25 android:layout_width="wrap_content" 26 android:text="cos" 27 android:textSize="@dimen/text_size" 28 android:textAllCaps="false" /> 29 <Button android:id="@+id/btn_tan" 30 android:layout_height="match_parent" 31 android:layout_width="wrap_content" 32 android:text="tan" 33 android:textSize="@dimen/text_size" 34 android:textAllCaps="false" /> 35 <Button android:id="@+id/btn_cls" 36 android:layout_height="match_parent" 37 android:layout_width="wrap_content" 38 android:text="C" 39 android:textSize="@dimen/text_size" 40 android:textAllCaps="false" /> 41 <Button android:id="@+id/btn_del" 42 android:layout_height="match_parent" 43 android:layout_width="wrap_content" 44 android:text="Del" 45 android:textSize="@dimen/text_size" 46 android:textAllCaps="false" /> 47 </TableRow> 48 49 <TableRow android:layout_weight="1" > 50 <Button android:id="@+id/btn_pia" 51 android:layout_height="match_parent" 52 android:layout_width="wrap_content" 53 android:text="@string/calculator_pia" 54 android:textSize="@dimen/text_size" /> 55 <Button android:id="@+id/btn_lna" 56 android:layout_height="match_parent" 57 android:layout_width="wrap_content" 58 android:text="ln" 59 android:textSize="@dimen/text_size" 60 android:textAllCaps="false" /> 61 <Button android:id="@+id/btn_log" 62 android:layout_height="match_parent" 63 android:layout_width="wrap_content" 64 android:text="log" 65 android:textSize="@dimen/text_size" 66 android:textAllCaps="false" /> 67 <Button android:id="@+id/btn_fac" 68 android:layout_height="match_parent" 69 android:layout_width="wrap_content" 70 android:text="!" 71 android:textSize="@dimen/text_size" 72 android:textColor="#ff9933" /> 73 <Button android:id="@+id/btn_add" 74 android:layout_height="match_parent" 75 android:layout_width="wrap_content" 76 android:text="+" 77 android:textSize="@dimen/text_size" 78 android:textColor="#ff9933" /> 79 </TableRow> 80 81 <TableRow android:layout_weight="1"> 82 <Button android:id="@+id/btn_7" 83 android:layout_height="match_parent" 84 android:layout_width="wrap_content" 85 android:text="7" 86 android:textSize="@dimen/text_size" /> 87 <Button android:id="@+id/btn_8" 88 android:layout_height="match_parent" 89 android:layout_width="wrap_content" 90 android:text="8" 91 android:textSize="@dimen/text_size" /> 92 <Button android:id="@+id/btn_9" 93 android:layout_height="match_parent" 94 android:layout_width="wrap_content" 95 android:text="9" 96 android:textSize="@dimen/text_size" /> 97 <Button android:id="@+id/btn_pow" 98 android:layout_height="match_parent" 99 android:layout_width="wrap_content" 100 android:text="^" 101 android:textSize="@dimen/text_size" 102 android:textColor="#ff9933"/> 103 <Button android:id="@+id/btn_sub" 104 android:layout_height="match_parent" 105 android:layout_width="wrap_content" 106 android:text="-" 107 android:textSize="@dimen/text_size" 108 android:textColor="#ff9933" /> 109 </TableRow> 110 111 <TableRow android:layout_weight="1"> 112 <Button android:id="@+id/btn_4" 113 android:layout_height="match_parent" 114 android:layout_width="wrap_content" 115 android:text="4" 116 android:textSize="@dimen/text_size" /> 117 <Button android:id="@+id/btn_5" 118 android:layout_height="match_parent" 119 android:layout_width="wrap_content" 120 android:text="5" 121 android:textSize="@dimen/text_size" /> 122 <Button android:id="@+id/btn_6" 123 android:layout_height="match_parent" 124 android:layout_width="wrap_content" 125 android:text="6" 126 android:textSize="@dimen/text_size" /> 127 <Button android:id="@+id/btn_sqr" 128 android:layout_height="match_parent" 129 android:layout_width="wrap_content" 130 android:text="@string/calculator_sqr" 131 android:textSize="@dimen/text_size" 132 android:textColor="#ff9933" /> 133 <Button android:id="@+id/btn_mul" 134 android:layout_height="match_parent" 135 android:layout_width="wrap_content" 136 android:text="*" 137 android:textSize="@dimen/text_size" 138 android:textColor="#ff9933" /> 139 </TableRow> 140 141 <TableRow android:layout_weight="1"> 142 <Button android:id="@+id/btn_1" 143 android:layout_height="match_parent" 144 android:layout_width="wrap_content" 145 android:text="1" 146 android:textSize="@dimen/text_size" /> 147 <Button android:id="@+id/btn_2" 148 android:layout_height="match_parent" 149 android:layout_width="wrap_content" 150 android:text="2" 151 android:textSize="@dimen/text_size" /> 152 <Button android:id="@+id/btn_3" 153 android:layout_height="match_parent" 154 android:layout_width="wrap_content" 155 android:text="3" 156 android:textSize="@dimen/text_size" /> 157 <Button android:id="@+id/btn_lef" 158 android:layout_height="match_parent" 159 android:layout_width="wrap_content" 160 android:text="(" 161 android:textSize="@dimen/text_size" 162 android:textColor="#ff9933" /> 163 <Button android:id="@+id/btn_div" 164 android:layout_height="match_parent" 165 android:layout_width="wrap_content" 166 android:text="/" 167 android:textSize="@dimen/text_size" 168 android:textColor="#ff9933" /> 169 </TableRow> 170 171 <TableRow android:layout_weight="1"> 172 <Button android:id="@+id/btn_0" 173 android:layout_height="match_parent" 174 android:layout_width="wrap_content" 175 android:text="0" 176 android:textSize="@dimen/text_size" /> 177 <Button android:id="@+id/btn_00" 178 android:layout_height="match_parent" 179 android:layout_width="wrap_content" 180 android:text="00" 181 android:textSize="@dimen/text_size" /> 182 <Button android:id="@+id/btn_poi" 183 android:layout_height="match_parent" 184 android:layout_width="wrap_content" 185 android:text="." 186 android:textSize="@dimen/text_size" /> 187 <Button android:id="@+id/btn_rig" 188 android:layout_height="match_parent" 189 android:layout_width="wrap_content" 190 android:text=")" 191 android:textSize="@dimen/text_size" 192 android:textColor="#ff9933" /> 193 <Button android:id="@+id/btn_equ" 194 android:layout_height="match_parent" 195 android:layout_width="wrap_content" 196 android:text="=" 197 android:textSize="@dimen/text_size" 198 android:textColor="#ff9933" /> 199 </TableRow> 200 201 </TableLayout>
2、xml代碼簡單分析
針對計算器這種功能性按鈕呈類似表格狀分布的應用程序界面,筆者首先想到的布局組件就是TableLayout和TableRow。
從xml布局代碼或開頭的界面示意圖可以看出,整體界面的布局采用的組件如下:
a、根元素是1個TableLayout,並且設置了屬性android:stretchColumns="*",保證其子組件TableRow中的元素所占列寬相同;
b、第二級子組件為1個TextView和6個TableView,前者TextView用來顯示用戶輸入內容和最終計算結果;后者每個TableRow各有五個按鈕,即總共30個按鈕;
下面主要介紹一下布局代碼中需要注意的地方。
a、第8、9行對於TextView組件的高度屬性設置為android:layout_weight="3" , android:layout_height="0dp",結合后面的5個TableRow組件的高度屬性設置android:layout_weight="1",那么整個TableLayout的所占的界面高度被分為了8份,最終效果為1個TextView占總高度的3/8,5個TableRow各占總高度1/8;
b、第22行對於按鈕文本內容顯示的大小寫屬性設置為android:textAllCaps="false",false表示最終顯示在按鈕的文本內容的大小寫和定義時一致,如果不設置的話默認為true,那么程序會自動將本文全部轉為大寫;
c、第20、26等行是在xml布局文件中直接對按鈕文本進行設置,規范的做法應該是在資源文件values/strings.xml(名稱自取,不固定)文件中進行定義,然后在xml文件中利用@string/xxx(Java代碼中是R.string.xxx)的形式進行獲取。當然,有些字串是無法直接在xml布局文件中進行輸入的,如π(pi,53行)、√(sqrt,130行)等,這時就必須在資源文件中對其進行定義,利用機器能夠識別的十進制編碼。定義代碼如下:
1 <string name="calculator_pia">π</string> 2 <string name="calculator_sqr">√</string>
d、當然,可以將每個按鈕或者每個TableRow結合styles等屬性分別定義成可復用的xml文件,那樣的話在最終的界面布局文件activity_calculator.xml中只需要利用include關鍵字導入定義好的TableRow組件對應的文件名即可。這部分設計本文沒有給出,后面實現過程中如有必要的話會進行實現並寫入文章中;
e、雖然按鈕對應的功能實現本文沒有涉及,但其對應的id命名這里先解釋一下。像btn_0、btn_1這種很好理解,對應的按鍵是數字0、1,而像π、√、.這類按鈕的id名稱為btn_pia、btn_sqr、btn_poi。即除了數字一目了然外,其余的命名均采用btn_xxx的形式,這樣做的目的是在后續的Java文件中獲取組件id時有個統一的標准,畢竟組件很多的情況下有個可以參考的線索是比較省腦細胞的。
3、字串賦值規范化
既然說到字串等資源定義的規范化,接下來就將上面介紹的按鈕文本直接賦值轉為資源文件+Java代碼的設置方式。
首先將所有按鈕用到的字串統一定義到資源文件values/strings_calculator.xml中,具體如下。
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <string-array name="strings_calculator" > 5 6 <item>sin</item> 7 <item>cos</item> 8 <item>tan</item> 9 <item>C</item> 10 <item>Del</item> 11 12 <item>π</item> 13 <item>ln</item> 14 <item>log</item> 15 <item>!</item> 16 <item>+</item> 17 18 <item>7</item> 19 <item>8</item> 20 <item>9</item> 21 <item>^</item> 22 <item>-</item> 23 24 <item>4</item> 25 <item>5</item> 26 <item>6</item> 27 <item>√</item> 28 <item>*</item> 29 30 <item>1</item> 31 <item>2</item> 32 <item>3</item> 33 <item>(</item> 34 <item>/</item> 35 36 <item>0</item> 37 <item>00</item> 38 <item>.</item> 39 <item>)</item> 40 <item>=</item> 41 42 </string-array> 43 44 </resources>
接下來得注意,定義了字串資源文件后,對組件的文本進行設置可以在xml布局文件中,也可以在Java代碼中。雖然常見的也較符合常理的做法是在xml文件中利用android:text="@string/xxx"進行設置,但是針對本文介紹的計算器而言,在Java代碼中進行設置更為方便。結合TableLayout和TableRow的特性,來看看怎樣快速地對左右按鈕進行本文的設置。
1 package com.dylan_wang.calculator; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.view.Menu; 6 import android.view.MenuItem; 7 import android.widget.Button; 8 import android.widget.TableLayout; 9 import android.widget.TableRow; 10 11 public class ActivityCalculator extends Activity { 12 13 @Override 14 protected void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.activity_calculator); 17 18 String[] stringsCalculator = getResources().getStringArray(R.array.strings_calculator); 19 TableLayout tableLayout = (TableLayout)findViewById(R.id.tablelayout_calculator); 20 for(int i=1;i<tableLayout.getChildCount();++i){ 21 TableRow tableRow = (TableRow)tableLayout.getChildAt(i); 22 for(int j=0;j<tableRow.getChildCount();++j){ 23 Button button = (Button)tableRow.getChildAt(j); 24 button.setText(stringsCalculator[(i-1)*5+j]); 25 } 26 } 27 } 28 29 @Override 30 public boolean onCreateOptionsMenu(Menu menu) { 31 // Inflate the menu; this adds items to the action bar if it is present. 32 getMenuInflater().inflate(R.menu.menu_main, menu); 33 return true; 34 } 35 36 @Override 37 public boolean onOptionsItemSelected(MenuItem item) { 38 // Handle action bar item clicks here. The action bar will 39 // automatically handle clicks on the Home/Up button, so long 40 // as you specify a parent activity in AndroidManifest.xml. 41 int id = item.getItemId(); 42 43 //noinspection SimplifiableIfStatement 44 if (id == R.id.action_settings) { 45 return true; 46 } 47 48 return super.onOptionsItemSelected(item); 49 } 50 }
可以看到,真正只用了9行代碼(18-26)就完成了30個按鈕的本文獲取與設置。當然,如果在各行按鈕之間穿插其他組件的話,得分情況處理。
從界面示意圖可以看出,乘除號分別是*與/,並不是理想中的×與÷。那么對於π(pi,53行)、√(sqrt,130行)這種特殊字符對應編碼去哪找,乘除號(×與÷)又該怎么輸入呢?
對於前者,有一個總結得比較齊全的網站http://www.cnblogs.com/zhouyinhui/p/4025637.html,是咱們博客園中的同志貢獻的,供大家參考。
而對於乘除號這類符號靠輸入法+細心就能搞定了,相信平時大家在中文p拼音模式下(有時英文也會出現)輸入一些中文字的部分或全部字符時一定看到過,輸入法提示框中會出現額外的數學符號。如在百度輸入chu,會出現以下提示框:
輸入ch,竟然乘除號都出來了:
若是輸入cheng,則沒有想象中的×出現:
當然,不同電腦及輸入法會有差異,但不出意外的話該方法是能夠幫助我們獲取到想要的符號的。
將乘除號設置為×、÷,並將清零與回刪按鈕標記為紅色后的界面如下:
4、總結
至此只是完成了一款計算器粗略的界面設計部分,后續會慢慢對各按鈕對應的功能進行實現,有必要也會對界面進行完善。
最后分享一個感覺不錯的png等圖標獲取網站http://www.easyicon.net/iconsearch//,如果直接打開有問題,也可以直接度娘easyicon。
歡迎討論,覺得有用且對后續實現感興趣的朋友幫忙點個贊哦^_^