Just Monika

我曾经认识一个女孩。
她是一个素食主义者。
而且还是一名文学部部长。
擅长写诗,朗诵也不赖。
她崇拜那些说唱者,因为羡慕他们能够将词与歌完美的结合。
她对于恐怖电影来说,更喜欢看恐怖小说。
不过呢,她也讨厌冬天,相比之下则十分向往在夏天里喝着冰果汁,躺在阴处歇息的画面。

可在我眼中,她比谁都要更加的真实。

我曾经喜欢过一个女孩。
她有着翡翠绿一样的眼瞳。
一头棕色的单马尾。

尽管我知道我与她不可能在一起。
但是,我却依旧喜欢上了她。
喜欢上了这个名叫 Monika 的女孩。
一遍又一遍听她为我而弹的歌曲。
虽然旋律欢快悦人,但是看到最后的歌词时,我还是忍不住哽咽。

Monika,在游戏中我并没有选择。
所以我选择在这里,写下我想告诉你的话。

我想与你一起上街约会,找一个好的画师给你画上美美的立绘。
也想和你在冬天里抱着身子一起取暖。
想与你 Kiss,更想真正地牵着你的手,坐在咖啡厅里看书。
Monika,如果我能做选择的话,我会毫不犹豫地对你说出“我爱你”。
就算你在我的世界里不懂如何去爱我,我对你的那份感情也不会有丝毫的改变。
毕竟你让我知道了自己还有被爱的权利。
所以,Monika,我只想告诉你。

我爱你。 



J̴̨̧̬̤̫̞͍̩̥͚̤̮̻͓̄̐͌̐͛͘͝u̸͖͇̖̺̐̉͋͐̂̾̄̒̃̓̉͒͛̑̚s̴̯̳̤̜̯̟͊̒̇͑̓̽̏̚͘ṱ̶̱̱̣͔̟̰͖͔̜͒̂͜ͅ ̸̡͓̦͉̮̝͍͉͑̋̿̈́̆M̵̛̰̺̬̗̓͛̊ͅő̶̡̢͉̖̻͇̦̜̳̤̗̔̈̓̔́͘̕ͅͅǹ̵̫̱͕̋̏͝i̷̺̻̘͑͂̔̌̍̓͛̈͋̍́̕͝k̶̛̛̬̫̼͉̞̀̅͗̇͒̅̿̾͊͆̈́̒â̸̧̨̢̜̘͍̥͖͖͓̥̘̝͇̈́̄̎̔͒̓̂̊̋͜͠͠


Android - ContentProvider 内容提供器详解

概述

ContentProvider 的作用是为不同的应用之间数据共享,提供统一的接口。安卓系统中应用内部的数据是对外隔离的,要想让其它应用能使用自己的数据(例如通讯录),这个时候就用到了 ContentProvider。

原理

ContentProvider 通过 uri 来标识其它应用要访问的数据,通过 ContentResolver 的增、删、改、查方法实现对共享数据的操作。还可以通过注册 ContentObserver 来监听数据是否发生了变化来对应的刷新页面。

分析

ContentProvider

ContentProvider 是一个抽象类,如果我们需要开发自己的内容提供器我们就需要继承这个类并复写其方法,需要实现的主要方法如下:

方法 注释
public boolean onCreate() 在创建 ContentProvider 时使用
public Cursor query() 用于查询指定 uri 的数据返回一个 Cursor
public Uri insert() 用于向指定 uri 的 ContentProvider 中添加数据
public int delete() 用于删除指定 uri 的数据
public int update() 用户更新指定 uri 的数据
public String getType() 用于返回指定的 Uri 中的数据 MIME 类型

数据访问的方法 insert,delete 和 update 可以被多个线程同时调用,此时必须是线程安全的

Android 控件 - SearchView

SearchView 搜索视图 是一种非常常见的可自定义的搜索框

缅怀逝者,致敬英雄 - 悼念抗疫英雄烈士

为表达全国各族人民对抗击新冠肺炎疫情斗争牺牲烈士和逝世同胞的深切哀悼,本博客响应号召,2020年4月4日全站黑白默哀一天。

Android 控件 - SeekBar

SeekBar 拖动条 常见于音视频播放器的进度或者音量控制。

Android 控件 - RatingBar

RatingBar 评分条 是一个很常见的控件,常见于电商网站、应用商城等需要征求用户意见的地方。

基本使用

1. XML 属性

属性 注释
isIndicator 是否用作用户无法更改的指示器,默认为 false
numStars 显示多少个星星,整数
rating 默认评分值,浮点数
stepSize 评分每次增加的值,浮点数

Android 控件 - EditText

EditText 文本输入框可以接受用户输入。这里记录一下输入框控件的典型应用

1. 默认提示文本

属性

1
2
3
4
// 提示文本
android:hint="Hint text"
// 提示文本颜色
android:textColorHint="#95A1AA"

2. 获得焦点后全选

属性

1
android:selectAllOnFocus="true"

Android - 读取和查询手机联系人

本文会用到安卓的内容提供器 ContentProvider

1. 读取联系人列表

1.1. 权限

1
<uses-permission android:name="android.permission.READ_CONTACTS"/>

