安卓开发基础期末考试知识点总结

安卓开发基础期末考试知识点总结

1. 布局

- 线性布局

//线性布局以水平或垂直方式来显示界面中的控件
//orientation属性设置垂直或水平
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    >
</LinearLayout>

- 表格布局

//通过表格来管理内部组件位置
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:stretchColumns="0,3"  //相当于设置表格四列
    android:gravity="center_vertical"   //表格整体居中
    android:background="#bf66ff"      //设置背景颜色
    >
	//添加若干行
    <TableRow>
		//添加若干组件,span设置是否跨列
        <TextView android:layout_span="4" />
    </TableRow>
</TableLayout>

- 约束布局

一种可视化方式编写方式,直接拖动组件即可

2. 基本组件

- 单选按钮

//单选按钮的页面样式
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:background="#bf66ff"
    >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="您的性别是:"/>
    <RadioGroup
        android:id="@+id/sex"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <RadioButton
            android:id="@+id/man"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="男"
            android:checked="true"/> //设置默认选中 男
        <RadioButton
            android:id="@+id/woman"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="女"/>
    </RadioGroup>
</LinearLayout>
//单选按钮的事件监听
public void onClick(View view){
        RadioGroup radioGroup = findViewById(R.id.sex);
        for(int i=0;i<radioGroup.getChildCount();i++){
            RadioButton radioButton = (RadioButton) radioGroup.getChildAt(i);
            if(radioButton.isChecked()){
                Toast.makeText(MainActivity.this,"您点击了"+radioButton.getText(),Toast.LENGTH_SHORT).show();
                break;//因为是单选,所以可以直接退出循环
            }

        }

    }

- 多选按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:background="#bf66ff"
    >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="您的爱好有:"/>
    <CheckBox
        android:id="@+id/love1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="篮球"/>
    <CheckBox
        android:id="@+id/love2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="足球"/>
    <CheckBox
        android:id="@+id/love3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="羽毛球"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="提交"
        android:onClick="onClick"/>
</LinearLayout>
//多选按钮监听
public void onClick(View view){
        CheckBox checkBox1 = findViewById(R.id.love1);
        CheckBox checkBox2 = findViewById(R.id.love2);
        CheckBox checkBox3 = findViewById(R.id.love3);
        String str = "您的爱好有:";
        if(checkBox1.isChecked()) str+=checkBox1.getText()+" ";
        if(checkBox2.isChecked()) str+=checkBox2.getText()+" ";
        if(checkBox3.isChecked()) str+=checkBox3.getText()+" ";
        Toast.makeText(MainActivity.this,str,Toast.LENGTH_SHORT).show();
    }

- ImageView

用于图像放置

- ImageSwitcher

图像切换并可以产生动画效果

- 实现一个图片浏览器

//布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/images"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@mipmap/zhifubao"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="95dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
//功能实现
package com.example.tupianliulanqi;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {
    int count =-1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final int[] images = new int[]{R.mipmap.zhifubao,R.mipmap.weixin,R.mipmap.mmm};
        final ImageView imageView = findViewById(R.id.images);

        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(count>=images.length-1) count=-1;
                imageView.setImageResource(images[++count]);
            }
        });
    }
}

- SeekBar

拖动条,用户操作控制

- RatingBar

评分条,一般用于对产品的评价或服务满意度评价,用户操作

- 用SeekBar(拖动条)和RatingBar(评分条)改变图片的透明度(要求同步)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="0dp"
        android:layout_height="280dp"
        android:layout_marginStart="31dp"
        android:layout_marginLeft="31dp"
        android:layout_marginEnd="31dp"
        android:layout_marginRight="31dp"
        android:layout_marginBottom="40dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintBottom_toTopOf="@+id/seekBar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="226dp"
        android:max="255"
        android:progress="255"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <RatingBar
        android:id="@+id/ratingBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="31dp"
        android:numStars="5"
        android:rating="5"
        android:stepSize="0.5"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/seekBar" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginLeft="20dp"
        android:text="当前图片透明度为:"
        app:layout_constraintBaseline_toBaselineOf="@+id/alpha"
        app:layout_constraintStart_toStartOf="@+id/ratingBar" />

    <TextView
        android:id="@+id/alpha"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="34dp"
        android:text="透明度"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toBottomOf="@+id/ratingBar" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.tupiantoumingdu;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final ImageView imageView = findViewById(R.id.image);
        final SeekBar seekBar = findViewById(R.id.seekBar);
        final RatingBar ratingBar = findViewById(R.id.ratingBar);
        final TextView textView = findViewById(R.id.alpha);

        //拖动条监听方法setOnSeekBarChangeListener
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                imageView.setAlpha(i);  //透明度的最大值为255,所以直接用i
                ratingBar.setRating(i/51); //只有五颗星,所以除以51
                textView.setText(i+""); //这里的i必须为字符串类型
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
            @Override
            public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
                imageView.setAlpha((int)v*51);
                seekBar.setProgress((int)v*51);
                textView.setText(v*51+"");
            }
        });
    }
}

