欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

荐 Android 借书UI界面

程序员文章站 2022-03-12 08:38:03
文章目录案例说明实现案例视频UI布局UI效果activity_main.xml文件代码tostrings.xml文件代码书本类和用户类的定义书本类Book用户类Person功能实现初始化控件findViews()初始化数据initData()添加监听器setListeners()mNameEditText监听器mLendEditText监听器mSexRadioGroup监听器三个CheckBox的监听器SeekBar监听器mQueryButton监听器mNextButton监听器查找书籍方法主体日期比较方法...

案例说明

这个是我初学Android开发的时候用Java做的一个借书Demo,因为没有学数据库所以不包含数据库相关的技术,直接在代码中完成书籍的实例化操作

实现

  1. 完成UI界面搭建
  2. 完成书籍的查找并显示功能
  3. 完成书籍信息的“下一页”显示功能
  4. 完成借书时间判断功能
    • 输入的时间格式要按照演示视频的格式输入,并将输入的时间格式化成(yyyy-MM-dd)的形式
    • 判断日期,如果借出日期晚于还书日期,则弹出提示信息并调用finish()方法实现页面的关闭,当输入时间符合要求时则能正确查找图书

案例视频

UI布局

布局约束用的是线性布局LinearLayout,这一块基本没有什么难度,无非就是各个LinearLayout之间控制好权重属性android:layout_weight,具体的细节完全按照自己喜好来就可以

UI效果

荐
                                                        Android 借书UI界面

activity_main.xml文件代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFB4EA"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="@string/title"
        android:textColor="#AA5E91"
        android:textSize="26sp"
        android:textStyle="bold" />

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="10dp"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="@string/nametext"
                android:textSize="18sp"
                android:textStyle="bold" />

            <EditText
                android:id="@+id/nameEditText"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="30dp"
                android:layout_weight="1"
                android:hint="@string/inputname_hint"
                android:textSize="14dp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:text="@string/sextext"
                android:textSize="18sp"
                android:textStyle="bold" />

            <RadioGroup
                android:id="@+id/sexRadioGroup"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <RadioButton
                    android:id="@+id/male"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/male"
                    android:textSize="18sp" />

                <RadioButton
                    android:id="@+id/female"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/female"
                    android:textSize="18sp" />
            </RadioGroup>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="@string/lendtimetext"
                android:textSize="18sp"
                android:textStyle="bold" />

            <EditText
                android:id="@+id/lendEditText"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:hint="@string/inputlendtime_hint"
                android:textSize="14dp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/returntimetext"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/returnTime"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/returntime"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="@string/hobbytext"
                android:textSize="18sp"
                android:textStyle="bold" />

            <CheckBox
                android:id="@+id/hisCheckBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:text="@string/historytext"
                android:textSize="18sp" />

            <CheckBox
                android:id="@+id/susCheckBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:text="@string/suspensetext"
                android:textSize="18sp" />

            <CheckBox
                android:id="@+id/litCheckBox"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/literaturetext"
                android:textSize="18sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="@string/agetext"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/seekBar_ageTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"

                android:textSize="18sp" />

            <SeekBar
                android:id="@+id/seekBar"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="30dp"
                android:layout_marginRight="30dp"
                android:layout_weight="1" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:text="@string/age_100"
                android:textSize="18sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_weight="3"
            android:background="#FFD4EE"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/bookImageView"
                android:layout_width="250dp"
                android:layout_height="wrap_content"
                android:src="@mipmap/f" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:paddingTop="10dp">

                <TextView
                    android:id="@+id/bookNameTextView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="15dp"
                    android:text="@string/bookname"
                    android:textSize="16sp" />

                <TextView
                    android:id="@+id/bookKindTextView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="15dp"
                    android:text="@string/kind"
                    android:textSize="16sp" />

                <TextView
                    android:id="@+id/bookAgeTextView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/age"
                    android:textSize="16sp" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:padding="10dp">

        <Button
            android:id="@+id/queryBtn"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="#CC91BD"
            android:text="@string/querybtntext"
            android:textColor="#593152"
            android:textSize="20sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/bookNumTextView"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="-10dp"
            android:layout_marginRight="20dp" />

        <Button
            android:id="@+id/nextBtn"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:background="#CC91BD"
            android:text="@string/next"
            android:textColor="#593152"
            android:textSize="20sp"
            android:textStyle="bold" />
    </LinearLayout>
</LinearLayout>

tostrings.xml文件代码

