1、工程結構介紹
項目工程文件介紹:

.gradle和.idea:項目自動生成的一些文件,一般打包的時候會將這兩個包刪掉然后去發給別人
.app:項目中的資源和代碼都會在這里面,工作里面的核心目錄
gradle:是構建器,里面有一個wrapper文件,
gitignore:版本控制的時候,指定把我們的文件排除在版本控制里面

gradlew:用在Mac或者linux系統上的gradle執行指令的時候所用的文件
gradlew.bat:windows里面執行gradle所用文件。

local.properties:指定sdk的路徑

settings.gradle:指定我們項目中所有引入的模塊

下面是app內部的目錄結構:

- build:這個文件就是通過build>make project去生成的。

一般在壓縮的時候也會將這個刪除去減少我們壓縮包的大小。
-
libs:當我們項目中使用了第三方的jar包的時候,就需要把jar包放到這個目錄中去。
-
src:
- androidTest:編寫測試用例的
- main
- java:java代碼
-
res:
- AndroidManifest.xml:四大組件的注冊和權限等。
- test:單元測試
-
gitignore:這個內部的gitignore和外部的作用一樣,只不過外面是管理整個工程的,而這個是管理我們這個app的。
-
build.gradle:app模塊的構建腳本,一般一些第三方庫的依賴就是在這里
-
properties:指定項目代碼的混淆規則
2、TextView
2.1基礎屬性:
layout_width 、layout_height:設置組件的寬高
-
match_parent:父容器有多寬,這個組件就有多寬
-
wrap_content:內容有多寬,這個組件就有多寬
-
或者直接輸入數值
id: 設置一個組件的id
text:
-
在布局文件中設置組件的文本內容:
android:text="hello"
-
也可以在java代碼當中設置文本內容,如果兩個都設置的話,java代碼中設置的文本內容會把xml布局文件中設置的文本內容給覆蓋掉。
TextView tv_one = findViewById(R.id.tv_one); tv_one.setText("leo");
兩個都設置了之后,最終的顯示結果:

textColor:設置字體的顏色
顏色一共有八位。
- 最前面這兩位設置咱們的透明度。00表示純透明,ff表示不透明。
- 剩下六位依次是:紅、綠、藍
textStyle:設置字體的風格
如果屬性忘記有什么了,可以直接點進來看。
textSize:字體大小,一般用的是sp
android:textSize="30sp"
background: 控件的背景顏色,可以理解為填充整個控件的顏色,可以是圖片
android:background="#FFFF0000"
gravity: 設置控件中內容的對齊方向,TextView中 是文字,ImageView中是圖片等等。
android:gravity="center"
上面的這些可能不太規范,一般都是放到values這個文件夾下的文件里面
比如設置字符串名字就是string.xml里面寫
<resources>
<string name="tv_one" >123456</string>
</resources>
就可以在layout里面引用了
android:text="@string/tv_one"
2.2帶陰影的TextView
-
android:shadowColor:設置陰影顏色需要與shadowRadius-起使用
-
android:shadowRadius:設置陰影的模糊程度設為0.1就變成字體顏色了,建議使用3.0
-
android:shadowDx:設 置陰影在水平方向的偏移就是水平方向陰影開始的橫坐標位置
-
android:shadowDy:設置陰影在豎直方向的偏移就是豎直方向陰影開始的縱坐標位置
<TextView
android:id="@+id/tv_one"
android:layout_width="200dp"
android:layout_height="200dp"
android:text="@string/tv_one"
android:textColor="@color/design_default_color_background"
android:textStyle="italic"
android:textSize="30sp"
android:shadowColor="@color/red"
android:shadowRadius="3"
android:shadowDx="10.0"
android:shadowDy="10.0"
android:gravity="center"/>
顯示效果如圖所示:

2.3跑馬燈效果的TextView
- android:singleLine:內容單行顯示
- android:focusable:是否可以獲取焦點
- android:focusablelnTouchMode;用於控制視圖在觸摸模式下是否可以聚焦
- android:ellipsize="marquee"在哪里省略文本
- android:marqueeRepeatLimit:字幕動畫重復的次數
<TextView
android:id="@+id/tv_two"
android:layout_width="200dp"
android:layout_height="200dp"
android:text="@string/circle"
android:textColor="@color/design_default_color_background"
android:textStyle="italic"
android:textSize="30sp"
android:shadowColor="@color/red"
android:shadowRadius="3"
android:shadowDx="10.0"
android:shadowDy="10.0"
android:gravity="center"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:focusable="true"
android:focusableInTouchMode="true"/>
設置完這些屬性還是沒有動起來:
-
設置可點擊:
android:clickable="true"
點擊之后顯示跑馬燈效果。
-
自定義MyTextView繼承TextView(5.0之后是
androidx.appcompat.widget.AppCompatTextView
),重寫isFocused()方法@Override public boolean isFocused() { return true; }
然后更改我們的組件的名字把TextView換成我們自己的組件
com.android.myapplication.MyTextView
-
或者直接在
<TextView>
標簽中設置一個<requestFocus/>
先從第二問開始吧,
AppCompatTextView
繼承自TextView
,是對TextView
的一種擴展,因為在5.0中首次推出了MaterialDesign
這種設計風格,但是眾所周知,5.0推出不可能所有的設備全部都更新到最新版本,為了在早期版本上實現新的功能(這些新功能比如從源碼注釋中解讀到backgroundTint
屬性,根據文本內容自適應大小等),即為了新特性同樣可以兼容老版本,framework在創建TextView
實例的時候,自動幫我們進行了替換。其它的AppCompatXXX與XXX的關系也是如此。
3.Button
3.1StateListDrawable
設置background:
設置按鈕顏色的時候在老版本設置按鈕顏色的時候是顯示正常的,但是新版本需要設置一下
在themes文件下添加.Bridge
新建一個drawable資源中,設置按鈕按下和不按下的時候的區別
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_baseline_account_balance_24" android:state_pressed="true"></item>
<item android:drawable="@drawable/ic_baseline_accessibility_24" android:state_pressed="false"></item>
</selector>
設置backgroundTint

在res下新建一個color文件夾,新建一個draw資源文件中
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="ff0000" android:state_pressed="true"/>
<item android:color="@color/black" />
</selector>
在布局文件中:
android:backgroundTint="@color/btn_color_seletor"
設置前景色foreground
android:foreground="#50667788"
事件監聽:
- 首先現在oncreate方法里面找到btn
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.btn);
}
可以添加各種監聽事件:
- 點擊事件
//點擊事件
btn.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
Log.e(TAG,"ONCLICK:");
return false;
}
});
當返回值為true的時候,沒有打印onclick方法。先執行ontouch-->onlongclick(true),由於條件判斷導致onclick這個方法沒有執行。
- 觸摸事件
//觸摸事件
btn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.e(TAG,"ontouch:"+motionEvent.getAction());
return false;
}
});

鼠標按下去是 ontouch0
鼠標長按之后左右move是2
鼠標抬起來是ontouch1
onclick事件發生在ontouch 0之后
- 長按事件
//長按事件
btn.setOnLongClickListener(new View.OnLongClickListener(){
@Override
public boolean onLongClick(View view) {
Log.e(TAG,"onLongClick:");
return false;
}
});
當我們設置這個方法的返回值為true的時候,就不再顯示其他事件了。
事件就被ontouch消費了,就不再傳遞給onclick和onlongclick了
你要點擊按鈕,肯定事先得觸摸按鈕,所以才有觸摸事件,然后才有點擊事件,然后點擊按鈕又會有按下和按鈕彈起這些時間。
長按事件處理除了這個內部類監聽之外還有可以添加自定義方法:
public void helloClick(View view) {
Log.e(TAG,"ONCLICK:");
}
在layout中只需要寫這個方法的名字即可
android:onClick="helloClick"
4、EditText
屬性
- android:hint輸入提示
android:hint="請輸入用戶名:"
-
andrid:textColorHint:輸入提示文字的顏色
-
android:nputType:輸入類型
比如說設置為phone
android:inputType="phone"

