android|移动终端应用开发上机2常用控件和事件处理

一、题目:界面设计。 (1)开发一个单页面的APP。
(2)“线性布局”TAB页:显示个人相关信息,需要使用TextView、EditText、Button、CheckBox等控件。(页面内容也可自行设计)
(3)“触摸屏处理”TAB页:在规定区域内实现触摸屏功能。
(4)其他TAB页:可自行设计页面功能。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

二、界面显示 android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

三、创建过程&主角代码 【android|移动终端应用开发上机2常用控件和事件处理】1、工程创建
file->new->new project->Tabbed Activity
android|移动终端应用开发上机2常用控件和事件处理
文章图片

2、观察里面的工程内容,会发现里面有几个需要我们注意的东西。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

我们知道Tab页面可以分出好几个,而老师或者一些很老的博客里面会告诉我们,若是我们需要n个Tab页面,我们则需要在一个project中新建n个fragmentactivity的Java文件和xml文件。
但是在这个project里面我们只看到了一个fragment.xml文件,而在运行模拟器时却发现有两个Tab。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

3、这时返回去看代码,在ui.main文件夹下我们找到了一个名为SectionsPagerAdapter的Java文件。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

这个文件很重要,因为其内包含了Tab的标题、Tab的内容等代码,这也恰恰表明,此次制作Tab的主角就是SectionsPagerAdapter.java。
但是在对它“动手”之前,请先在布局文件中新建两个布局文件。在这里,用红框框的第一个文件是我的第一个Tab,第二个文件是第二个Tab。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

拿来主义,上课时录了个视频,把老师在PPT上展示的代码直接敲下来用了,所以第一个xml文件用的还是老师上课展示的代码。
第二个xml文件里用的是书上的代码。
因为不是这次的重点,这里就不放了,主要用到的还是布局嵌套,按键用的是RadioButton。
4、开始看主角文件里的代码。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

直接用它封装好的工程的好处就是有的地方有注释,还能省许多心。
从上图的注释中,我们可以知道这个名字叫FragmentPagerAdapter的东西(类)可以返回与某个部分/分栏/页对应的片段。
这里的Tab有两个,用了个数组(也许?)来定义它们,我改了改名字。
改名字可以在上面图片的数组里面改,如果会报错的话,也可以在res->values->string.xml修改相应的Tab名字,因为这里Tab的标题名字就是源自于string.xml文件里的,代码参数为:new int[]{R.layout.Tab1,R.layout.Tab2}。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

而这个getItem则是定位用的(如果我没猜错的话),它可以根据Tab不同位置呈现不同的内容。
所以等会需要在这里修改返回内容。
后面还有两段代码不是我们重点要关注的地方,可以暂时不用管(如果不需要自行车的话)。
5、在这里,我们利用getItem去获取我们要显示的页面。把return后返回的内容删掉,用switch去返回我们需要的页面,页面内容在Tab1和Tab2里。

@Override //根据tab不同位置呈现不同的内容 // getItem is called to instantiate the fragment for the given page. // Return a PlaceholderFragment (defined as a static inner class below). public Fragment getItem(int position) {switch (position){case 0: return new Tab1(); case 1: return new Tab2(); } return null; }

然后建立一个静态类页面,其父类是Fragment。
public static class Tab1 extends Fragment { //内容 }

接下来就可以往这个类里放我们要的东西了,在这里写下的代码是直接用于页面上的。
在这里我直接挪用了老师的代码。
public static class Tab1 extends Fragment {public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {super.onCreate(savedInstanceState); View v = inflater.inflate(R.layout.section_pager_adapter, container, false); final RadioButton rb1 = (RadioButton) v.findViewById(R.id.RadioButton1); final RadioButton rb2 = (RadioButton) v.findViewById(R.id.RadioButton2); final EditText ed1 = (EditText) v.findViewById(R.id.entry1); final EditText ed2 = (EditText) v.findViewById(R.id.entry2); final TextView text1 = (TextView) v.findViewById(R.id.label4); Button but1 = (Button) v.findViewById(R.id.get); Button but2 = (Button) v.findViewById(R.id.cancel); final String str3=""; but1.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {String str1 = ed1.getText().toString(); String str2 = ed2.getText().toString(); String str3 = null; if(rb1.isChecked()) str3=rb1.getText().toString(); if(rb2.isChecked()) str3=rb2.getText().toString(); text1.setText("姓名:"+str1+"年龄:"+str2+"是否现在睡觉:"+str3); } }); but2.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {ed1.setText(""); ed2.setText(""); rb1.setChecked(false); rb2.setChecked(false); } }); return v; } }

在这里实例化的两个button是用来作“获取”和“清除”作用的,代码内容和我上一篇上机的博客差不多,在此不做赘述。
重点是这行代码。
View v = inflater.inflate(R.layout.section_pager_adapter, container, false);