<resources>
    <string name="app_name">LibraryDemo</string>
    <string name="title">借书</string>
    <string name="nametext">读者:</string>
    <string name="inputname_hint">请输入名字</string>
    <string name="sextext">性别:</string>
    <string name="male"></string>
    <string name="female"></string>
    <string name="lendtimetext">借出时间:</string>
    <string name="inputlendtime_hint">请输入</string>
    <string name="returntimetext">归还时间:</string>
    <string name="returntime">2016.06.30</string>
    <string name="hobbytext">爱好:</string>
    <string name="historytext">历史</string>
    <string name="suspensetext">悬疑</string>
    <string name="literaturetext">文艺</string>
    <string name="agetext">年龄:</string>
    <string name="age_18">18</string>
    <string name="age_100">100</string>
    <string name="bookname">书名</string>
    <string name="kind">类型</string>
    <string name="age">适用年龄</string>
    <string name="querybtntext">查找</string>
    <string name="next">下一个</string>
</resources>

书本类和用户类的定义

书本类Book

根据要求,书本类属性包括以下属性

  • String:书名name,类型kind
  • int:适用年龄age,图片的地址pic
  • boolean:是否属于历史、悬疑、文艺
public class Book {
    //属性:书名、类型、适用年龄、图片地址
    //三个boolean类型:历史、悬疑、文艺
    private String name;
    private String kind;
    private int age;
    private int pic;
    boolean his;
    boolean sus;
    boolean lit;

    public Book() {

    }

    public Book(String name, String kind, int age, int pic, boolean his, boolean sus, boolean lit) {
        this.name = name;
        this.kind = kind;
        this.age = age;
        this.pic = pic;
        this.his = his;
        this.sus = sus;
        this.lit = lit;
    }
    //getter和setter方法...
}

用户类Person

根据要求,书本类属性包括以下属性

  • String:姓名name,性别sex
  • int:年龄age
  • Date:借书时间lendTime
  • Book:书本类对象book
public class Person {
    //属性:姓名、性别、借书时间、书本
    //年龄默认为20岁
    private String name;
    private String sex;
    private int age = 20;
    private Date lendTime;
    private Book book;

    public Person() {

    }

    public Person(String name, String sex, int age, Date lendTime, Book book) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.lendTime = lendTime;
        this.book = book;
    }
    //getter和setter方法...
}

用户在UI界面输入的借书时间是String类型,不能通过Person类原始的setLendTime方法直接传参,需要将传进来的字符串进行格式转换

    //将输入的时间(String类型)转换为Date类型,格式"yyyy-MM-dd"
    public void setLendTime(String dateString) throws ParseException {
        this.lendTime = new SimpleDateFormat("yyyy-MM-dd").parse(dateString);
    }

功能实现

首先确定onCreate方法的实现思路
为了代码的可读性,我把功能实现都封装在了方法体内

  • 加载布局文件setContentView()
  • 初始化控件findViews()
  • 初始化数据initData()
  • 为控件添加监听器并实现基本功能setListeners()
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //初始化控件
        findViews();

        //初始化数据
        initData();

        //为控件添加监听器,实现基本功能
        setListeners();
    }

添加布局文件的方法在创建工程的时候已经自动生成了,所以就不用另外再写一遍

初始化控件findViews()

在这个方法体实现了获取控件ID的功能以及部分控件设置初始值操作

	//初始化控件,获取控件ID
    private void findViews() {
        mNameEditText = findViewById(R.id.nameEditText);
        mLendEditText = findViewById(R.id.lendEditText);
        mSexRadioGroup = findViewById(R.id.sexRadioGroup);
        mHisCheckBox = findViewById(R.id.hisCheckBox);
        mSusCheckBox = findViewById(R.id.susCheckBox);
        mLitCheckBox = findViewById(R.id.litCheckBox);
        mSeekBar = findViewById(R.id.seekBar);
        //设置SeekBar的初始值为20
        mSeekBar.setProgress(20);
        mAgeTextView = findViewById(R.id.seekBar_ageTextView);
        //设置SeekBar控件左边的TextView显示的数值与SeekBar当前数值保持一致
        mAgeTextView.setText(String.valueOf(mSeekBar.getProgress()));
        mQueryButton = findViewById(R.id.queryBtn);
        mNextButton = findViewById(R.id.nextBtn);
        mBookImageView = findViewById(R.id.bookImageView);
        mBookNumTextView = findViewById(R.id.bookNumTextView);
        mBookName = findViewById(R.id.bookNameTextView);
        mBookKind = findViewById(R.id.bookKindTextView);
        mBookAge = findViewById(R.id.bookAgeTextView);
        mReturnTime = findViewById(R.id.returnTime);
    }