- android:drawablexXxx :在輸入框的指定方位添加圖片
比如說我們添加一個左側的圖標:
android:drawableLeft="@drawable/ic_baseline_person_24"
-
android:drawablePadding:設置圖片與輸入內容的間距
圖標距離文字太近了,可以設置一定的邊距:
android:drawablePadding="20dp"
-
android:paddingXxx:設置內容與邊框的間距
android:paddingLeft="20dp"
-
android:background:背景色
獲取輸入框內容:
設置兩個組件的id分別為et和btn
public class MainActivity extends AppCompatActivity { private EditText et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //分別獲取兩個id Button btn = findViewById(R.id.btn); et = findViewById(R.id.et); //設置監聽事件 btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //輸出 String text = et.getText().toString(); Log.e("leo","輸入的內容"+text); } }); } }
這里一直獲取不出來,是因為選擇錯了模擬器!
5、imageView
屬性
- scaleType
android:scaleType="matrix"
縮放類型:
-
fitStart:保持寬高比縮放圖片,直到較長的邊與Image的邊長相等縮放完成后將圖片放在ImageView的左上角
-
fitCenter:默認值,同上,縮放后放於中間
-
fitEnd:同上,縮放后放於右下角
-
fitXY:對圖像的橫縱方向進行獨立縮放,使得該圖片完全適應lmageView,但是圖片的寬高比可能會發生改變
-
center保持原圖的大小,顯示在ImageView的中心。 當原圖的size大於ImageView的size,超過部分裁剪處理。
並不會對圖片進行一個拉伸
-
centerCrop保持寬高比縮放圖片,直到完全覆蓋ImageView,可能會出現圖片的顯示不完全
-
centerInside保持寬高比縮放圖片,直到ImageView能夠完全地顯示圖片
centerInside最主要的功能是把這個圖片顯示在imageView里面,如果你的圖片小於這個imageView的話,就直接顯示在最中間

如果你的圖片大於imageView的話,就將其縮放。
如果圖片大於imageView的話,centerInside和fitCenter顯示效果相同。但是如果圖片小的話,顯示效果是不同的。
- matrix不改變原圖的大小,從ImageView的左上角開始繪制原圖,原圖超過ImageView的部分作裁剪處理

imageView很少有情況和我們的imageView的長寬一樣。
所以我們需要設置
maxWidth和maxHeight:
android:maxHeight="200dp"
android:maxWidth="200dp"
添加之后並沒有什么變化,設置一下adjustViewBounds為true:
android:adjustViewBounds="true"
6、Progressbar
屬性
-
android:max:進度條的最大值
-
anndroid:progress: 進度條已完成進度值。通過這個值來獲取當前進度條的值
- 給button加上一個click方法load:
android:onClick="load"
-
progressbar設置id
android:id="@+id/pb2"
-
progressbar獲取id
private ProgressBar pb2; //oncreate方法: pb2 = findViewById(R.id.pb2);
-
編寫方法load
public void load(View view) { //設置進度條的值 int progress = pb2.getProgress(); //每次click的時候這個數值都要增加10 progress+=10; //重新設置progress的數值 pb2.setProgress(progress); }
-
android:indeterminate:如果設置成true,則進度條不精確顯示進度,類似於我們之前的圓形進度條,一直在滾動。不固定。
-
style=" ?android:attr/progressBarStyleHorizontal":水平進度條
style="?android:attr/progressBarStyleHorizontal"
設置進度條顯示或者隱藏:
private ProgressBar pb;
//在oncreate方法里面
pb = findViewById(R.id.pb);
然后創建事件監聽:
public void helloClick(View view) {
if (pb.getVisibility() == View.GONE){
pb.setVisibility(View.VISIBLE);
}else{
pb.setVisibility(View.GONE);
}
}
View.VISIBLE--->可見
View.INVISIBLE--->不可見,但這個View仍然會占用在xml文件中所分配的布局空間,不重新layout
View.GONE---->不可見,但這個View在ViewGroup中不保留位置,會重新layout,不再占用空間,那后面的view就會取代他的位置,
7、notification
創建一個NotificationManager
NotificationManager類是一個通知管理器類,這個對象是由系統維護的服務,是以單例模式的方式獲得,所以一般並不直接實例化這個對象。
-
使用Activity. getSystemService(String)方法獲取NotificationManager對象
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Activity.getSystemSericelString)方法可以通過Android系統級服務的句柄,返回對應的對象。在這里需要返NotificationManager,所以直接傳遞Context.NOTIFICATION_ SERVICE即可。
-
使用Builder構造器來創建Notification對象
使用NotificationCompat類的Builder構造器來創建Notification對象,可以保證程序在所有的版本上都能正常工作。Android8.0新增 了通知渠道(channelId)這個概念,如果沒有設置,則通知無法Android8.0的機器上顯示Notification build = new NotificationCompat.Builder(this,"hello").build();
這里builder的第二個參數就是ChannelId
NotificationChannel
通知渠道: Android 8.0引入了通知渠道,其允許您為要顯示的每種通知類型創建用戶可自定
義的渠道。
所以我們需要判斷一下版本:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel("hello", "測試通知", NotificationManager.IMPORTANCE_HIGH);
//把創建的放入這里面
manager.createNotificationChannel(channel);
}
NotificationChannel
public NotificationChannel(String id, CharSequence name, int importance) {
throw new RuntimeException("Stub!");
}
-
id:實際上就是我們的channelId,這里必須要和我們notification里面的channelId是一樣的!
-
CharSequence name:我們后期用戶可以看懂即可
-
int importance:
通知重要程度:
- IMPORTANCE_ NONE關閉通知
- IMPORTANCE_ MIN 開啟通知,不會彈出,但沒有提示音,狀態欄中無顯示
- IMPORTANCE_ Low開啟通知,不會彈出,不發出提示音,狀態欄中顯示
- IMPORTANCE_ DEFAULT開啟通知,不會彈出,發出提示音,狀態欄中顯示
- IMPORTANCE_HIGH 開啟通知,會彈出,發出提示音,狀態欄中顯示
設置通知的一些屬性
- setContentTitle 設置通知的標題
- setContentText設置通知的內容
- setSmallIcon()
Notification notification = new NotificationCompat.Builder(this,"hello")
.setContentTitle("官方通知")//設置通知的標題
.setContentText("世界那么大,想去走走嗎?")//設置通知的內容
.setSmallIcon(R.drawable.ic_baseline_person_24)//設置通知的圖標
.build();
public Builder setSmallIcon(int icon)
返回值為int型,所以只能不能是有顏色的圖
Android從5.0系統開始,對於通知欄圖標的設計進行了修改現在Google要求,所有應用程序的通知欄圖標,應該只使用alpha圖層來進行繪制,而不應該包括RGB圖層。簡而言之來說,就是圖片不能帶顏色!
//通過發送通知來觸發通知
public void sendNotification(View view) {
//這里的第一個參數
manager.notify(1,notification);
}
-
id 指定通知的 id,要保證每個通知的 id 是不同的;
-
Notification 對象,傳入之前創建好的即可。
顯示效果:

其他的一些屬性:
-
setLargelcon(Bitmap icon)設置通知的大圖標
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.test1))
這里的Icon的格式是bitmap所以可以設置彩色的圖片
但是需要轉換一下:
BitmapFactory.decodeResource(getResources(),R.drawable.test1)
-
setColor(int argb)設置小圖標的顏色
這里的參數是int型的rgb,我們可以調用Color.parseColor(),把這個十六進制的顏色轉化為int型的數值
-
setContentIntent(PendingIntent intent)設置點擊通知后的跳轉意圖
需要先創建Intent:
Intent intent = new Intent(this, NotifictionActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
然后將這個pendingintent放入到setContentIntent方法中
PendingIntent.getActivity中的四個方法:
context:上下文對象。
requstCode:請求碼,發件人的私人請求代碼(當前未使用)。
intent:請求意圖。用於要指明要啟動的類以及數據的傳遞;
flags:這是一個關鍵的標志位:
-
setAutoCanelboolean boolean)設置點擊通知后自動清除通知
.setAutoCancel(true)
設置取消通知:
public void cancelNotification(View view) { manager.cancel(1); }
注意這里的cancel傳入的參數id是要和我們剛開始manager.notify(1,notification);這里面的id要一致!
-
setWhen(long when)設置通知被創建的時間
8、toolbar
在res>values>themes.xml文件中可以看到:
我們可以將其修改為NoActionBar
之后可以看出這里的toolbar沒有了