3. 易考题

- ListView

定义一个ListView,用SimpleAdapter为其添加内容,要求每个表项显示一本书的封面图像,书名,内容简介;为其添加单击事件监听,在单击时显示书的作者信息
//layout.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:orientation="vertical">
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </ListView>
</LinearLayout>

//main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/img"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:paddingLeft="10dp"
        />
    <TextView
        android:id="@+id/textView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:textAlignment="center"
        android:gravity="center"
        android:text="简介"
        android:layout_marginLeft="20dp"
        />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:textAlignment="center"
        android:gravity="center"
        android:text="介绍"
        android:layout_marginLeft="20dp"
        />

</LinearLayout>
//MainActivity.java
package com.example.listview;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //注意,这里一定要改为listview的布局
        super.setContentView(R.layout.layout);

        ListView listView = findViewById(R.id.listView);
        final String[] writer = new String[]{"马化腾","马云","曾强"};
        final String[] info = new String[]{"微信,移动社交软件","支付宝,移动支付,方便快捷","帅气大方绅士高尚"};
        final int[] imgs = new int[]{R.mipmap.weixin,R.mipmap.zhifubao,R.mipmap.mmm};

        List<Map<String,Object>> listItem = new ArrayList<>();
        for(int i=0;i<writer.length;i++){
            Map<String,Object> map = new HashMap<>();
            map.put("img",imgs[i]);
            map.put("writer",writer[i]);
            map.put("info",info[i]);
            listItem.add(map);
        }

        SimpleAdapter simpleAdapter = new SimpleAdapter(this,listItem,R.layout.activity_main,
                new String[]{"img","writer","info"},new int[]{R.id.img,R.id.textView,R.id.textView1});
        listView.setAdapter(simpleAdapter);

        //listview项目监听
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this,writer[i],Toast.LENGTH_SHORT).show();
            }
        });
    }
}

- 通知

package com.example.tongzhi;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.send);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //创建一个notification对象
                Notification.Builder notification = new Notification.Builder(MainActivity.this);
                //打开通知,通知自动消失
                notification.setAutoCancel(true);
                //设置消息图标
                notification.setSmallIcon(R.mipmap.ic_launcher);
                notification.setContentTitle("通知标题");
                notification.setContentText("通知提示文本");
                //设置提示方式
                notification.setDefaults(Notification.DEFAULT_SOUND);
                //设置发送时间
                notification.setWhen(System.currentTimeMillis());
                //创建启动activity的Intent对象
                Intent intent = new Intent(MainActivity.this, Message.class);
                PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,0,intent,0);
                //设置通知栏点击跳转
                notification.setContentIntent(pendingIntent);
                //获取通知管理器
                NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
                Toast.makeText(MainActivity.this,"test",Toast.LENGTH_SHORT).show();
                notificationManager.notify(0x11,notification.build());
            }
        });
    }
}

- 对话框

package com.example.duihuakuang;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
                alertDialog.setIcon(R.mipmap.ic_launcher);
                alertDialog.setTitle("对话框标题");
                alertDialog.setMessage("对话框的内容");
                alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Toast.makeText(MainActivity.this,"取消",Toast.LENGTH_SHORT).show();
                    }
                });
                alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Toast.makeText(MainActivity.this,"确定",Toast.LENGTH_SHORT).show();
                    }
                });
                alertDialog.show();
            }
        });
    }
}

- 多Activity,并用Bundle传递数据

//main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/str1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="56dp"
        android:hint="str1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="提交"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/str1" />

</androidx.constraintlayout.widget.ConstraintLayout>

//main2.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main2Activity">

    <TextView
        android:id="@+id/result"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="返回结果"/>

    <Button
        android:id="@+id/back"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="64dp"
        android:text="返回"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