这里有个小技巧,在完成声明后选择该行按Ctrl+Alt+F,可以将声明操作提取成私有全局变量

	private EditText mNameEditText;
    private RadioGroup mSexRadioGroup;
    private CheckBox mHisCheckBox;
    private CheckBox mSusCheckBox;
    private CheckBox mLitCheckBox;
    private SeekBar mSeekBar;
    private Button mQueryButton;
    private Button mNextButton;
    private ImageView mBookImageView;
    private List<Book> mBooks;
    private Person mPerson;
    private List<Book> mBookResult;
    private boolean mIsHistory;
    private boolean mIsSuspense;
    private boolean mIsLiterature;
    private int mAge;
    private int mCurrentIndex;
    private TextView mAgeTextView;
    private TextView mBookNumTextView;
    private TextView mBookName;
    private TextView mBookAge;
    private TextView mBookKind;
    private EditText mLendEditText;
    private TextView mReturnTime;
    private Date lend = null;
    private Date borrow = null;

初始化数据initData()

工程不包含数据库方面的技术,这里通过initData方法初始化所有书本对象的信息,并且把它加入到mBooks集合中
mBookResult符合条件的书本集合
borrow还书时间,这里把时间直接写死了,也可以通过其它方法来获取当前系统的时间

    //初始化数据
    private void initData() {
        //初始化书本集合
        mBooks = new ArrayList<Book>();
        mBooks.add(new Book("人生感悟", "心灵鸡汤", 43, R.mipmap.aa, false, false, true));
        mBooks.add(new Book("边城", "文学", 30, R.mipmap.bb, false, false, true));
        mBooks.add(new Book("sapir", "传记", 28, R.mipmap.cc, true, false, true));
        mBooks.add(new Book("光辉岁月", "历史", 50, R.mipmap.dd, true, false, false));
        mBooks.add(new Book("宋词三百首", "诗文", 88, R.mipmap.ee, false, false, true));
        mBooks.add(new Book("中国古代文学", "教学纲要", 42, R.mipmap.ff, false, false, true));
        mBooks.add(new Book("无花果", "诗文", 35, R.mipmap.gg, false, false, true));
        mBooks.add(new Book("古镇记忆", "悬疑", 22, R.mipmap.hh, true, true, false));

        //始化用户对象
        mPerson = new Person();

        //初始化书本查找集合
        mBookResult = new ArrayList<Book>();

        //初始化还书时间
        try {
            borrow = new SimpleDateFormat("yyyy-MM-dd").parse("2016-06-30");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

添加监听器setListeners()

这一块是整个Demo的核心代码,大部分控件的响应事件都封装在这里

    //为控件添加监听器
    private void setListeners() {

mNameEditText监听器

将用户输入的姓名字符串传给mPerson对象的setName方法修改mPersonname属性

//nameEditText监听器
        mNameEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (mPerson != null)
                    mPerson.setName(s.toString());
            }
        });

传参之前先判断一下是否为空避免崩溃

mLendEditText监听器

将用户输入的时间字符串传给mPerson对象的setLendTime方法修改mPersonlendTime属性,并将lendTime赋值给this.lend

        //lendEditText监听器
        mLendEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (mPerson != null) {
                    try {
                        mPerson.setLendTime(s.toString());
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                lend = mPerson.getLendTime();
            }
        });

传参时同样要判断对象是否为空

mSexRadioGroup监听器

性别选择的RadioButton放在一个RadioGroup里面,通过监听用户的选择给mPerson.sex进行赋值

//RadioGroup监听器
        mSexRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.male:
                        mPerson.setSex(getString(R.string.male));
                        break;
                    case R.id.female:
                        mPerson.setSex(getString(R.string.female));
                        break;
                }
            }
        });

三个CheckBox的监听器

存储用户的阅读喜好

        //hisCheckBox监听器
        mHisCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mIsHistory = isChecked;
            }
        });
        //susCheckBox监听器
        mSusCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mIsSuspense = isChecked;
            }
        });
        //litCheckBox监听器
        mLitCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mIsLiterature = isChecked;
            }
        });

SeekBar监听器