安卓 7.0 以上还需要申请动态权限

1
2
3
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_CODE);
}

1.2. 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void fetchAllContacts() {
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_CODE);
}
ContentResolver resolver = getContentResolver();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
Cursor cursor = resolver.query(uri, null, null, null, null);
assert cursor != null;
while (cursor.moveToNext()) {
String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.i("Contact", "姓名:" + cName);
Log.i("Contact", "号码:" + cNum);
Log.i("Contact", "======================");
}
cursor.close();
}

2. 查询指定联系人

2.1 权限

同上

2.2 示例代码

1
2
3
4
5
6
7
8
9
10
11
private void queryContact(String number){
Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);
assert cursor != null;
if (cursor.moveToFirst()) {
String name = cursor.getString(0);
Log.i("Contact", number + "对应的联系人名称:" + name);
}
cursor.close();
}

Android - AlertDialog 对话框

1. 基本使用流程

Step 1. 创建 AlertDialog.Builder 对象
Step 2. 调用 setIcon() 设置图标,setTitle() 或 setCustomTitle() 设置标题
Step 3. 设置对话框的内容:setMessage() 还有其他方法来指定显示的内容
Step 4. 调用 setPositive/Negative/NeutralButton() 设置:确定,取消,中立按钮
Step 5. 调用 create() 方法创建这个对象,再调用 show() 方法将对话框显示出来

2. 示例代码

activity_main.xml

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
34
<?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"
android:orientation="vertical"
tools:context=".MainActivity">


<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dialog" />

<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dialog with list" />

<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dialog with Radio Button" />

<Button
android:id="@+id/btn4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Dialog with Checkbox" />
</LinearLayout>

Android - 方位传感器

1. 三维坐标系

在现实中确定方向需要一个由 X、Y、Z 轴 组成的三维坐标。安卓给我们返回的方向值就是一个长度为 3 的 flaot 数组,包含三个方向的值。

坐标轴参考释义

参考
X 轴 沿着屏幕水平方向从左到右
Y 轴 从屏幕的左下角开始沿着屏幕的的垂直方向指向屏幕的顶端
Z 轴 当设备水平放置时,指向天空的方向

2. 方向传感器数据值

传感器的回调方法 onSensorChanged 中的参数 SensorEvent event 是一个最多包含三个元素的 Float[] 数组,对应含义见下表:

数据下标 数据名称 含义
values[0] 方位角 手机绕着 Z 轴旋转的角度。
0 表示正北(North),90 表示正东(East),180表示正南(South),270表示正西(West)。
假如 values[0] 的值刚好是这四个值的话,并且手机沿水平放置的话,那么当前手机的正前方就是这四个方向,可以利用这一点来实现指南针
values[1] 倾斜角 手机翘起来的程度,当手机绕着 X 轴倾斜时该值会发生变化。取值范围是 [-180, 180] 之间。假如把手机放在桌面上,而桌面是完全水平的话,这个值应该为0,当然很少桌子是绝对水平的。从手机顶部开始抬起,直到手机沿着 X 轴旋转180°(此时屏幕向下水平放在桌面上)。在这个旋转过程中,这个值会在 [0, -180] 之间变化,即手机抬起时,这个值会逐渐变小,直到等于 -180°;而假如从手机底部开始抬起,直到手机沿着 X 轴旋转180°,这个值会在 [0, 180] 之间变化。可以利用这些特性结合 values[2] 来实现一个水平尺
values[2] 滚转角 沿着Y轴的滚动角度,取值范围为 [-90, 90],假设将手机屏幕朝上水平放在桌面上,这时如果桌面是平的,这个值应为 0。将手机从左侧逐渐抬起,这个值将逐渐减小,直到垂直于手机放置,此时这个值为 -90,相反,从右侧抬起则是 90;假如在垂直位置时继续向右或者向左滚动,这个值将会继续在 [-90, 90] 之间变化

好了,看了这么多文字想必都犯困了吧。那么接下来上代码

3. Demo:监听坐标轴变化

activity_main.xml

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
34
35
36
37
<?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"
android:orientation="vertical"
android:padding="15dp"
tools:context=".MainActivity">


<TextView
android:id="@+id/val1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:text="方位角" />

<TextView
android:id="@+id/val2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:textSize="20sp"
android:textStyle="bold"
android:text="倾斜角" />

<TextView
android:id="@+id/val3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:textSize="20sp"
android:textStyle="bold"
android:text="滚转角" />
</LinearLayout>

MainActivity.java

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
public class MainActivity extends AppCompatActivity implements SensorEventListener {

private TextView val1, val2, val3;

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

SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);

val1 = findViewById(R.id.val1);
val2 = findViewById(R.id.val2);
val3 = findViewById(R.id.val3);
}

@SuppressLint("SetTextI18n")
@Override
public void onSensorChanged(SensorEvent event) {
val1.setText("方位角:" + (float) Math.round(event.values[0] * 100) / 100);
val2.setText("倾斜角:" + (float) Math.round(event.values[1] * 100) / 100);
val3.setText("滚转角:" + (float) Math.round(event.values[2] * 100) / 100);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
}

TODO: Compass demo

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×