//main.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String str = ((EditText)findViewById(R.id.str1)).getText().toString();
                Intent intent = new Intent(MainActivity.this,Main2Activity.class);
                Bundle bundle = new Bundle();
                bundle.putCharSequence("str",str);
                intent.putExtras(bundle);
                startActivity(intent);
            }
        });
    }
}

//main2.java
public class Main2Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        TextView textView = findViewById(R.id.result);
        String str = bundle.getString("str");
        textView.setText(str);
        Button button = findViewById(R.id.back);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }
}

- 菜单

添加菜单,并为菜单添加单击事件,在选择菜单项后改变背景色
//在res目录下创建目录menu,并编写一个menu.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/red" android:title="红色"/>
    <item android:id="@+id/green" android:title="绿色"/>
</menu>

//activity
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu1,menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        TextView textView = findViewById(R.id.color);
        switch (item.getItemId()){
            case R.id.red:
                textView.setText("红色");
                textView.setBackgroundColor(Color.parseColor("#ff0000"));
                break;
            case R.id.green:
                textView.setText("绿色");
                textView.setBackgroundColor(Color.parseColor("#00ff00"));
                break;
        }
        return super.onOptionsItemSelected(item);
    }
}

- Fragment(重点)

1. 静态Fragment设置标题和内容

  1. 创建两个fragment,设置布局文件
//fragment_title.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:id="@+id/TitleFragment"
    tools:context=".titleFragment"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/logo"
        android:layout_width="50dp"
        android:layout_height="30dp"
        android:layout_centerVertical="true"
        android:paddingLeft="10dp"
        android:scaleType="centerCrop"
        android:src="@mipmap/ic_launcher"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="标题"
        android:textSize="27sp"
        android:textColor="#ff00ff"/>

</RelativeLayout>

//fragment_content.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".contentFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="内容"
        android:gravity="center"
        android:textSize="30sp"
        android:textColor="#ffff00"/>

</LinearLayout>
  1. 初始化Fragment,需要重写onCreateView()方法
//titleFragment.java
@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_title, null);
        RelativeLayout layout = view.findViewById(R.id.TitleFragment);
        layout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getActivity(),"您单击呢标题",Toast.LENGTH_SHORT).show();
            }
        });
        return  view;
    }

//contentFragent.java
@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_content, null);
    }

注意:如果最终运行结果闪退,则需要注释掉如下代码:
 /* @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }*/
  1. 最后,在主布局文件中引入各个fragment
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
    android:id="@+id/fragment_title"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:name="com.example.fragment.titleFragment"/>

    <fragment
        android:id="@+id/fragment_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.example.fragment.contentFragment"/>

</RelativeLayout>
注意:不要忘了修改配置文件,去除程序默认的标题显示
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar

2. 动态Fragment

实现模拟底部导航切换界面
1. 编写两个页面的内容部分
//这里用上面的fagment_title.xml来代替第一个页面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/TitleFragment"
    tools:context=".titleFragment"
    android:orientation="horizontal">
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:text="这是主页"
        android:textSize="27sp"
        android:textColor="#ff00ff"/>

</RelativeLayout>

//第二个页面内容fragment_content.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/ContentFragment"
    tools:context=".contentFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="第二页"
        android:layout_gravity="center"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:textSize="30sp"
        android:textColor="#ffff00"/>

</RelativeLayout>

2. 编写主活动代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private FragmentManager manager;
    private FragmentTransaction transaction;
    private RadioButton radioButton1;
    private RadioButton radioButton2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        manager = getSupportFragmentManager();
        transaction = manager.beginTransaction();
        transaction.add(R.id.id_content,new titleFragment());
        transaction.commit();
        initView();
    }
    private void initView(){
        radioButton1 = findViewById(R.id.bar1);
        radioButton2 = findViewById(R.id.bar2);
        radioButton1.setOnClickListener(this);
        radioButton2.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        transaction = manager.beginTransaction();
        switch (view.getId()){
            case R.id.bar1:
                transaction.replace(R.id.id_content,new titleFragment());
                break;
            case R.id.bar2:
                transaction.replace(R.id.id_content,new contentFragment());
                break;
        }
        transaction.commit();
    }
}

3. 用fragment分两步实现登录功能,要求能够回退,解决重屏问题

  1. 解决重屏
<activity android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
  1. 编写2个fragment布局代码和主布局代码
//main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

//login1.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Login1Fragment"
    >

    <TableLayout
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stretchColumns="0,3">
        <TableRow>
            <TextView />
            <TextView
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="用户名"/>
            <EditText
                android:id="@+id/username"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hint="请输入用户名"/>
            <TextView />
        </TableRow>
        <TableRow>
            <TextView />
            <Button
                android:id="@+id/username_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="下一步"
                android:layout_span="2" />
            <TextView />
        </TableRow>
    </TableLayout>

