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

一、题目:界面设计。

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

二、界面显示

移动终端应用开发上机2常用控件和事件处理_第3张图片
移动终端应用开发上机2常用控件和事件处理_第4张图片

三、创建过程&主角代码

1、工程创建
file->new->new project->Tabbed Activity

移动终端应用开发上机2常用控件和事件处理_第5张图片

2、观察里面的工程内容,会发现里面有几个需要我们注意的东西。
移动终端应用开发上机2常用控件和事件处理_第6张图片
我们知道Tab页面可以分出好几个,而老师或者一些很老的博客里面会告诉我们,若是我们需要n个Tab页面,我们则需要在一个project中新建n个fragmentactivity的Java文件和xml文件。
但是在这个project里面我们只看到了一个fragment.xml文件,而在运行模拟器时却发现有两个Tab。
移动终端应用开发上机2常用控件和事件处理_第7张图片
移动终端应用开发上机2常用控件和事件处理_第8张图片
3、这时返回去看代码,在ui.main文件夹下我们找到了一个名为SectionsPagerAdapter的Java文件。
移动终端应用开发上机2常用控件和事件处理_第9张图片
这个文件很重要,因为其内包含了Tab的标题、Tab的内容等代码,这也恰恰表明,此次制作Tab的主角就是SectionsPagerAdapter.java。
但是在对它“动手”之前,请先在布局文件中新建两个布局文件。在这里,用红框框的第一个文件是我的第一个Tab,第二个文件是第二个Tab。
移动终端应用开发上机2常用控件和事件处理_第10张图片
拿来主义,上课时录了个视频,把老师在PPT上展示的代码直接敲下来用了,所以第一个xml文件用的还是老师上课展示的代码。
第二个xml文件里用的是书上的代码。
因为不是这次的重点,这里就不放了,主要用到的还是布局嵌套,按键用的是RadioButton。

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

其实在一开始的时候我的代码会显示出高亮的一块黄色,像下面这样。
移动终端应用开发上机2常用控件和事件处理_第13张图片
很迷茫,在网上找了也只有一个答案“代码写得不规范导致”,但是怎么改呢?完全没有解决方案,虽然也能够运行,但是看着很难受… …
后来当我因为另一个problem一筹莫展的时候,不小心点到了页面的某个地方,它给我自动添加了一行代码,我的代码终于恢复正常了。
移动终端应用开发上机2常用控件和事件处理_第14张图片
添加了这行代码:

@SuppressLint("ClickableViewAccessibility")

后来去网上找了才知道是什么问题,在文章结尾会附上相关链接。

四、观察MainActivity.java里的代码

移动终端应用开发上机2常用控件和事件处理_第15张图片
在一开始运行模拟器的时候发现页面右下角有一个悬浮窗口,点击其窗口会出现弹窗文字。
移动终端应用开发上机2常用控件和事件处理_第16张图片
其监听器在MainActivity.java文件中,因为只是了解,并没有过多深究,所以只是改了其文本内容。
但是这个文件里的内容很重要,因为其控制了我们整个工程的页面。

五、演示

移动终端应用开发上机2常用控件和事件处理_第17张图片
移动终端应用开发上机2常用控件和事件处理_第18张图片
移动终端应用开发上机2常用控件和事件处理_第19张图片
注:因为是在模拟器上跑的代码,用的是鼠标点击“屏幕”,所以这里的触点压力和触点尺寸分别恒为1.0和0.0。

六、小结

只能说,这次的上机很坎坷,因为在一开始,是想要按部就班地抄书上的代码,然后就好了,但是没想到书上的代码有的函数在AndroidStudio里已经失效了,运行时工程直接闪退,于是开始去网上找方法看看能不能改用别的方法去运行这个工程,但是没想到,这一找,就踏上了Android开发的坎坷之路。
移动终端应用开发上机2常用控件和事件处理_第20张图片
移动终端应用开发上机2常用控件和事件处理_第21张图片

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

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

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

你可能感兴趣的