前言
①方法:思路+案例、預(yù)習(xí)思路
②補充知識點:debug、代碼規(guī)范、約束布局
③學(xué)生講課:三四節(jié)課學(xué)生講課(學(xué)委--組長--組員):前一天通知,沒有就題庫
④小組PK:
提問搶答加分
檢查作業(yè)給對應(yīng)組加分
成為主持人的給對應(yīng)組加分

題庫
1.側(cè)滑、音樂、tvf、rv單布局、elv+點擊(√)
2.側(cè)滑、rv+刷新+點擊、pop、通知+延時意圖、選項菜單
3.側(cè)滑、tvf、多布局、打電話、webview
4.側(cè)滑、tvf、項目、刷新、webview
5.vp導(dǎo)航、tvf、banner+rv多布局、多布局(需要修改)
6.導(dǎo)航、tvf、九宮格+banner、二級列表、webview
7.側(cè)滑、tvf、rv多布局、選項菜單、pop、相冊跳轉(zhuǎn)替換圖片、service實現(xiàn)音樂播放
8.tvf、rv+banner多布局、選項菜單、數(shù)據(jù)庫、上下文菜單、pop、通知
9.側(cè)滑、tvf、banner+rv多布局、選項菜單、pop、點擊頭像替換圖片
10、tvf、二級列表、側(cè)滑菜單、toobar、cardview、項目
50個面試題
每天講解十五個面試題(一節(jié)課),剩余的時間學(xué)生記憶
4月2日:項目搭建,主要側(cè)滑和toobar
4月3日:題庫4、10,主要項目
4月7日:題庫1、3、6,主要音樂和九宮格、打電話
4月8日:題庫2、8,主要pop和通知(數(shù)據(jù)庫不講)
4月9日:題庫7、9,主要相冊替換和服務(wù)播放音樂
4月10日:題庫5、8,主要數(shù)據(jù)庫
4月13日:帶領(lǐng)大家做終極題1-15(給定時間學(xué)生練習(xí))
4月14日:帶領(lǐng)大家做終極題16-25
一、列表
二級列表(ExpandableListView)
①創(chuàng)建布局,找控件
②獲取數(shù)據(jù):死數(shù)據(jù)、網(wǎng)絡(luò)數(shù)據(jù)
③創(chuàng)建適配器:10個方法要掌握
④設(shè)置適配器
⑤父項、子項點擊事件
⑥基本屬性Listview手動、自動加載更多
(1)Listview
①創(chuàng)建布局,找控件
②獲取網(wǎng)絡(luò)數(shù)據(jù)
③創(chuàng)建適配器:兩個優(yōu)化(必會):convertView復(fù)用,避免重復(fù)找控件
④設(shè)置適配器
(2)Listview手動加載更多
①創(chuàng)建布局,找控件
②獲取網(wǎng)絡(luò)數(shù)據(jù)
③創(chuàng)建適配器:兩個優(yōu)化(必會)
④設(shè)置適配器
⑤給Listview添加一個footer
⑥點擊footer中button加載更多:page++,獲取數(shù)據(jù)
(3)Listview自動加載更多
①創(chuàng)建布局,找控件
②獲取網(wǎng)絡(luò)數(shù)據(jù)
③創(chuàng)建適配器:兩個優(yōu)化(必會)
④設(shè)置適配器
⑤定義一個變量isBottom表示是否滑到底部
⑥Listview設(shè)置滑動監(jiān)聽
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
/**
* 滑動狀態(tài)發(fā)生改變:如果滑到底部,加載更多,修改isBottom值
* @param view
* @param scrollState
* //scrollState 有三種類型
* 1.SCROLL_STATE_IDLE 手指未觸摸屏幕,且屏幕靜止
* 2.SCROLL_STATE_TOUCH_SCROLL 手指未離開屏幕滑動
* 3.SCROLL_STATE_FLING 手指使勁滑動屏幕,然后手指離開屏幕,屏幕仍在滾動
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case SCROLL_STATE_IDLE:
if (isBottom) {
page++;
initData();
isBottom = false;
}
break;
}
}
/**
* 滑動監(jiān)聽,判斷是否滑動底部,返回isBottom具體值
* @param view
* @param firstVisibleItem:可見頁面第一個條目小標(biāo)
* @param visibleItemCount:可見頁面數(shù)據(jù)個數(shù)
* @param totalItemCount:條目總數(shù)
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
isBottom = true;
} else {
isBottom = false;
}
}
});
二、菜單
側(cè)滑菜單
①添加依賴
②創(chuàng)建布局:DrawerLayout、NavigationView(三個屬性、menu)
③設(shè)置actionbar:toolbar設(shè)置標(biāo)題、logo、關(guān)聯(lián)toobar和側(cè)滑菜單
④監(jiān)聽事件:頭部監(jiān)聽、側(cè)滑菜單監(jiān)聽、DrawerLayout、代買開關(guān)側(cè)滑菜單
⑤沉浸式狀態(tài)欄選項菜單
①創(chuàng)建選項菜單(onCreateOptionsMenu):兩種方式-代碼和menu(showAsAction)
②選項菜單的點擊事件(onOptionsItemSelected):switch上下文菜單
①注冊上下文菜單:registerForContextMenu()
②創(chuàng)建上下文菜單:onCreateContextMenu()
③上下文菜單點擊事件:onContextItemSelected()
注意區(qū)別:
OptionsMenu是整個界面共用,ContextMenu是注冊給某個組件,此組件擁有此菜單,沒有注冊的組件沒此菜單。補充:fragment怎么顯示選項菜單??
三、RecyclerView
RecyclerView基本使用
①添加依賴(版本問題注意)
②創(chuàng)建布局(寬高必須是充滿的)
③找控件
④設(shè)置布局管理器(三種顯示方式:線性布局、網(wǎng)格布局、瀑布流布局)
⑤獲取數(shù)據(jù)(切換子線程的方法)
⑥創(chuàng)建適配器-- 重寫三個,通過接口回調(diào)實現(xiàn)點擊事件
⑦設(shè)置適配器RecyclerView多布局一:list+banner
① RecyclerView基本使用
②定義類型常量
③重寫方法getItemViewType()根據(jù)位置返回不同類型
④重寫oncreateViewHolder()根據(jù)不同類型加載不同的布局
⑤重寫onBindViewHolder()根據(jù)不用類型加載不同數(shù)據(jù)
- 注意
①獲取條目總數(shù):list.size()+1
②onBindViewHolder:獲取別表條目數(shù)據(jù)的時候,position-1
- RecyclerView多布局二:奇數(shù)位置左圖右文字+偶數(shù)位置左文字右圖片
① RecyclerView基本使用(看6)
②定義類型常量
③重寫方法getItemViewType()根據(jù)位置返回不同類型
④重寫oncreateViewHolder()根據(jù)不同類型加載不同的布局
⑤重寫onBindViewHolder()根據(jù)不用類型加載不同數(shù)據(jù)
- 注意:沒有7中注意
RecyclerView通過接口回調(diào)實現(xiàn)點擊事件
①在adapter定義一個內(nèi)部接口,內(nèi)部接口定義一個方法,方法參數(shù)是我們需要返回值的;
②在adapter定義接口變量,并設(shè)置set方法
③在onBindVIewholder()中,給條目做一個點擊事件
④在fragment或者activity中,使用adapter對象調(diào)用點擊事件即可RecyclerView添加刷新
①添加依賴
②在布局中添加刷新的控件并找控件
③給刷新控件添加加載更多、下拉刷細(xì)膩添加監(jiān)聽,監(jiān)聽中寫具體代碼
④刷新完畢列表,關(guān)閉SmartRefreshLayout頭和腳。
四、fragment
- 靜態(tài)添加fragment
①創(chuàng)建一個fragment
②創(chuàng)建布局,把①中的fragment放到布局中
- 注意:
①必須要有id,否則:Caused by: java.lang.IllegalArgumentException: Binary XML file line #9: Must specify unique android:id, android:tag, or have a parent with an id for com.anfly.fragmentr.AFragment
②布局中必須添加屬性name,值該fragment全類名
- 動態(tài)添加fragment
//獲取碎片管理器
FragmentManager fm = getSupportFragmentManager();
//開啟事務(wù)
FragmentTransaction fragmentTransaction = fm.beginTransaction();
//獲取fragment對象
AFragment aFragment = new AFragment();
//替換容器中內(nèi)容
fragmentTransaction.replace(R.id.fl_container, aFragment);
//提交事務(wù)
fragmentTransaction.commit();
Transaction常用方法
①add
②remove
③replace
④hide
⑤show
⑥attach
⑦detach
⑧commitfragment生命周期
①onAttach()
②onCreate()
③onCreateView()
④onActivityCreated()
⑤onStart()
⑥onResume()
⑦onPause()
⑧onStop()
⑨onDestroyView()
⑩onDestroy()
?onDetach()fragment傳遞數(shù)據(jù)到activity
①獲取activity對象,直接調(diào)用方法
MainActivity activity = (MainActivity) getActivity();
activity.getMsgFromFramgent("我是來自fragment的數(shù)據(jù)");
②接口回調(diào)傳遞數(shù)據(jù)
Java接口與接口回調(diào)在Android中的使用
③通過fragment的有參構(gòu)造傳數(shù)據(jù)(不推薦)
- activity傳遞數(shù)據(jù)到fragment
①通過bundle方式傳值
activity中:
AFragment aFragment = new AFragment();
Bundle bundle = new Bundle();
bundle.putString("a", "我是來自activity的數(shù)據(jù)");
aFragment.setArguments(bundle);
fragment中:
Bundle bundle = getArguments();
String a = bundle.getString("a");
fragment與fragment之間傳遞數(shù)據(jù)
①通過構(gòu)造方式傳值(不推薦)
②通過FragmentManager找到對應(yīng)Id或者Tag的Framgment,然后獲取里面的數(shù)據(jù)或方法
③通過它們所在的Activity作為橋梁,可以使用getActivity()或者接口回調(diào),達(dá)到獲取另一個Fragment數(shù)據(jù)的目的.RadioGroup底部導(dǎo)航結(jié)合Fragmentr切換
五、ViewPager+tablayout
- ViewPager結(jié)合view實現(xiàn)導(dǎo)航
①創(chuàng)建布局找控件
②獲取數(shù)據(jù)集合
③創(chuàng)建適配器:
getCount()
isViewFromObject()
instantiateItem()
destroyItem()
④設(shè)置適配器
Viewpager結(jié)合Fragment實現(xiàn)導(dǎo)航
①創(chuàng)建布局找控件
②獲取fragment的集合fragments
③創(chuàng)建適配器:FragmentStatePagerAdapter和FragmentPagerAdapter區(qū)別以及內(nèi)部方法
④設(shè)置適配器Banner開源框架
官方
banner
.setBannerStyle(BannerConfig.NUM_INDICATOR_TITLE)//設(shè)置風(fēng)格
.setImages(images)//設(shè)置圖片集合
.setBannerAnimation(Transformer.DepthPage)//設(shè)置動畫
.setBannerTitles(titles)//直接添加無效,必須設(shè)置BannerStyle
.setImageLoader(new GlideImageLoader())//圖片加載器
.start();
Tablayout
①屬性TVF
①創(chuàng)建布局找控件:TV
②創(chuàng)建兩個集合:fragments和titles
③創(chuàng)建適配器:四個方法(包含一個構(gòu)造)
④設(shè)置適配器
⑤TV結(jié)合:tab.setupWithViewPager(vp);
⑥設(shè)置圖片選擇器tab.getTabAt(0).setIcon()TVF涉及到的懶加載 -- 為了避免預(yù)加載
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
initData();
} else {
if (list != null && list.size > 0) {
list.clear();
}
}
}
六、PopupWindow
①創(chuàng)建PopupWindow布局
②創(chuàng)建PopupWindow對象,用三個參數(shù)的構(gòu)造
③PopupWindow四種顯示方式
④聚焦:EditText能輸入內(nèi)容
⑤點擊范圍外關(guān)閉PopupWindow
⑥全屏陰影,PopupWindow點擊消失監(jiān)聽
⑦進(jìn)出場動畫
七、Notification
①獲取通知管理器getSystemService
②兼容O版以上系統(tǒng)
③獲取通知對象(構(gòu)建者模式):必要屬性有三項
④用通知管理器發(fā)送通知
⑤延時意圖:intent、pendingIntent、setContentIntent
⑥通知提示:聲音、震動、呼吸燈、全部
八、權(quán)限
- 分類
①普通權(quán)限:不需要動態(tài)獲取
②危險權(quán)限:需要動態(tài)獲取 - 危險權(quán)限分類
3CSLMP - 如何動態(tài)獲取權(quán)限
①在清單列表寫上需要的全下你
②檢查是否授權(quán)
如果授權(quán) -> 操作
如果沒有授權(quán) -> 請求權(quán)限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 100);
}
③請求權(quán)限結(jié)果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 100:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
Toast.makeText(MainActivity.this, "授權(quán)失敗", Toast.LENGTH_SHORT).show();
}
break;
}
}
- 通過框架獲取危險權(quán)限
①添加依賴implementation 'com.github.dfqin:grantor:2.5'
②使用
PermissionsUtil.requestPermission(this, new PermissionListener() {
@Override
public void permissionGranted(@NonNull String[] permission) {
callPhone();
}
@Override
public void permissionDenied(@NonNull String[] permission) {
Toast.makeText(MainActivity.this, "授權(quán)失敗", Toast.LENGTH_SHORT).show();
}
}, Manifest.permission.CALL_PHONE);
九、內(nèi)容提供者
- ContentProvider
①創(chuàng)建一個數(shù)據(jù)庫及一張表
②自定義ContentProvider繼承自ContentProvider,重寫方法 - ContentResolver
①獲取ContentResolver
②獲取uri:Uri.parse("content://"+authorities+/+path)
Uri uri = Uri.parse("content://com.anfly.contentproviderr.ClContentProvider/cl");
3.ContentResolver讀取短信、通訊錄、圖片、音頻、視頻
①動態(tài)獲取危險全新
②獲取ContentResolver對象contentResolver
③contentResolver調(diào)用query()方法查詢相關(guān)內(nèi)容
短信:Telephony.Sms.CONTENT_URI
通訊錄:ContactsContract.CommonDataKinds.Phone.CONTENT_URI
圖片:MediaStore.Images.Media.EXTERNAL_CONTENT_URI
音頻:MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
視頻:MediaStore.Video.Media.EXTERNAL_CONTENT_URI
十、Service
- service概述、應(yīng)用場景
- startService生命周期
- bindService生命周期
- startService和bindService區(qū)別
- Activity和Service之間的數(shù)據(jù)傳遞
①數(shù)據(jù)從Activity和到Service
intent方式:startService和bindService都可以
②數(shù)據(jù)從Activity到Service
IBinder方式:bindService
③數(shù)據(jù)從Service到Activity
接口回調(diào)和廣播
十一、音樂播放器
- MediaPlayer創(chuàng)建方式
①MediaPlayer mp = new MediaPlayer();
②MediaPlayer mp = MediaPlayer.create(this, R.raw.test); - 四種資源
①用戶在應(yīng)用中事先自帶的resource資源
例如:MediaPlayer.create(this, R.raw.test);
②存儲在SD卡或其他文件路徑下的媒體文件
例如:mp.setDataSource("/sdcard/test.mp3");
③網(wǎng)絡(luò)上的媒體文件
例如:mp.setDataSource("http://music.163.com/song/media/outer/url?id=139894.mp3");
④assets目錄下文件
AssetManager assets = getAssets();
try {
AssetFileDescriptor assetFileDescriptor = assets.openFd("qinghuaci.mp3");
player.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
- assets 和 raw 資源文件夾區(qū)別
- 結(jié)合SeekBar實現(xiàn)拖動播放音樂功能
①創(chuàng)建seekbar布局
②seekbar設(shè)置監(jiān)聽,在停止拖動中player.seekTo(seekBar.getProgress());
③更新seekbar:
private void updataProgress() {
new Thread(new Runnable() {
@Override
public void run() {
while (player.isPlaying()) {
try {
Thread.sleep(1000);
seekbar_mp.setMax(player.getDuration());
seekbar_mp.setProgress(player.getCurrentPosition());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
- 結(jié)合RecyclerView實現(xiàn)音樂播放上一首,下一首功能
① 使用ContentResolver+recyclerview展示音樂列表
②條目點擊事件播放對應(yīng)的音樂
③點擊上一首、下一首
private void next() {
if (positon < list.size() - 1) {
positon++;
} else {
positon = 0;
}
player(list.get(positon).getPath());
}
private void pre() {
if (positon > 0) {
positon--;
} else {
positon = list.size() - 1;
}
player(list.get(positon).getPath());
}
- 結(jié)合Service實現(xiàn)后臺音樂播放功能
①創(chuàng)建一個服務(wù)AudioService
②服務(wù)中創(chuàng)建內(nèi)部類AudioBinder,類中有一個方法返回服務(wù)類
③在onCreate()初始化MediaPlayer對象
④創(chuàng)建一系列關(guān)于mp的方法:播放、暫停、繼續(xù)、停止、拖動
⑤在AudioActivity中綁定服務(wù),返回服務(wù)類的對象
⑥按鈕點擊事件:通過服務(wù)類對象調(diào)用其方法實現(xiàn)音頻播放
⑦seekbar進(jìn)度改變監(jiān)聽,把進(jìn)度傳給mp