屬性:
特別注意這里的這個Toolbar應該是androidx.appcompat.widget.Toolbar!
-
android:layout_width="match_parent"
-
android:layout_height="?attr/actionBarSize"
<androidx.appcompat.widget.Toolbar
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>

注意此時的linearlayout的寬高都是match_parent
-
設置標題顏色 邊距:
app:title="標題"
app:titleTextColor="#ff0000"
app:titleMarginStart="90dp" -
設置子標題的顏色
app:subtitle="子標題"
app:subtitleTextColor="@color/purple_200" -
設置logo和navigationicon
app:logo="@mipmap/ic_launcher"
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
app:title="標題"
app:titleTextColor="#ff0000"
app:titleMarginStart="90dp"
app:subtitle="子標題"
app:subtitleTextColor="@color/purple_200"
app:logo="@mipmap/ic_launcher"
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
效果:

同時也可以通過java里面的類直接設置:
Toolbar toolbar2 = findViewById(R.id.tb2);
toolbar2.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24);
toolbar2.setTitle("TOOLBAR2");
toolbar2.setSubtitle("TOOLBAR2副標題");
toolbar2.setNavigationIcon(R.mipmap.ic_launcher);
Log.e("hello","onclick:toolbar2被點擊了~");
設置toolbar內容居中:

<androidx.appcompat.widget.Toolbar
android:id="@+id/tb3"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginTop="10dp"
android:background="#ffff00"
>
<TextView
android:text="標題"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.appcompat.widget.Toolbar>
可以直接在Toolbar里面添加一個TextView,這個TextView中設置 android:layout_gravity="center"
。
9、alertDialog
AlertDialog. Builder builder = new AlertDialog Bider(context);構建Dialog的各種參數
public void showDialog(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.mipmap.ic_launcher)
.setTitle("我是對話框")
.setMessage("今天天氣怎么樣")
.create()
.show();
}
這些set方法返回都是一個builder,所以我們可以用鏈式結構,但是create返回值是alertdialog,show又是dialog這個類里面的方法,所以我們把show放在create后面。
添加按鈕:
//設置確定按鈕
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e("hello","onclick:點擊了確定");
}
})
//設置取消按鈕
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e("hello","onclick:點擊了取消");
}
})
//設置中間按鈕
.setNeutralButton("中間", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e("hello","onclick:點擊了中間");
}
})

設置布局:
新建一個dialog_view.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/purple_200">
<ImageView
android:src="@mipmap/ic_launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="哈哈,天氣很好~"/>
</LinearLayout>
將其設置為這個dialog的布局:
View dialogview = getLayoutInflater().inflate(R.layout.dialog_view,null);
.setView(dialogview)