</FrameLayout>

//login2.xml同上

  1. 编写fragment代码
//首先,两个fragment都要实现View.OnClickListener,并重写onClick()方法
public class Login1Fragment extends Fragment implements View.OnClickListener

//Login1Fragment.java
private String username;
    public String getUsername() {
        return username;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_login1, container, false);
        Button btn = view.findViewById(R.id.username_btn);
        final EditText editText = view.findViewById(R.id.username);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                username = editText.getText().toString();
                if(getActivity()instanceof OnFragmentInteractionListener){
                    ((OnFragmentInteractionListener) getActivity()).onBtnNextClick();
                }
            }
        });
        return view;
    }

    @Override
    public void onClick(View view) {

    }

    public interface OnFragmentInteractionListener{
        void onBtnNextClick();
    }

//Login2Fragment.java
private String password;

    public String getPassword() {
        return password;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_login2, container, false);
        Button btn = view.findViewById(R.id.password_btn);
        final EditText editText = view.findViewById(R.id.password);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                password = editText.getText().toString();
                if(login2FragmentListener!=null){
                    login2FragmentListener.btnNext2Click();
                }
            }
        });
        return view;
    }

    public interface Login2FragmentListener{
        void btnNext2Click();
    }
    private Login2FragmentListener login2FragmentListener;

    public void setLogin2FragmentListener(Login2FragmentListener login2FragmentListener) {
        this.login2FragmentListener = login2FragmentListener;
    }

    @Override
    public void onClick(View view) {

    }
  1. 主活动方法
//需要先实现两个fragment的接口
public class MainActivity extends AppCompatActivity implements Login1Fragment.OnFragmentInteractionListener,Login2Fragment.Login2FragmentListener{