这里只需获取用户滑动结果,并通过Toast来显示结果
mAge用户选择的年龄int类型
mAgeTextView是位于SeekBar左边的TextView控件,内容与当前选择的年龄一致

        //seekBar监听器
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mAge = seekBar.getProgress();
                mPerson.setAge(mAge);
                //SeekBar左边的TextView更新为当前年龄
                mAgeTextView.setText(String.valueOf(mSeekBar.getProgress()));
                Toast.makeText(MainActivity.this, "年龄:" + mAge, Toast.LENGTH_SHORT).show();
            }
        });

mQueryButton监听器

        //查找按钮监听器
        mQueryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //格式化显示输入的借书时间
                mLendEditText.setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(lend));
                //每次查找前初始化图片及文字信息
                mBookImageView.setImageResource(R.mipmap.f);
                mBookName.setText(R.string.bookname);
                mBookKind.setText(R.string.kind);
                mBookAge.setText(R.string.age);
                mBookNumTextView.setText("");

                if (mPerson.getName() == null)
                    Toast.makeText(MainActivity.this, "姓名不能为空!", Toast.LENGTH_SHORT).show();
                else if (mPerson.getLendTime() == null)
                    Toast.makeText(MainActivity.this, "借书日期不能为空!", Toast.LENGTH_SHORT).show();
                else if (mPerson.getSex() == null)
                    Toast.makeText(MainActivity.this, "请选择性别!", Toast.LENGTH_SHORT).show();
                else if (compareDate()) {//判断借出时间是否大于归还时间
                    Toast.makeText(MainActivity.this, "借书时间晚于还书时间,程序退出!", Toast.LENGTH_SHORT).show();
                    finish();
                } else
                    searchBook();
            }
        });

mNextButton监听器

        //下一个按钮监听器
        mNextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrentIndex++;
                if (mCurrentIndex < mBookResult.size()) {
                    mBookImageView.setImageResource(mBookResult.get(mCurrentIndex).getPic());
                    Toast.makeText(MainActivity.this, "显示:Person[per_name=" + mPerson.getName()
                                    + ",sex=" + mPerson.getSex() + ",age=" + mPerson.getAge()
                                    + ",time=" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(lend) + "]"
                            , Toast.LENGTH_SHORT).show();
                    //ImageView右边显示书籍信息
                    mBookName.setText(mBookResult.get(mCurrentIndex).getName());
                    mBookAge.setText(String.valueOf(mBookResult.get(mCurrentIndex).getAge()));
                    mBookKind.setText(mBookResult.get(mCurrentIndex).getKind());
                    //按钮右边的TextView显示剩余数量
                    mBookNumTextView.setText("符合条件的书还剩" + (mBookResult.size() - mCurrentIndex - 1) + "本");
                } else {
                    Toast.makeText(MainActivity.this, "没有啦!", Toast.LENGTH_SHORT).show();
                }
            }
        });

查找书籍方法主体

    //查找书籍
    private void searchBook() {
        //如果为空,先初始化书籍结果对象
        if (mBookResult == null)
            mBookResult = new ArrayList<Book>();
        //清空结果列表
        mBookResult.clear();
        mCurrentIndex = 0;

        //遍历所有书籍
        for (int index = 0; index < mBooks.size(); index++) {
            Book book = mBooks.get(index);
            //适用年龄要大于设定年龄
            //符合爱好的选择
            if (book != null) {
                if (book.getAge() >= mAge
                        && ((book.isHis() == true) && (book.isHis() == mIsHistory)
                        || (book.isLit() == true) && (book.isLit() == mIsLiterature)
                        || (book.isSus() == true) && (book.isSus() == mIsSuspense))) {
                    mBookResult.add(book);
                }
            }
        }

        if (mCurrentIndex < mBookResult.size()) {
            //先显示第一张图片
            mBookImageView.setImageResource(mBookResult.get(mCurrentIndex).getPic());
            //ImageView右边显示书籍信息
            mBookName.setText(mBookResult.get(mCurrentIndex).getName());
            mBookAge.setText(String.valueOf(mBookResult.get(mCurrentIndex).getAge()));
            mBookKind.setText(mBookResult.get(mCurrentIndex).getKind());
            //按钮右边的TextView显示剩余数量
            mBookNumTextView.setText("符合条件的书还剩" + (mBookResult.size() - 1) + "本");
        }
    }

日期比较方法主体

    //日期比较
    private boolean compareDate() {
        //若借书时间晚于还书时间,返回true
        if (lend.compareTo(borrow) == 1)
            return true;
        else
            return false;
    }

IDE:Android Studio 4.0

本文地址:https://blog.csdn.net/lckgr/article/details/107111464