先从基本的android代码结构开始吧,推荐网页
https://blog.csdn.net/weixin_49770443/article/details/116935303
也有对这几个文件的基本结构功能做了分析,可以去看原文章
Activity活动的生命周期
还有个值得了解的,Activity活动的生命周期,像是onCreate方法是点击APP开始第一个进入的,可以写些初始化的操作。但是控件之类的,在setContentView(R.layout.activity_main);方法之后才能调用,不然组件都没加载就用,会导致闪退,没有相应权限调用方法一样会闪退,别问我为什么知道的。
https://developer.android.google.cn/guide/components/activities/activity-lifecycle
所以首先需要声明好权限,我这就不多说了,我另一篇有讲以蓝牙的为例。
搭建APP界面
了解完基础知识之后,就可以开始搭建APP啦,点击AndroidManifest.xml开始布局自己的界面,我还是习惯用右上角的design界面,直接编辑界面,这才是编辑前端的正确打开方式吗,毕竟我也是新手。
有两个比较使用的布局组件,LinearLayout(线性布局)跟 constraintlayout(约束布局),线性布局可以在竖向或横向的堆叠方式,约束布局可以随意拖拽约束跟四周控件的距离,也十分方便,可以在component Tree里右键组件添加约束条件。
比较重要的控件参数
android:id="@+id/textView" //程序调用的入口名字
android:layout_width="match_parent" //跟随父类的大小
android:layout_height="wrap_content" //自适应大小
android:layout_weight="0.8" //控件大小的占比,
//适合多控件之间分配比例,来适应不同屏幕
我的app界面代码如下,类似聊天窗口,我是用来做蓝牙调试助手的。
<?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"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="80dp" android:lineSpacingExtra="2dp" android:fadeScrollbars="false" android:scrollbars="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" /> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent"> <EditText android:id="@+id/editText" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:autofillHints="" android:hint="@string/editText" android:textColorHint="#757575" /> <Button android:id="@+id/sentButton" android:layout_width="120dp" android:layout_height="match_parent" android:layout_marginBottom="0dp" android:text="@string/sent" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
常用组件控件
常用的组件有Button(按键)、TextView(文本框)、EditText(编辑框)、ListView(列表视图)
控件都需要先声明,再初始化,就可以调用相应控件方法啦。
Button sentButton; TextView textView; EditText editText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sentButton = (Button) findViewById(R.id.sentButton); textView = (TextView) findViewById(R.id.textView); editText = (EditText) findViewById(R.id.editText); //按键监听 sentButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ //按键按下处理代码 } });
在界面代码也看到,我在TextView里加了这两行代码,
android:fadeScrollbars="false" //显示滚动条
android:scrollbars="vertical" //垂直方向滚动
再程序里面加上一句,textView.setMovementMethod(ScrollingMovementMethod.getInstance()); //设置滚动
便能实现TextView的文本过多滚动显示
最后贴上MainActivity.java的代码
package com.example.bt_communication; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.content.pm.PackageManager; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; //先声明,实例化 Button sentButton; TextView textView; EditText editText; //textview实现消息自动滚动 private void refreshScrollPosition(){ int line = textView.getLineCount(); if (line > 33) {//超出屏幕自动滚动显示(33是当前页面显示的最大行数) //textView.getLineHeight(),中文跟字母的高度大小不一致,中文会有位置不对的bug int offset = textView.getLineCount() * textView.getLineHeight(); textView.scrollTo(0, offset - textView.getHeight() ); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //控件初始化,匹配控件ID sentButton = (Button) findViewById(R.id.sentButton); textView = (TextView) findViewById(R.id.textView); editText = (EditText) findViewById(R.id.editText); textView.setMovementMethod(ScrollingMovementMethod.getInstance()); //设置滚动 //确认权限 Permission permission = new Permission(); permission.checkPermissions(this); //按键监听 sentButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ String inputText = editText.getText().toString(); textView.setText(inputText); //直接设置覆盖文本框的内容 Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show(); //弹出文本通知 Log.d(TAG,"inputText:" + inputText + '\n'); //打印debug类型的log textView.append(inputText + '\n'); //将文本添加到文本框加换行 refreshScrollPosition(); } }); } //权限申请声明 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == Permission.RequestCode) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { Log.e("p","拒绝的权限名称:" + permissions[i]); Log.e("p","拒绝的权限结果:" + grantResults[i]); Log.e("p","有权限未授权,可以弹框出来,让客户去手机设置界面授权。。。"); }else { Log.e("p","授权的权限名称:" + permissions[i]); Log.e("p","授权的权限结果:" + grantResults[i]); } } } } }
最后可以用android studio下方的Logcat来调试自己的代码,log.d之类的方法会打印信息在里面
1、选上自己的程序(默认选上还是会跑出一堆系统的打印的)
2、可以选上不同的打印类型,可是还会打印更高级的log信息
3、选择不同的过滤方式,也可以自定义
问题:Attempt to invoke virtual method '.......' on a null object reference
出现空指针的话,确定初始化的步骤是否正确,控件findViewById初始化需要在onCreate函数里,而且而且在setContentView(R.layout.activity_main);之后。
Button sentButton; TextView textView; EditText editText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sentButton = (Button) findViewById(R.id.sentButton); textView = (TextView) findViewById(R.id.textView); editText = (EditText) findViewById(R.id.editText); sentButton.setcgListener(new View.cgListener() { @Override public void cg(View view) { } });
联系客服