安卓开发基础的学习笔记
Tocst的基础使用
1
Toast.makeText(MainActivity.this,text_show.toString(),Toast.LENGTH_SHORT).show();
如果您的应用以 Android 12(API 级别 31)或更高版本为目标平台,则消息框上限为两行文本,并且必须在文本旁边显示应用图标。请注意,此文本的行长因屏幕尺寸而异,因此最好尽可能缩短文本长度。
所以只能用其他消息提示控件代替,如:AlretDialog1
2
3
4
5
6
7
8// 定义AlertDialog以完全显示
AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
builder.setMessage(text_show);
builder.setCancelable(true);
AlertDialog dialog=builder.create();
// 底部显示
dialog.getWindow().setGravity(Gravity.BOTTOM);
dialog.show();或者这样定义:
AlertDialog(对话框)详解_菜鸟教程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23builder = new AlertDialog.Builder(mContext);
alert = builder.setIcon(R.mipmap.ic_icon_fish)
.setTitle("系统提示:")
.setMessage("这是一个最普通的AlertDialog,\n带有三个按钮,分别是取消,中立和确定")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mContext, "你点击了取消按钮~", Toast.LENGTH_SHORT).show();
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mContext, "你点击了确定按钮~", Toast.LENGTH_SHORT).show();
}
})
.setNeutralButton("中立", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mContext, "你点击了中立按钮~", Toast.LENGTH_SHORT).show();
}
}).create(); //创建AlertDialog对象
alert.show();控件绑定
1
2
3
4
5Button btn = findViewById(R.id.btn_id);
//或者先定义好对象类型再进行控件绑定
private Button btn;
btn = findViewById(R.id.btn_id);监听器的绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23switch_s_hidden.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (switch_s_hidden.isChecked()){
rg_s.setVisibility(View.INVISIBLE);
switch_flag=false;
}
else{
rg_s.setVisibility(View.VISIBLE);
switch_flag=true;
}
}
});
//或者定义一个单独的类(在onCreate()之外),继承对应的监听器,再实例化调用
class chk_lis implements CompoundButton.OnCheckedChangeListener{
@Override
public void onCheckedChanged(CompoundButton cButton,boolean b){
@Todo
}
}
chk_lis chk_lis1=new chk_lis();
chk_l.setOnCheckedChangeListener(chk_lis1);屏幕像素密度:
需要注意的是,要适配不同密度的手机屏幕,dp还远远不够。- px:pixel缩写,意为像素。
- dp(推荐使用):density-independent pixel缩写,有时被缩写为dip,意为密度无关像素。
- sp(推荐对字体使用):scale-independent pixel缩写,意为缩放无关像素。
drawable、drawable-ldpi、mdpi、hdpi、xhdpi
对应默认密度、中等密度、高密度、超高密度等。引用时只需要引用id即可,几个文件夹存入的图片同名且只能是小写不能包含空格。文件夹只是给人来分辨和方便存储,实际调用的时候还是根据图片的密度来调用。因此你甚至能把它们全放进同一个文件夹里,如果可以的话。
ListView组件中含有CheckBox控件时可能会出现一些问题。比如刷动后已选中的选项会贝清除或未被选中的选项贝选中。可以在CheckBox的OnCheckChange监听器中添加一个保存状态的语句,并在后面再重新赋值一次CheckBox的状态。
- ListView动态计算高度&数据更新:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// 定义为函数方便调用
public void listAdapterSet(){
try {
List<Map<String, Object>> mapList = noteUpdate();
if (mapList==null){
int hhh=1/0;
}
// 重新设置adapter以刷新数据
baseAdapter = new MyAdapter(MainActivity.this, mapList);
listViewNote.setAdapter(baseAdapter);
// 动态设置listView高度
ViewGroup.LayoutParams layoutParams=listViewNote.getLayoutParams();
int hS=0;
int itemCount=baseAdapter.getCount();
int qq=0;
while (qq<itemCount){
View view=baseAdapter.getView(qq,null,listViewNote);
view.measure(0,0);
qq++;
hS+=view.getMeasuredHeight();
if (qq==itemCount){
// 似乎少算了一行
hS+=view.getMeasuredHeight();
}
}
hS=hS+itemCount*listViewNote.getDividerHeight();
layoutParams.height=hS;
listViewNote.setLayoutParams(layoutParams);
} catch (Exception e) {
Log.d("TAG", "onCreate: nullMapList");
}
}
- ListView动态计算高度&数据更新:
调试语句:
1
Log.d("TAG", "onCheckedChanged: ");
无法使用switch的原因是模块中的
R
不是final类型,因此只能用if-else
来代替。TabLayout与ViewPage2的绑定:
1
new TabLayoutMediator(tabLayout, viewPager2, true, (tab, position) -> tab.setText(titleList.get(position))).attach();
另外,ViewPage2的触发器继承
FragmentStateAdapter
。因为两者绑定了,所以只有ViewPage2需要触发器。1
ViewPageAdapter viewPageAdapter=new ViewPageAdapter(getActivity(),fragmentList);
fragments
是List<Fragment>
类型,需要在里面加入碎片以在ViewPage2中显示。另外fragment可以加入构造方法以实现单个类的多次使用。BottomNavigationView的使用:
触发器的设置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20bottomNavigationSelectedListener navListener = new bottomNavigationSelectedListener();
bottomNav.setOnItemSelectedListener(navListener);
// 设置默认选中页面
bottomNav.setSelectedItemId(bottomNav.getMenu().getItem(0).getItemId());
class bottomNavigationSelectedListener implements BottomNavigationView.OnItemSelectedListener {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id=item.getItemId();
if (id==R.id.logout){
} else if (id==R.id.scan) {
} else if (id==R.id.imagePage) {
}else {
return false;
}
return true;
}
}ToolBar的使用:
触发器的定义:1
2
3
4
5toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
return false;
}使用中需要注意的是,toolbar需要导入的包是
androidx.appcompat.widget.Toolbar
,而不是android.widget.Toolbar
。
布局文件同理,是androidx.appcompat.widget.Toolbar
而不是Toobar
。广播Broadcast与接收器Receiver:
动态注册广播:1
2
3
4
5
6
7
8
9broadcastReceiver = new BroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction("musicPlay");
filter.addAction("musicPause");
filter.addAction("broadcast");
// 动态注册广播接收者
registerReceiver(broadcastReceiver, filter);自定义广播:
1
2
3
4
5
6
7Intent intent=new Intent("musicPlay");
//传递参数,可要可不要
Bundle bundle=new Bundle();
bundle.putString("title",editTextTitle.getText().toString());
bundle.putString("context",editTextContext.getText().toString());
intent.putExtras(bundle);
sendBroadcast(intent);接收器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class BroadcastReceiver extends android.content.BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "onReceive:dsds ");
// wifi开关
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
Log.d("TAG", "onReceive:WLAN ");
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1111);
switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLED:
Toast.makeText(context, "Wifi_Disable", Toast.LENGTH_LONG).show();
break;
case WifiManager.WIFI_STATE_ENABLING:
Toast.makeText(context, "Wifi_Enable", Toast.LENGTH_LONG).show();
break;
}
}
//音乐播放,关闭音乐为mediaPlayer.stop();
else if (intent.getAction().equals("musicPlay")){
if (mediaPlayer!=null){
mediaPlayer.stop();
mediaPlayer=null;
}
mediaPlayer=MediaPlayer.create(context,R.raw.loop_65);
mediaPlayer.start();
}
}注意在
MainActivity
中重写销毁方法以销毁广播:1
2
3
4
5
6
7@Override
protected void onDestroy() {
super.onDestroy();
if (broadcastReceiver != null) {
unregisterReceiver(broadcastReceiver);
}
}通知:
构造和相关代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34Bundle bundle=intent.getExtras();
String strTitle=bundle.getString("title");
String strContext=bundle.getString("context");
Intent intent1=new Intent(context,MainActivity.class);
// 需要唯一的intent来进行传参,否则将无法传参
// 即需要设置setData值方可传参
intent1.setData(Uri.parse("custom://"+System.currentTimeMillis()));
Bundle bundle1=new Bundle();
bundle1.putString("title",strTitle);
bundle1.putString("context",strContext);
bundle1.putBoolean("isCast",true);
intent1.putExtras(bundle1);
// 设置为0时传入的参数会被覆盖(与这个无关,因为处理的是同样的intent)
// Android12以上PendingIntent需要强制增加FLAG_IMMUTABLE或FLAG_MUTABLE
PendingIntent pi = PendingIntent.getActivity(context, 0 ,intent1, PendingIntent.FLAG_IMMUTABLE);
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//创建 NotificationChannel 对象
NotificationChannel channel = new NotificationChannel("Channel_ID", "chat message",NotificationManager.IMPORTANCE_DEFAULT);
//创建通知渠道
mNotificationManager.createNotificationChannel(channel);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context,"Channel_ID")
.setContentTitle(strTitle)
.setContentText(strContext)
.setWhen(System.currentTimeMillis())
// 设置图标
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_launcher_foreground))
// 设置通知点击跳转
.setContentIntent(pi);
// 点击后消失
// .setAutoCancel(true);
//发送通知( id唯一,可用于更新通知时对应旧通知; 通过mBuilder.build()拿到notification对象 )
mNotificationManager.notify(1,mBuilder.build());关闭通知:
1
mNotificationManager.cabcel(1);
Sqlite的基础使用:
定义相关类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class DBOpenHelper extends SQLiteOpenHelper {
public static final String SQL_TB_NAME="user";
public static final String SQL_TB_Note_NAME="note";
public DBOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// 此处必须是integer而不能是int,否则会出现无法创建的错误,ntext是以unicode存储的文本,大概4k字
sqLiteDatabase.execSQL("create table if not exists "+SQL_TB_NAME+"(accountId integer primary key,password varchar)");
sqLiteDatabase.execSQL("create table if not exists "+SQL_TB_Note_NAME+"(id integer primary key autoincrement,accountId int,title ntext,context ntext)");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
// 刷新数据库,即删除重建
sqLiteDatabase.execSQL("drop table if not exists "+SQL_TB_NAME);
sqLiteDatabase.execSQL("drop table if not exists "+SQL_TB_Note_NAME);
onCreate(sqLiteDatabase);
}
}查询操作:
1
2
3
4
5
6
7
8
9
10
11
12sqLiteOpenHelper = new DBOpenHelper(MainActivity.this, "Note.db", null, 1);
sqLiteDatabase = sqLiteOpenHelper.getReadableDatabase();
Cursor result = sqLiteDatabase.rawQuery("select * from note where accountId=" + account, null);
if (result.getCount() <= 0) {
int hhh = 1 / 0;
} else {
// cursor需要移动到指定行才能使用getString()方法来获取列数据
// -1开始,0为第一行,但第一行为行名
result.move(1);
// 第1列
pwd = result.getString(0);
}更新操作:
1
2
3
4
5
6
7
8
9
10
11
12
13sqLiteDatabase=sqLiteOpenHelper.getWritableDatabase();
ContentValues values=new ContentValues();
values.put("accountId",account);
values.put("title",editText.getText().toString());
String where="id="+id;
int i=sqLiteDatabase.update(DBOpenHelper.SQL_TB_Note_NAME,values,where,null);
if (i>0){
Log.d("TAG", "onClick:update ");
Toast.makeText(MainActivity.this, "更新成功" , Toast.LENGTH_SHORT).show();
}else {
Log.d("TAG", "onClick:noUpdate ");
Toast.makeText(MainActivity.this, "更新失败" , Toast.LENGTH_SHORT).show();
}删除操作:
1
2
3
4
5
6
7
8long i=sqLiteDatabase.insert(DBOpenHelper.SQL_TB_Note_NAME,null,values);
if (i==-1){
Log.d("TAG", "onClick:NoInsert ");
Toast.makeText(MainActivity.this, "添加失败" , Toast.LENGTH_SHORT).show();
}else {
Log.d("TAG", "onClick:insert");
Toast.makeText(MainActivity.this, "添加成功" , Toast.LENGTH_SHORT).show();
}
共享数据以实现记住密码的功能:
获取共享数据:
1
2
3
4SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
Boolean isRemember = prefs.getBoolean("rememberMe", false);
String account = prefs.getString("account", "");
String password = prefs.getString("password", "");发送数据:
1
2
3
4
5
6
7
8
9
10SharedPreferences.Editor editor = prefs.edit();
if (chkBoxRememberMe.isChecked()) {
// “记住密码”是否被选中
editor.putBoolean("rememberMe", true);
editor.putString("account", account);
editor.putString("password", password);
} else {
editor.clear();
}
editor.apply();