App开发是一个工作量比较大的项目,要学习App开发首先我们要先去学习手机中的各类工具和信息是怎么运行的,我们可以使用哪些工具来对手机进行设置。这里我采用的开发工具是Android studio。
目录
Textview控件
文本框控件:
阴影/模糊度控件:
Button控件
按钮设置:
按键事件:
EditText控件
ImageView控件
ProgressBar控件
Notification控件
消息创建:
消息转换:
Toolbar控件
Alertdialog控件
Textview中的文本框控件是用来配置显示的文本框的配置器,常见使用到的工具有:id、gravity、text、textcolor、layout_width、layout_height、textsize、textstyle、backgroud。
android:id="@+id/app_id"
android:layout_width="514dp"
android:layout_height="832dp"
android:background="@color/cardview_light_background"
android:gravity="center"
android:text="@string/str1"
android:textColor="#FF335566"
android:textSize="30sp"
android:textStyle="italic"
id是用于配置这个文本框的名字,以便我们到时候在java代码里使用到时能够直接通过id来访问这个文本框。所以我们一般也会在java代码里创建一个Textview的变量:
TextView app_id = findViewById(R.id.app_id);
我们可以通过这个变量来直接修改文本框里的内容,并且在java里的修改可以直接覆盖里面原来的内容。
textstyle和textsize分别是用于设置字体的风格和字体的大小,字体的风格有三种形式:normal(正常)、bold(粗体)、italic(斜体)。而字体的大小就是可以自己设置的了,不过字体的大小一般是以sp为单位,以便于在不同的手机在适配。
layout_width和layout_height分别用于配置文本框的长和宽,它们可以有选择或者自己配置,自己配置就是以dp为单位配置,选择就可以有三种:match_parent、wrap_content或者fill_parent,但是常用的就是前面两个。match_parent是看手机有多宽就自动适配到对应大小,而wrap_content就看Textview内的字体的大小来自动分配占的大小。
background和Textcolor就是分别设置背景颜色和字体颜色了。它们使用一般是双引号里先跟个#号再输入一个8位的数字,前面两位表示字体透明度,第3、4位表示三原色中的红,5、6表示绿,7、8表示蓝。我们可以自定义配置颜色,为了通用也可以将其放入到专门存放的文件中:
最后就是字体的位置gravity和字体text了,通过字体位置我们可以很方便去控制字体显示的位置,字体位置这里也向我们提供了多个选择:
但是值得主义的是text中的字符串我们为了让其有普遍的适用性可以将其放到strings.xml里面,就像我们放自定义的颜色进去color.xml文件里面一样。
android:shadowColor="@color/black"
android:shadowRadius="9.0"
android:shadowDx="10.0"
android:shadowDy="60.0"
先贴出代码,我们要是想控制字体的阴影或者模糊度都可以利用这个代码,下面我们来看看这几个量:
首先是阴影的颜色,就是shadowcolor,这个颜色与我们之前的text颜色配置之类都一样,这就不多说了,然后就是shadowRadius,这个表示阴影的模糊程度,0.1就是正常的字体,这个度越大就表示越模糊。而后面的shadowDx和shadowDy就表示将阴影移动的位置偏移量,下面我们来看看9.0的模糊度和3.0模糊度的的对比(左边是9.0,右边是3.0):
说到手机就不可避免需要设置按钮,我们设置按钮是通过在
上面的代码是去配置一个按钮,这个按钮长宽均为95dp,并且按钮里吗显示的是“按钮1”的文字:
为了更美观,也更好看,我们选择将按钮的背景修改一下,就像我们修改文本框里的的背景颜色一样。这里需要使用到图片选择器。首先我们在drawable里面创建一个图片选择器的文件(drawable Resource File),这样我们的按钮图片都可以存放到里面,并且可以设置状态:
然后我们可以在drawable里面又创建两个文件来存储我们按钮的图标。这里我们选择使用的是Vector Asset,并且点进去clip Art就可以选择图标的图片了。我们也可以选择导入我们自己自定义的图片。
这里我选择了两张图片,并且命名为pic1和pic2,我让它们分别充当我按下按钮前显示的图标和按下按钮后显示的图标。然后将图片导入到图片选择器里,如下图,设置这些图片的状态。
这里的图片状态有很多,我们可以根据我们的需求来选择,这里我选择的是将图片1设置为state_press为true时显示,这就代表着如果我按下按钮,那么显示的是图片1。
如果还想设置图标的颜色,我们可以选择在res下新建一个颜色选择器(Directory),方法原理和图片选择器一样,最后再将颜色选择器赋给backgroundTint即可。
常见的按键触发的事件,我们分为三类:触摸事件(setOnTouchListener)、点击事件(setOnClickListener)和长按事件(setOnLongClickListener);它们三着分别对应不同的意义。要想设置这些事件,我们首先在java里设置一个案件的类:
Button button_id = findViewById(R.id.But);
这个类的id我已经在之前的activity_main.xml文件里面给button定义了。所以我在java里直接用findviewbyid来创建一个button_id类。之后我们就可以来创建三个事件了:我们让这些事件分别都输出它们的状态:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//TextView app_id = findViewById(R.id.app_id);
Button button_id = findViewById(R.id.But);
button_id.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "onClick: " );
}
});
button_id.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
Log.e(TAG, "onLongClick: ");
return false;
}
});
button_id.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.e(TAG, "onTouch: " );
return false;
}
});
此时再运行我们可以看到当我们点击按钮时事件对应就会有输出:这里我们需要注意三个事件的顺序:当我们触摸到了按钮,ontouch事件就会发生,它包含三个状态:按下、移动、放开。所以当我们按下按钮时,会输出三次Ontouch,因为我们按下一个按钮(无论长短按)都会有按下、移动、放开的三个顺序。所以ontouch会输出三次。
1、此时如果我们是短按,就有输出三次ontouch加一次onclick。
2、但是要是此时我们长按,会有3次输出ontouch加一次onlongclick和最后一次onclick。
总结起来三个事件顺序是:ontouch>onlongclick>onclick。如果我们不想后面的事件执行,那么只需要将return后面的false改成true即可。即如果ontouch里的return改成true,那么onlongclick和onclick事件都不会执行;如果onlongclick后面的return改成true,那么此时onclick将不会执行。
android:id="@+id/name"
android:layout_width="225dp"
android:layout_height="75dp"
android:layout_marginTop="136dp"
android:backgroundTint="@color/white"
android:drawableLeft="@drawable/ic_baseline_create_24"
android:drawablePadding="5dp"
android:hint="请输入用户名"
android:inputType="text"
android:padding="5dp"
android:textSize="25dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
这个控件用于输入的设置,我们手机上经常需要输入密码之类的,这个输入界面的一些控件就可以由EditText来设置。它主要的工具有:hint、inputType、padding、groundTint、drawableLeft等等。
hint是输入界面的提示信息,就像“请输入密码”、“请输入用户名”之类的,当我们有东西输入进去这些提示字符就会消失,因为EditText也是继承自Viewtext,所以我们可以利用Textsize和Textcolor来控制这些输入信息的大小和颜色。
其次就是inputType,这个工具用于指定你能够输入的数据类型,如文本、纯数字、密码(输入立马变成星号)...
还有一个就是输入左端我们一般可以设置一些图标信息,如下图所示,这些图标信息就是由drawbaleLeft来设置(放左端情况下)。而图标和输入框的距离可以用drawablepadding来控制,具体图标加输入框的整体位置就用padding来控制。
说完输入信息,我们还需要将信息存储起来,这时候就需要联系到按键的知识了,我们可以在输入的下面增加一个按键,并且将按键点击的事件设置为获取输入的信息即可,获取信息的方式可以如下,使用getText里面的tostring来获取字符串形式数据。
EditText ed_name = findViewById(R.id.name);
EditText ed_pwd =findViewById(R.id.password);
Button but = findViewById(R.id.but);
but.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String name = ed_name.getText().toString();
String pwd = ed_pwd.getText().toString();
Log.e(TAG, "name: "+name );
Log.e(TAG, "passowrd:"+pwd );
}
});
这部分有个小问题,就是如果我们直接在split里移动这些框,可能会报Missing Constraints in ConstraintLayout的错误,此时可以按一下下面图示地方即可:
Imageview这个控件是我们用来配置图片的,我们随机获得的图片或许不一定会符合我们为图片开辟的框架大小,此时就需要我们对图片进行设置。首先我们将图片复制到drawable下。然后创造一个ImageView类,并且开辟一个200dp x 200dp大小的框架,然后使用src工具来将其导入。导入后我们可以利用scaletype工具来调试图片的显示,它有很多的选择:fitstart、fitCenter、fitend、fitxy、center、centercrop、centerinside、matrix。默认是fitcenter,它表示将图片缩放放中间;fitstart表示保持宽和高来缩放图片,直到比较长的边和框相等,缩放后放上面,而fitend放下面。左图表示fitstart、右图表示fitend
fitxy表示完全填充,直至满,一般会对图片进行拉伸;center表示显示到中心,如果图片比文本框大,则超出的裁剪;centercrop表示等比缩放图片,直至适应框,超过部分裁剪;centerinside也表示将缩放,不过如果图片小于图片框,那么不会处理(fitCenter则会处理小的图片直到适应);matrix表示不改原图大小,放到左上角,超过部分裁剪。
还有一种方式是直接让图片框来适应图片,即图片有多大,就对图片框进行裁剪,让图片框大小适应图片大小。此时就用到maxHeight、maxWidth和adjustViewBounds。前面两者表示图片框大小,而后面的表示图片框是否可以根据图片大小进行裁剪,这里选择是。
这样我们的图片框大小就可以很好地符合我们地图片大小了:
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200dp"
android:layout_height="0dp"
android:layout_marginStart="84dp"
android:layout_marginTop="48dp"
android:max="100"
android:indeterminate="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
ProgressBar控件是用于设置进度条的信息的,也就是我们手机上常见的转圈圈和加载条。ProgressBar控件常用的属性有:max、progress、indeterminate。其中max表示我们进度条的最大值,一般情况下可以默认为100,progress表示我们当前的进度、indeterminate表示是否不精确显示进度,显示的话进度条会一直动直到填满,不显示的话就是进度条一直来回动:左图为不显示、右图为显示。
对于进度条而言,一个很重要的指标就是当前进度,我们可以通过java里设置的类来访问到progress的当前值甚至修改它。
pb = findViewById(R.id.pb);
------------------------------------
int now = pb.getProgress();
now += 10;
pb.setProgress(now);
注意:一般情况下我们默认的进度条是一个圆圈在转来转去,要是想要修改它的进度条的显示方式,只需要设置style的数值即可:
style="?android:attr/progressBarStyleHorizontal"
Button but1 =findViewById(R.id.but1);
Button but2 =findViewById(R.id.but2);
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new
NotificationChannel("K","test",NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
notification = new NotificationCompat.Builder(this,"K")
.setContentTitle("通知!")
.setContentText("没事了..")
.setSmallIcon(R.drawable.pic1)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.pic3))
.setColor(Color.parseColor("#ff0000"))
.build();
Notification这个控件是用于管理我们的消息的,它共需要两个类,一个是消息Notification这个类,另外一个是管理消息的NotificationManager这个类,其中NotificatioManager这个类并不需要具体实例化对象,它是由系统进行维护的,我们使用的时候只需要通过安卓服务的句柄获取一个对象即可。这里我们在oncreate类外对我们即将创建的对象进行声明:
private Notification notification;
private NotificationManager manager;
首先我们先去申请一个消息管理器的对象,这里我们使用getsystemservice方法来获取这个对象,并且将其转换为和我们创建的manager的相同类型。获取方式就是使用NOTIFICATION_SERVICE字符串
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
当创建了消息管理器后,我们下一步就需要创建一个消息了:
notification = new NotificationCompat.Builder(this,"K")
这个消息我们使用Notificationcompat方法下的Builder方法来创建,向其传入两个参数,一个是this,另一个是channelid,这个channelid是消息的来源,所以我们还需要创建一个消息来源,但是因为是安卓8.0以后才引入消息渠道,所以我们还需要判断一下版本:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel channel = new
NotificationChannel("K","test",NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
在if语句内部创建一个新的channel来源,它的第一个channelid与我们消息的channelid一样即可,第二个是来源的名字,这里我们起为test,第三个就是消息的重要等级:
然后我们只需要将消息来源赋给我们创建的消息管理器即可:
manager.createNotificationChannel(channel);
最后就是对消息框的设置:消息框的设置利用链式法则直接跟在消息设置的后面即可,其中标题、文本内容和小图标是必须要填的!
如下,我设置了标题为“通知”、文本内容为”没事了..“,小图标我设置为我存储的照片pic1,大图标设置为我存储的另一种照片,这里要注意一个点,那就是小图标必须是黑白的,而且是int类型。大图标就不同,可以是彩色的。
notification = new NotificationCompat.Builder(this,"K")
.setContentTitle("通知!")
.setContentText("没事了..")
.setSmallIcon(R.drawable.pic1)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.pic3))
.setColor(Color.parseColor("#ff0000"))
.build();
运行效果如下:
notification = new NotificationCompat.Builder(this,"K")
.setContentTitle("通知!")
.setContentText("没事了..")
.setSmallIcon(R.drawable.pic1)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.pic3))
.setColor(Color.parseColor("#ff0000"))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
-------------------------------------------------------------------------
我们知道,当我们有消息时,我们一般会点进去,这样才能进去别的页面,而这种设置就需要用到contentintent了,它的方法是setcontentintent,这个方法需要一个参数pendingintent,intent是意图,pending是悬而未决的,合起来意义是我们想要转进的地方,所以我们先创建一个意图:
Intent intent = new Intent(this, NotificationActivity.class);
这个意图有两个参数,第一个是我们原来的类,也就是现在this指向的位置,第二个就是我们要去的类,这里我创建一个新的类:
在这个类中我们只输出一句话,以此来判断是否转进成功:
package com.example.myproject;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
public class NotificationActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("K", "onCreate: enter" );
}
}
这个类的书写也有考究,首先我们创建一个新的java类后让其继承自Activity,然后输入oncre后面那一堆就出来了,我们实际输入的就一句:Log.e("K", "onCreate: enter" );
我们创建一个新的类后让其作为意图的目的传递给意图,但是我们需要的是一个Pendingintent,一个悬而未决的意图,所以我们还需要创建一个新的满足方法参数的意图:
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);
最后将其传入给方法即可,这里为了方便还设置了一个点击删除消息的方法:
.setAutoCancel(true)
下面来测试一下,因为消息需要东西来触发,所以我们这里设置两个按钮,一个负责触发消息,一个负责取消消息:
public void But1(View view) {
manager.notify(1,notification);
}
public void But2(View view) {
manager.cancel(1);
}
下面我们来看看测试表现:
点击触发按钮:
点击消息:
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/tb"
app:navigationIcon="@drawable/ic_baseline_navigate_before_24"
android:background="#98ffff"
app:title="TITILE"
app:titleMarginStart="90dp"
app:logo="@drawable/mood"
app:titleTextColor="#ff0000"
Toolbar控件是用来配置导航栏的信息的,我们都知道,在一个页面上方都需要有导航栏。我们来看看配置导航来的控件Toolbar。这里我们常用到的是navigationicon、titile、titlemarginstart、logo和titletextcolor这5个配件,当然,副标题也可以配置,这些我就不记录在这里。
首先是titile,这个毫无疑问就是标题的内容,而titletexcolor就是配置标题颜色的属性,titlemarginstart则是配置标题距离手机左侧的距离。
再来看看navigationicon,这个是导航键,也就是常见的手机左上方的返回键,这里图标和意义我们都可以设置:
Toolbar tb = findViewById(R.id.tb);
tb.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e(TAG, "onClick: click here!" );
}
});
这里我们就设置点击这个导航键就可以输出一行信息,当然,我们也可以实现页面跳转,就像之前的信息栏控制一样,这里不多赘述。
logo就是可以在导航栏新增一个logo的图标。结合所以的这些,下面就是成果图:
这里有两个注意事项:
1、我们java里的toolbar包要导这个包:import androidx.appcompat.widget.Toolbar;
2、要想删除原先项目自带的标题栏,只需要到values下的theme文件修改即可:
public void click(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.pic1)
.setTitle("标题")
.setMessage("内容")
.setPositiveButton("按钮1", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e(TAG, "onClick: 按钮1" );
}
})
.setNegativeButton("按钮2", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e(TAG, "onClick: 按钮2");
}
})
.setNeutralButton("按钮3", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e(TAG, "onClick: 按钮3" );
}
})
.create()
.show();
这个控件是用来配置我们的对话框,也就是会显示到手机中间的事件框。我们对话框的设置需要用到Alertdialog的Bulider来配置一个对话框,就像我们配置消息一样。与消息一样,为了触发这个对话框,我在这里设置了一个按钮,在按钮的触发事件里来配置对话框:
与消息一样,在配置对话框前我们需要先来设置一个Alertdialog对话框:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
创建一个对话框后,我们就可以来配置对话框的内容了:首先是seticon,这个属性用来配置对话框的图标;其次是settitle、setmessage,这两个分别表示对话框的标题以及对话框的内容。其次是对话框里的按键,这里默认三个按键,分别分为左右和中,这些按键都需要创建点击事件:
.setNegativeButton("按钮2", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//点击触发内容
}
最后就是创造一个对话框和显示出来,分别是create和show。这里要注意的是无论中间使用链式法则配置多少内容,都需要将create和show按顺序放到后面。下面是测试结果:
参考资料:控件篇参考资料