转载请注明出处: http://blog.csdn.net/like_program/article/details/51925765
上一篇博客,我们写的计算器已经有计算功能了,但是界面并不美观,这一篇博客,我将讲解 如何美化界面 。
在前面的博客中,由于我们的计算器的操作界面(GridView)用的是 Androd 自带的子项布局,而自带的子项布局是 textview,所以只能简单的显示文字,而且文字的大小,背景颜色等等,都无法修改。在这篇博客中,我们将使用自定义的子项布局,替换之前的 Android 自带的子项布局。
为了自定义布局,我们先来添加下自定义布局需要的颜色和尺寸,在 app / src / main / res / values 目录下的 colors.xml 文件和 dimens.xml 中,添加如下代码:
colors.xml 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorBlue">#729FFA</color>
<color name="colorGrayDark">#807877</color>
<color name="colorGrayLight">#B7A4A1</color>
<color name="colorOrange">#FA8072</color>
<color name="colorOrangeDark">#DA6052</color>
<color name="colorSalmon">#FFA07B</color>
<color name="colorSalmonDark">#D18263</color>
<color name="colorWhite">#FFFFFF</color>
<color name="colorGray">#9A614D</color>
<color name="colorBackground">#F5D3C7</color>
<color name="colorBlackBlue">#4B0082</color>
</resources>
dimens.xml 代码如下:
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="radius">5dp</dimen>
</resources>
定义好 颜色 和 尺寸 后,待会我们会在布局文件中引用到这些颜色和尺寸。
我们先来给计算器的界面组件添加背景颜色,修改 activity_calculator.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"
......
android:background="@color/colorBackground"
tools:context="com.example.calculatortest.CalculatorActivity" >
<!-- 标题 -->
<TextView
......
android:background="@color/colorBlue" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
......
<EditText
......
android:background="@color/colorWhite"/>
</RelativeLayout>
</LinearLayout>
定义好了界面组件的背景颜色后,接着我们来自定义子项布局,在 app / src / main / res / layout 目录下,新建一个 item_button.xml ,
item_button.xml 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="22sp"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="@color/colorBlackBlue"
android:background="@drawable/selector_button" />
</LinearLayout>
</LinearLayout>
代码很简单,我就不一一解释了。这里需要注意下
android:background="@drawable/selector_button"
这里定义 背景 时,引用的代码 @drawable/selector_button 中, selector_button 是一个单独的xml文件,之所以要引用一个 xml 文件,是因为我们要定义的背景是一个选择器,这个选择器有两种状态,一种是没有按下时的状态,一种是按下时的状态。两种状态下的按钮样式不同。
在 app / src / main / res / drawable 目录下,新建 selector_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 点击按钮 -->
<item android:state_pressed="true">
<shape >
<!-- 圆角,半径 -->
<corners android:radius="@dimen/radius"/>
<!-- 填充,颜色 -->
<solid android:color="@color/colorSalmon"/>
</shape>
</item>
<!-- 按钮正常状态,未点击 -->
<item >
<shape >
<!-- 圆角,半径 -->
<corners android:radius="@dimen/radius"/>
<!-- 填充,颜色 -->
<solid android:color="@color/colorSalmonDark"/>
</shape>
</item>
</selector>
我们可以看到,按钮在 点击 和 未点击 两种状态下的背景颜色是不一样的
选择器里还定义了 圆角半径 属性,这是为了避免矩形按钮看上去太生硬。
定义好了子项布局后,我们就要使用这个自定义子项布局了。要使用这个自定义子项布局,我们还需要自定义一个 GridView 的 Adapter(适配器),新建一个 CalculatorAdapter.java ,继承自 ArrayAdapter。
CalculatorAdapter.java 代码如下:
public class CalculatorAdapter extends ArrayAdapter<String> {
private int resourceId;
public CalculatorAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 获取当前项
String str = getItem(position);
// 实例化View
View view = LayoutInflater
.from(getContext()).inflate(R.layout.item_button, null);
// 根据view找到按钮对应的控件TextView
TextView textView = (TextView) view.findViewById(R.id.text_button);
// 设置按钮上的内容
textView.setText(str);
// 给Back和CE按钮单独加效果,根据str的值来判断
if (str.equals("Back")) {
textView.setBackgroundResource(R.drawable.selector_button_backspace);
textView.setTextColor(Color.WHITE);
} else if (str.equals("CE")) {
textView.setBackgroundResource(R.drawable.selector_button_clear);
textView.setTextColor(Color.WHITE);
}
return view;
}
}
每当实例化子项布局的时候,getView()方法就会被调用。这个方法中的 R.layout.item_button 就是我们自定义的布局,这段代码
View view = LayoutInflater
.from(getContext()).inflate(R.layout.item_button, null);
就会把我们自定义的子项布局加载出来,接着实例化 textview 控件,并设置对应的文字。然后对按钮上的文字进行判断,如果是 Back 或 CE,就给 Back 键或 CE 键设置新的背景和文字颜色。
在这里, Back 键和 CE 键的背景都是选择器
在 app / src / main / res / drawable 目录下,新建 selector_button_backspace.xml 和 selector_button_clear.xml
selector_button_backspace.xml 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true">
<shape >
<corners android:radius="@dimen/radius"/>
<solid android:color="@color/colorGray"/>
</shape>
</item>
<item >
<shape >
<corners android:radius="@dimen/radius"/>
<solid android:color="@color/colorGrayDark"/>
</shape>
</item>
</selector>
selector_button_clear.xml 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true">
<shape >
<corners android:radius="@dimen/radius"/>
<solid android:color="@color/colorOrangeDark"/>
</shape>
</item>
<item >
<shape >
<corners android:radius="@dimen/radius"/>
<solid android:color="@color/colorOrange"/>
</shape>
</item>
</selector>
定义好 Adapter(适配器)之后,我们就要在代码中设置适配器了。修改 CalculatorActivity.java ,代码如下:
public class CalculatorActivity extends AppCompatActivity {
/**
* 用来存储操作按钮上的字符集合
*/
private List<String> mTextBtnsList = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隐藏标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_calculator);
// 把字符集合依次添加到List中
initTextBtns();
......
// mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mTextBtns);
// 创建适配器
mAdapter = new CalculatorAdapter(this, R.id.text_button, mTextBtnsList);
// 设置适配器
mGridView.setAdapter(mAdapter);
......
}
/**
* 把字符集合依次添加到List中
*/
private void initTextBtns() {
for (String btn : mTextBtns) {
mTextBtnsList.add(btn);
}
}
}
这里创建了一个 ArrayList ,用来存储操作按钮上的字符集合,并把 mTextBtns 里的数据遍历存储到 ArrayList 中。这是因为适配器的构造函数需要的参数类型是 List 类型, String 数组类型不符合要求。
在适配器的构造函数中,我们分别传入 上下文,自定义子项布局的资源id,操作按钮上的字符集合。然后设置适配器, ok ,运行一下程序,我们就会发现,界面比之前要美观了不少。
最后,我们给这个 App 换个图标,因为自带的图标是个 ADT 自动生成的图标,太老土了。所以,我准备好了一张图片来作为软件图标。
将图片另存为 calculator_icon.png 并放入 app / src / main / res / mipmap-hdpi 目录下,修改 AndroidManifest.xml ,代码如下:
android:icon="@mipmap/calculator_icon"
大功告成!
看上去计算器 App 已经成功的写出来了。但是好像还有点瑕疵。
比如:
如果计算结果是 无限循环 或 无限不循环 小数,那么在屏幕上就会占很长一列空间。
能不能改进一下,判断计算结果的小数位,如果超过4位小数,就精确到4位小数。
还有,如果在计算完一个表达式后,直接按 + - × / 中任何一个运算符,再随便按一个数字,就不能连续计算表达式了。
能不能改进一下,如果在计算完一个表达式后,直接按 + - × / 中任何一个运算符,就把上一个表达式中计算的结果插到运算符前面,这样就可以连续计算表达式了。
下一篇博客 Android计算器解析(四): 完善计算功能 中,我将会讲解,如何 完善计算功能 。