zoukankan      html  css  js  c++  java
  • 【Android实验】UI设计-Android计算器

    实验目的

    自主完成一个简单APP的设计工作,综合应用已经学到的Android UI设计技巧,重点注意合理使用布局

    实验要求

    1. 完成一个计算器的设计,可以以手机自带的计算器为参考。设计过程中,注意考虑界面的美观性,不同机型的适应性,以及功能的完备性。
    2. 注意结合Activity的生命周期,考虑不同情况下计算器的界面状态。
    3. 如有余力,可以考虑实现一个高精度科学计算型的计算器。

    实验过程

    1. 界面设计

    界面仿照自己手机中计算器界面进行了设计,采用的布局是线性布局,其中比较特殊的布局是最后两行的布局,由于“=”键占用两个位置,所以采用vertical和horizontal相互配合的方式进行。

    界面的展示如下:

    界面代码(activity_caculator.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">
    
        <LinearLayout
            android:background="@drawable/a5"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:orientation="vertical"
            android:focusableInTouchMode="true">
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Calculator"
                android:textStyle="italic"
                android:textAlignment="center"
                android:textSize="20sp" />
    
            <EditText
                android:id="@+id/et_input"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="0"
                android:enabled="true"
                android:textAlignment="textEnd"
                android:textSize="30sp"
                android:background="@null"/>
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:weightSum="4">
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_clear"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFE4C4"
                android:text="C"
                android:textAlignment="center"
                android:textSize="20sp"/>
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_divide"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFE4C4"
                android:text="/"
                android:textAlignment="center"
                android:textSize="20sp"/>
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_times"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFE4C4"
                android:text="*"
                android:textAlignment="center"
                android:textSize="20sp"/>
    
            <Button
                android:id="@+id/btn_delete"
                style="?android:attr/buttonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFE4C4"
                android:text="DEL"
                android:textAlignment="center"
                android:textSize="20sp" />
        </LinearLayout>
    
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="1"
            android:weightSum="4">
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_7"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FDF5E6"
                android:text="7"
                android:textAlignment="center"
                android:textSize="20sp"/>
    
            <Button
                android:id="@+id/btn_8"
                style="?android:attr/buttonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FDF5E6"
                android:text="8"
                android:textAlignment="center"
                android:textSize="20sp" />
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_9"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FDF5E6"
                android:text="9"
                android:textAlignment="center"
                android:textSize="20sp"/>
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_sub"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="#FFC0CB"
                android:layout_weight="1"
                android:text="-"
                android:textAlignment="center"
                android:textSize="20sp"/>
        </LinearLayout>
    
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="1"
            android:weightSum="4">
    
            <Button style="?android:attr/buttonStyle"
                android:id="@+id/btn_4"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FDF5E6"
                android:text="4"
                android:textAlignment="center"
                android:textSize="20sp"/>
    
            <Button
                android:id="@+id/btn_5"
                style="?android:attr/buttonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FDF5E6"
                android:text="5"
                android:textAlignment="center"
                android:textSize="20sp" />
    
            <Button
                android:id="@+id/btn_6"
                style="?android:attr/buttonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FDF5E6"
                android:text="6"
                android:textAlignment="center"
                android:textSize="20sp" />
    
            <Button
                android:id="@+id/btn_add"
                style="?android:attr/buttonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#FFC0CB"
                android:text="+"
                android:textAlignment="center"
                android:textSize="20sp" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="2"
            android:weightSum="4">
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:layout_weight="1">
    
                <Button style="?android:attr/buttonStyle"
                    android:id="@+id/btn_1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#FDF5E6"
                    android:text="1"
                    android:textAlignment="center"
                    android:textSize="20sp"/>
    
                <Button style="?android:attr/buttonStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="%"
                    android:textAlignment="center"
                    android:background="#FDF5E6"
                    android:layout_weight="1"
                    android:id="@+id/btn_remainder"
                    android:textSize="20sp"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:layout_weight="1">
    
                <Button style="?android:attr/buttonStyle"
                    android:id="@+id/btn_2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#FDF5E6"
                    android:text="2"
                    android:textAlignment="center"
                    android:textSize="20sp"/>
    
                <Button style="?android:attr/buttonStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="0"
                    android:textAlignment="center"
                    android:background="#FDF5E6"
                    android:layout_weight="1"
                    android:id="@+id/btn_0"
                    android:textSize="20sp"/>
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:layout_weight="1">
                <Button style="?android:attr/buttonStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="3"
                    android:textAlignment="center"
                    android:background="#FDF5E6"
                    android:layout_weight="1"
                    android:id="@+id/btn_3"
                    android:textSize="20sp"/>
    
                <Button
                    android:id="@+id/btn_point"
                    style="?android:attr/buttonStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="#FDF5E6"
                    android:text="."
                    android:textAlignment="center"
                    android:textSize="20sp" />
            </LinearLayout>
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:layout_weight="1">
                <Button style="?android:attr/buttonStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="="
                    android:textAlignment="center"
                    android:background="#FFC0CB"
                    android:layout_weight="1"
                    android:id="@+id/btn_equal"
                    android:textSize="20sp"/>
            </LinearLayout>
    
        </LinearLayout>
    </LinearLayout>
    

    在界面设计的过程中,感觉android:layout_weight是一个比较重要的属性,整个界面的按比例排布都需要这个属性来决定,如果用绝对位置会导致翻转以后,计算器按钮无法按比例进行填充。

    另外界面的一个特点就是没有了ActionBar,这个通过设置Style.xml中的parent属性,从而可以改变。

    Style.xml文件如下:

    <resources>
        <!-- Base application theme. -->
        <style name="AppTheme" parent="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>
    

    另外的app命令以及图标替换在AndroidManifest.xml文件中更改:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.administrator.calculator">
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/pjthis"
            android:label="PjCalc"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">
            <activity android:name=".Caculator">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    修改APP名称在android:label属性中修改,APP图标在android:icon中修改,其中android:theme改为NoActionBar可以将头部的标题去掉,增大空间。在LinearLayout中修改android:backgroud可以对背景进行修改,这里换成了一个自定义背景。

    2. 功能设计

    进行事件响应的主体为:Calculator.java

    对界面事件的获取以及处理主要由该文件处理:

    代码如下:

    package com.example.administrator.calculator;
    
    import android.content.Context;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.Button;
    import android.widget.EditText;
    
    
    public class Caculator extends AppCompatActivity implements View.OnClickListener {
    
        Button bt_0, bt_1, bt_2, bt_3, bt_4, bt_5, bt_6, bt_7, bt_8, bt_9;
        Button bt_clear, bt_divide, bt_times, bt_delete, bt_add, bt_sub, bt_equal, bt_remainder, bt_point;
        private EditText et_input;
    
        private StringBuilder fomula = new StringBuilder();
    
        private void initP() {
            bt_0 = (Button) findViewById(R.id.btn_0);
            bt_1 = (Button) findViewById(R.id.btn_1);
            bt_2 = (Button) findViewById(R.id.btn_2);
            bt_3 = (Button) findViewById(R.id.btn_3);
            bt_4 = (Button) findViewById(R.id.btn_4);
            bt_5 = (Button) findViewById(R.id.btn_5);
            bt_6 = (Button) findViewById(R.id.btn_6);
            bt_7 = (Button) findViewById(R.id.btn_7);
            bt_8 = (Button) findViewById(R.id.btn_8);
            bt_9 = (Button) findViewById(R.id.btn_9);
            bt_clear = (Button) findViewById(R.id.btn_clear);
            bt_divide = (Button) findViewById(R.id.btn_divide);
            bt_times = (Button) findViewById(R.id.btn_times);
            bt_delete = (Button) findViewById(R.id.btn_delete);
            bt_add = (Button) findViewById(R.id.btn_add);
            bt_sub = (Button) findViewById(R.id.btn_sub);
            bt_equal = (Button) findViewById(R.id.btn_equal);
            bt_point = (Button) findViewById(R.id.btn_point);
            bt_remainder = (Button) findViewById(R.id.btn_remainder);
            et_input = (EditText) findViewById(R.id.et_input);
    
            et_input.setKeyListener(null);
    
    
            bt_0.setOnClickListener(this);
            bt_1.setOnClickListener(this);
            bt_2.setOnClickListener(this);
            bt_3.setOnClickListener(this);
            bt_4.setOnClickListener(this);
            bt_5.setOnClickListener(this);
            bt_6.setOnClickListener(this);
            bt_7.setOnClickListener(this);
            bt_8.setOnClickListener(this);
            bt_9.setOnClickListener(this);
            bt_add.setOnClickListener(this);
            bt_clear.setOnClickListener(this);
            bt_divide.setOnClickListener(this);
            bt_times.setOnClickListener(this);
            bt_delete.setOnClickListener(this);
            bt_sub.setOnClickListener(this);
            bt_remainder.setOnClickListener(this);
            bt_point.setOnClickListener(this);
            bt_equal.setOnClickListener(this);
    
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_caculator);
            initP();
        }
    
        @Override
        public void onClick(View v) {
            int latest = 0;
            if (fomula.length() != 0) {
                latest = fomula.codePointAt(fomula.length() - 1);
            }
            else
                latest = '.';
    
            switch (v.getId()) {
                case R.id.btn_0:
                    fomula = fomula.append("0");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_1:
                    fomula = fomula.append("1");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_2:
                    fomula = fomula.append("2");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_3:
                    fomula = fomula.append("3");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_4:
                    fomula = fomula.append("4");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_5:
                    fomula = fomula.append("5");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_6:
                    fomula = fomula.append("6");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_7:
                    fomula = fomula.append("7");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_8:
                    fomula = fomula.append("8");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_9:
                    fomula = fomula.append("9");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_sub:
                    if (latest >= '0' && latest <= '9')
                        fomula = fomula.append("-");
                    else {
                        if(latest != '.')
                            fomula.delete(fomula.length()-1, fomula.length());
                        fomula = fomula.append("-");
                    }
                    et_input.setText(fomula);
                    break;
                case R.id.btn_add:
                    if (latest >= '0' && latest <= '9')
                        fomula = fomula.append("+");
                    else {
                        if(latest != '.')
                            fomula.delete(fomula.length()-1, fomula.length());
                        fomula = fomula.append("+");
                    }
                    et_input.setText(fomula);
                    break;
                case R.id.btn_times:
                    if (latest >= '0' && latest <= '9')
                        fomula = fomula.append("*");
                    else {
                        if(latest != '.')
                            fomula = fomula.delete(fomula.length()-1,fomula.length());
                        fomula = fomula.append("*");
                    }
                    et_input.setText(fomula);
                    break;
                case R.id.btn_divide:
                    if (latest >= '0' && latest <= '9')
                        fomula = fomula.append("/");
                    else {
                        if(latest != '.')
                         fomula.delete(fomula.length()-1, fomula.length());
                        fomula = fomula.append("/");
                    }
                    et_input.setText(fomula);
                    break;
                case R.id.btn_delete:
                    if (fomula.length() > 0)
                        fomula = fomula.delete(fomula.length() - 1, fomula.length());
                    et_input.setText(fomula);
                    break;
                case R.id.btn_clear:
                    fomula = fomula.delete(0, fomula.length());
                    et_input.setText(fomula);
                    break;
                case R.id.btn_equal:
                    String ans="0";
                    if(fomula.length()>1){
                        InfixInToDuffix inf = new InfixInToDuffix();
                        try{
                            String a = inf.toSuffix(fomula);
                            System.out.println("out:");
                            System.out.println(a);
                            ans = inf.dealEquation(a);
                            fomula = fomula.delete(0,fomula.length());
                            fomula = fomula.append(ans);
                        }catch (Exception ex){
                            ans = "error";
                            fomula = fomula.delete(0,fomula.length());
                        }
                    }
                    et_input.setText(ans);
                    break;
                case R.id.btn_point:
                    fomula = fomula.append(".");
                    et_input.setText(fomula);
                    break;
                case R.id.btn_remainder:
                    if(latest >= '0' && latest <= '9'){
                        fomula.append("%");
                    }
                    else
                    {
                        if(latest != '.')
                            fomula.delete(fomula.length()-1,fomula.length());
                        fomula.append("%");
                    }
                    et_input.setText(fomula);
                    break;
            }
        }
    }
    

    声明各个按钮及部件,然后通过findViewById得到对应的对象,然后进行处理相应的处理。

    其中有几个细节需要处理,否则会导致程序崩溃:

    • 符号处理。
      • 符号前边不能有符号。
    • 小数点处理。
      • 如果结果是整数,不要加小数点。
      • 小数点的连续使用,如1.2.3.5.1。
    • 运算符号如果出现在数字之前,需要特殊判断。
    • 多个符号连续出现问题。
      • 处理方式为将上一个符号顶替下来,换成最新的运算符。
    • 减号如果作为-负号的情况出现。

    3. 运算处理

    主要是通过两个栈,将中缀转化为后缀,然后进行求解。其中“*/”运算符的优先级应该与“%”优先级一致,但是这里让“%”优先级低于"*/",然后进行的处理。

    package com.example.administrator.calculator;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.lang.*;
    import java.util.ArrayList;
    import java.util.*;
    /**
     * Created by pprp on 2018/9/22.
     */
    
    class InfixInToDuffix {
        //使用集合定义好符号的运算优先级别
        private static final Map<Character,Integer>basic =new HashMap<Character, Integer>();
        static {
            basic.put('-',1);
            basic.put('+', 1);
            basic.put('*', 3);
            basic.put('/', 3);
            basic.put('(', 0);
            basic.put('%',2);
        }
    
    
        //将中缀表达式转换为后缀表达式
        public String toSuffix(StringBuilder infix){
            List<String> queue = new ArrayList<String>();                                   
            List<Character> stack = new ArrayList<Character>();                            
    
            char[] charArr = infix.substring(0,infix.length()).trim().toCharArray();                                 
            String standard = "*/+-()%";                                                       
            char ch = '&';                                                                  
            int len = 0;                                                                    
            for (int i = 0; i < charArr.length; i++) {                                      
                ch = charArr[i];                                                            
                if(Character.isDigit(ch)) {                                                  
                    len++;
                }else if(ch == '.'){                                                      
                    len++;
                }else if(standard.indexOf(ch) != -1) {                                       
                    if(len > 0) {                                                           
                        queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));   
                        len = 0;                                                           
                    }
                    if(ch == '(') {                                                            
                        stack.add(ch);                                                        
                        continue;                                                          
                    }
                    if (!stack.isEmpty()) {                                                    
                        int size = stack.size() - 1;                                        
                        boolean flag = false;                                             
                        while (size >= 0 && ch == ')' && stack.get(size) != '(') {            
                            queue.add(String.valueOf(stack.remove(size)));                    
                            size--;                                                        
                            flag = true;                                                  
                        }
                        if(ch==')'&&stack.get(size) == '('){
                            flag = true;
                        }
                        while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) {   
                            queue.add(String.valueOf(stack.remove(size)));                 
                            size--;
                        }
                    }
                    if(ch != ')') {                                                      
                        stack.add(ch);                                                 
                    } else {                                                          
                        stack.remove(stack.size() - 1);
                    }
                }
                if(i == charArr.length - 1) {                                            
                    if(len > 0) {                                                     
                        queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1)));
                    }
                    int size = stack.size() - 1;                                       
                    while (size >= 0) {                                                       
                        queue.add(String.valueOf(stack.remove(size)));
                        size--;
                    }
                }
    
            }
            String a = queue.toString();
            return a.substring(1,a.length()-1);
        }
    
    
        public String dealEquation(String equation){
    
            String [] arr = equation.split(", ");
            List<String> list = new ArrayList<String>();
    
    
            for (int i = 0; i < arr.length; i++) {             
                int size = list.size();
                switch (arr[i]) {
                    case "+": double a = Double.parseDouble(list.remove(size-2))+ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(a));     break;
                    case "-": double b = Double.parseDouble(list.remove(size-2))- Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(b));     break;
                    case "*": double c = Double.parseDouble(list.remove(size-2))* Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(c));     break;
                    case "/": double d = Double.parseDouble(list.remove(size-2))/ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(d));       break;
                    case "%": double e = Double.parseDouble(list.remove(size-2)) % Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(e));     break;
                    default: list.add(arr[i]);     break;                                    //如果是数字  直接放进list中
                }
            }
            return list.size() == 1 ? list.get(0) : "Fail" ;                 
        }
    }
    
  • 相关阅读:
    jQuery
    前端开发之JavaScript篇
    前端开发之css篇
    前端开发之html篇
    mysql续
    MySQL入门
    进程线程协程那些事儿
    Python之socket网络编程
    2016.6.24——vector<vector<int>>【Binary Tree Level Order Traversal】
    2016.6.21——Climbing Stairs
  • 原文地址:https://www.cnblogs.com/pprp/p/9874621.html
Copyright © 2011-2022 走看看