    private Login1Fragment login1Fragment;
    private Login2Fragment login2Fragment;
    private String username;
    private String password;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        login1Fragment =new Login1Fragment();
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.add(R.id.content,login1Fragment);
        transaction.commit();
    }

    @Override
    public void onBtnNextClick() {
        username = login1Fragment.getUsername();
        login2Fragment = new Login2Fragment();
        login2Fragment.setLogin2FragmentListener(this);
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.hide(login1Fragment);
        transaction.add(R.id.content,login2Fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    @Override
    public void btnNext2Click() {
        password = login2Fragment.getPassword();
        Toast.makeText(getApplication(),"用户名:"+username+",密码:"+password,Toast.LENGTH_SHORT).show();
    }
}

- 数据库管理

使用数据库完成对用户的增删改查
1. 实体类
package com.example.shujuku;

public class User {
    private String username;
    private String password;
    private String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

2. 数据库和表的创建管理器
//UserDbHelper.java
package com.example.shujuku;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class UserDbHelper extends SQLiteOpenHelper {

    private final static int DB_VERSION = 1;
    private final static String DB_NAME = "user.db";
    public final static String TABLE_NAME = "user";


    public UserDbHelper(Context context){
        super(context,DB_NAME,null,DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String sql = "create table if not exists "+TABLE_NAME+"(username text primary key,password text,address text)";
        sqLiteDatabase.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        String sql = "drop table if exists "+TABLE_NAME;
        sqLiteDatabase.execSQL(sql);
        onCreate(sqLiteDatabase);
    }
}

3. 数据库操作类UserDao
//UserDao.java
package com.example.shujuku;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.ArrayList;
import java.util.List;

public class UserDao {
    private UserDbHelper userDbHelper;
    private Context context;
    private SQLiteDatabase db;

    public UserDao(Context context){
        this.context = context;
        userDbHelper = new UserDbHelper(context);
    }

    /**
     * 插入用户
     * @param user
     */
    public void insert(User user){
        db = userDbHelper.getWritableDatabase();
        db.beginTransaction();
        ContentValues contentValues = new ContentValues();
        contentValues.put("username",user.getUsername());
        contentValues.put("password",user.getPassword());
        contentValues.put("address",user.getAddress());
        db.insertOrThrow(userDbHelper.TABLE_NAME,null,contentValues);
        db.setTransactionSuccessful();
        db.endTransaction();
    }

    /**
     * 查找所有得用户
     * @return
     */
    public List<User> findAll(){
        ArrayList<User> users = new ArrayList<>();
        db = userDbHelper.getReadableDatabase();
        Cursor cursor = db.query(userDbHelper.TABLE_NAME,
                null,null,null,null,null,null);
        cursor.moveToFirst();
        while(!cursor.isAfterLast()){
            User user = new User();
            String username = cursor.getString(0);
            String password = cursor.getString(1);
            String address = cursor.getString(2);
            user.setUsername(username);
            user.setPassword(password);
            user.setAddress(address);
            users.add(user);
            cursor.moveToNext();
        }
        return users;
    }

    /**
     * 根据用户名删除用户
     * @param username
     */
    public void deleteStudentByUserName(String username){
        db = userDbHelper.getWritableDatabase();
        db.beginTransaction();
        String sql = "delete from "+UserDbHelper.TABLE_NAME+" where username ="+"'"+username+"'";
        db.execSQL(sql);
        db.setTransactionSuccessful();
        db.endTransaction();
    }


    /**
     * 根据用户名修改用户信息
     * @param user
     * @param username
     */
    public void update(User user ,String username){
        db = userDbHelper.getWritableDatabase();
        db.beginTransaction();
        ContentValues contentValues = new ContentValues();
        contentValues.put("username",user.getUsername());
        contentValues.put("password",user.getUsername());
        contentValues.put("address",user.getAddress());
        db.update(UserDbHelper.TABLE_NAME,contentValues,"username='"+username+"'",null);
        db.setTransactionSuccessful();
        db.endTransaction();
    }
}

4. 主方法类(实现各个功能页面的跳转)
//main.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button add_user = findViewById(R.id.add_user);
        add_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,AddUserActivity.class);
                startActivity(intent);
            }
        });

        Button find_user = findViewById(R.id.find_user);
        find_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,FindUserActivity.class);
                startActivity(intent);
            }
        });

        Button delete_user = findViewById(R.id.delete_user);
        delete_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,DeleteUserActivity.class);
                startActivity(intent);
            }
        });

        Button update_user = findViewById(R.id.update_user);
        update_user.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,UpdateUserActivity.class);
                startActivity(intent);
            }
        });
    }
}
5. 4个功能方法调用userdao实现增删改查
//增加用户
userDao = new UserDao(this);
        Button add_btn = findViewById(R.id.add_btn);
        add_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditText editText1 = findViewById(R.id.username);
                EditText editText2 = findViewById(R.id.password);
                EditText editText3 = findViewById(R.id.address);
                String username = editText1.getText().toString();
                String password = editText2.getText().toString();
                String address = editText3.getText().toString();
                User user = new User();
                user.setUsername(username);
                user.setPassword(password);
                user.setAddress(address);
                userDao.insert(user);
                TextView textView = findViewById(R.id.result);
                textView.setText("插入成功");
            }
        });

//删除用户
Button delete_btn = findViewById(R.id.delete_btn);
        delete_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EditText editText = findViewById(R.id.delete_username);
                String username = editText.getText().toString();
                userDao = new UserDao(DeleteUserActivity.this);
                userDao.deleteStudentByUserName(username);
                Toast.makeText(getApplication(),"删除成功!",Toast.LENGTH_SHORT).show();
            }
        });

//修改用户
Button update_btn = findViewById(R.id.update_btn);
        update_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                userDao = new UserDao(UpdateUserActivity.this);
                EditText editText = findViewById(R.id.prev_username);
                EditText editText1 = findViewById(R.id.update_username);
                EditText editText2 = findViewById(R.id.update_password);
                EditText editText3 = findViewById(R.id.update_address);
                String username = editText.getText().toString();
                String update_username = editText1.getText().toString();
                String update_password = editText2.getText().toString();
                String update_address = editText3.getText().toString();
                User user = new User();
                user.setUsername(update_username);
                user.setPassword(update_password);
                user.setAddress(update_address);
                userDao.update(user,username);
                Toast.makeText(getApplication(),"修改成功",Toast.LENGTH_SHORT).show();
            }
        });