然后照着Tab1的样子建立一个Tab2。这里的Tab2页面内容是书上的一个触摸事件(touch event)。
需要用到MotionEvent的包,重写里也要像Tab1一样加上LayoutInflater和ViewGroup容器,还有重写方法… …代码不难,花两分钟多看两眼基本能知道是什么了。
public static class Tab2 extends Fragment{@SuppressLint("ClickableViewAccessibility") @Override public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {super.onCreate(savedInstanceState); TextView labelView = null; View v = inflater.inflate(R.layout.touch_event, container, false); labelView = (TextView) v.findViewById(R.id.event_label); TextView touchView = (TextView)v.findViewById(R.id.touch_area); final TextView historyView = (TextView)v.findViewById(R.id.history_label); TextView finalLabelView = labelView; touchView.setOnTouchListener(new View.OnTouchListener() {@Override public boolean onTouch(View v, MotionEvent event) {int action = event.getAction(); switch (action) {case (MotionEvent.ACTION_DOWN): Display("ACTION_DOWN",event); break; case (MotionEvent.ACTION_UP): int historySize = ProcessHistory(event); historyView.setText("历史数据量:"+historySize); Display("ACTION_UP",event); break; case (MotionEvent.ACTION_MOVE): Display("ACTION_MOVE",event); break; } return true; } private void Display(String eventType, MotionEvent event){int x = (int)event.getX(); int y = (int)event.getY(); float pressure = event.getPressure(); float size = event.getSize(); int RawX = (int)event.getRawX(); int RawY = (int)event.getRawY(); String msg = ""; msg += "事件类型:" + eventType + "\n"; msg += "相对坐标:"+String.valueOf(x)+","+String.valueOf(y)+"\n"; msg += "绝对坐标:"+String.valueOf(RawX)+","+String.valueOf(RawY)+"\n"; msg += "触点压力:"+String.valueOf(pressure)+","; msg += "触点尺寸:"+String.valueOf(size)+"\n"; finalLabelView.setText(msg); } private int ProcessHistory(MotionEvent event) {int historySize = event.getHistorySize(); for (int i = 0; i < historySize; i++) {long time = event.getHistoricalEventTime(i); float pressure = event.getHistoricalPressure(i); float x = event.getHistoricalX(i); float y = event.getHistoricalY(i); float size = event.getHistoricalSize(i); } return historySize; } }); return v; } }

其实在一开始的时候我的代码会显示出高亮的一块黄色,像下面这样。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

很迷茫,在网上找了也只有一个答案“代码写得不规范导致”,但是怎么改呢?完全没有解决方案,虽然也能够运行,但是看着很难受… …
后来当我因为另一个problem一筹莫展的时候,不小心点到了页面的某个地方,它给我自动添加了一行代码,我的代码终于恢复正常了。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

添加了这行代码:
@SuppressLint("ClickableViewAccessibility")

后来去网上找了才知道是什么问题,在文章结尾会附上相关链接。
四、观察MainActivity.java里的代码 android|移动终端应用开发上机2常用控件和事件处理
文章图片

在一开始运行模拟器的时候发现页面右下角有一个悬浮窗口,点击其窗口会出现弹窗文字。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

其监听器在MainActivity.java文件中,因为只是了解,并没有过多深究,所以只是改了其文本内容。
但是这个文件里的内容很重要,因为其控制了我们整个工程的页面。
五、演示 android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

注:因为是在模拟器上跑的代码,用的是鼠标点击“屏幕”,所以这里的触点压力和触点尺寸分别恒为1.0和0.0。
六、小结 只能说,这次的上机很坎坷,因为在一开始,是想要按部就班地抄书上的代码,然后就好了,但是没想到书上的代码有的函数在AndroidStudio里已经失效了,运行时工程直接闪退,于是开始去网上找方法看看能不能改用别的方法去运行这个工程,但是没想到,这一找,就踏上了Android开发的坎坷之路。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

结果跳转到官网的另外一个页面,它叫我用navigation… …我不死心,我就去网上找例程,找之前在图书馆借的书里的随书代码… …
跑了几个很炫酷的例程,但我仍然对Fragment这个东西一无所知。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

android|移动终端应用开发上机2常用控件和事件处理
文章图片

而就在10月5日,也就是三天前,我闲得无聊,新建工程的时候发现在工程样式最下面有一个名为“Tabbed Activity”的样式。
喜出望外,遂新建工程。
毫无进展,因为看不懂代码,怎么没有fragmenta、fragmentb就能够创建出两个页面了?怎么这个MainActivity里面什么东西也没有?
然后又是漫长地寻找代码含义的道路。
终于,我在我的收藏夹里找到一个极具关键性的博客。是的,这篇博客给我接下来的代码提供了关键。
我终于知道Fragment是什么了!原来在Android升级之后,Fragment被改变成了一个类,但是因为不是Activity这样的类,所以我们不能直接使用findViewbyId去寻找我们布局文件里的控件,而需要构造一个LayoutInflater方法去构建一个view,虽然这个老师在上课也讲过,但是当时的我懵懵懂懂,而且第二天就是国庆了,我的心早已经放假了。
android|移动终端应用开发上机2常用控件和事件处理
文章图片

import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter;

而在继承Fragment父类时,要先导入以上类。
然后就开始啃代码,写代码了。
这次的上机2我用了6天的时间终于写完,而这篇博客,我花了两天的时间写完,其中的苦难不言而喻。
七、参考 以下这些链接是我在这次上机内容中参考过的网站或博客。
ActionBar
Navigation Editor
Android架构组件-Navigation的使用(一)
Tabbed Activity的使用(Fragment)
使用 ViewPager2 创建包含标签的滑动视图
Navigation导航图
Android Studio开发学习(十三)——Fragment
android studio有时写着代码,突然某一块代码背景变成土黄色
响应触摸事件
在安卓开发中,我需要将AppCompatActivity 转换fragment,请问该如何更改
Issue id: ClickableViewAccessibility
【Android】inflater的作用
使用TAB和新的工具栏(APPCOMPAT V7-21)
navigation/Menu1Fragment.kt

    推荐阅读