//查看所有用户
Button find_btn = findViewById(R.id.find_btn);
        find_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TableLayout tableLayout = findViewById(R.id.tableLayout);
                TableRow tableRow = new TableRow(FindUserActivity.this);
                TextView textView = new TextView(FindUserActivity.this);
                textView.setText("用户名");
                tableRow.addView(textView);
                TextView textView1 = new TextView(FindUserActivity.this);
                textView1.setText("密码");
                tableRow.addView(textView1);
                TextView textView2 = new TextView(FindUserActivity.this);
                textView2.setText("地址");
                tableRow.addView(textView2);
                tableLayout.addView(tableRow);
                userDao = new UserDao(FindUserActivity.this);
                List<User> users = userDao.findAll();
                for(int i=0;i<users.size();i++){
                    TableRow tableRow1 = new TableRow(FindUserActivity.this);
                    TextView text1 = new TextView(FindUserActivity.this);
                    text1.setText(users.get(i).getUsername());
                    tableRow1.addView(text1);
                    TextView text2 = new TextView(FindUserActivity.this);
                    text2.setText(users.get(i).getPassword());
                    tableRow1.addView(text2);
                    TextView text3 = new TextView(FindUserActivity.this);
                    text3.setText(users.get(i).getAddress());
                    tableRow1.addView(text3);
                    tableLayout.addView(tableRow1);
                }
            }
        });
6. 页面布局代码,略

- 服务

用服务完成两个随机数的加法操作
//main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:gravity="center">

    <Button
        android:id="@+id/open"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="绑定服务"/>
    <Button
        android:id="@+id/cannel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="取消绑定"/>
    <Button
        android:id="@+id/run"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="运行服务"/>

    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="结果"/>

</LinearLayout>
//MyService.java
package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;

public class MyService extends Service {

    private IBinder iBinder = new localBinder();

    public class localBinder extends Binder{
        MyService getService(){
            return MyService.this;
        }
    }
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(this,"绑定成功",Toast.LENGTH_SHORT).show();
        return iBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Toast.makeText(this,"取消绑定成功",Toast.LENGTH_SHORT).show();
        return super.onUnbind(intent);
    }

    //生成随机数
    public double getRandomNumber(){
        double x = Math.random()*100;
        return x;
    }

    public double jisuan(double x,double y){
        return x+y;
    }
}

//mian.java
public class MainActivity extends AppCompatActivity {


    private MyService myService;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            myService = ((MyService.localBinder) iBinder).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            myService = null;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn_open  = findViewById(R.id.open);
        btn_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(myService==null){
                    Intent intent = new Intent(getApplication(),MyService.class);
                    bindService(intent,conn,BIND_AUTO_CREATE);
                }
            }
        });

        Button btn_cannel = findViewById(R.id.cannel);
        btn_cannel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                unbindService(conn);
            }
        });

        Button run = findViewById(R.id.run);
        run.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TextView result = findViewById(R.id.result);
                double sum = myService.jisuan(myService.getRandomNumber(),myService.getRandomNumber());
                result.setText(sum+"");
            }
        });
    }
}

- 广播

使用广播监听网络状态
页面布局略
//MyReceiver.java
package com.example.guangbo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if(isNetwork(context)){
            Toast.makeText(context,"网络连接",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(context,"断开连接",Toast.LENGTH_SHORT).show();
        }
    }

    public interface NetWorkInfoInterface{}
    private NetWorkInfoInterface netWorkInfoInterface;
    public void getNetWorkInfo(MainActivity netWorkInfoInterface){
        this.netWorkInfoInterface = netWorkInfoInterface;
    }

    public boolean isNetwork(Context context){
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
        Network[] networks = connectivityManager.getAllNetworks();
        NetworkInfo networkInfo;
        for(Network network:networks){
            networkInfo = connectivityManager.getNetworkInfo(network);
            if((networkInfo.getState().equals(NetworkInfo.State.CONNECTED))){
                return true;
            }
        }
        return false;
    }
}

package com.example.guangbo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.IntentFilter;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity implements MyReceiver.NetWorkInfoInterface{

    MyReceiver myReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        myReceiver = new MyReceiver();
        registerReceiver(myReceiver,intentFilter);
        myReceiver.getNetWorkInfo(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(myReceiver);
    }
}

注:配置文件中需要添加权限和广播的配置信息
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>

        </receiver>

4. 考完了,来总结一下

考了四个题:

  1. 图片浏览器ImageView
  2. 布局(想用什么用什么布局)
  3. activity跳转并且传递数据
  4. Fragment跳转传数据

都是做过的题目,但是第四个还是没做完,很多细节的知识也没有把握住,很一般了,跪求成绩不要太低。。。

- 安卓开发基础资料:

链接:https://pan.baidu.com/s/1WjjGhVldbwBNhfs7JxWRtQ 
提取码:jtkq
版权声明:本文为博主原创文章,转载请附上博文链接!
原文地址:https://www.cnblogs.com/zq98/p/15027954.html