一 二級列表(ExpandableListView)
1.1 死數(shù)據(jù)步驟:
①創(chuàng)建布局找控件
②數(shù)據(jù)源(兩個集合:groupLists, childLists:泛型是<ArrayList<String>>)
③創(chuàng)建適配器:自定義一個類繼承自:BaseExpandableListAdapter
并重寫十個方法 注意:如果想要子條目實現(xiàn)點擊事件監(jiān)聽適配器中isChildSelectable方法設(shè)置為true
④設(shè)置適配器
1.2 Elv監(jiān)聽:
//父條目點擊事件監(jiān)聽
elv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Toast.makeText(MainActivity.this, grouplist.get(groupPosition), Toast.LENGTH_SHORT).show();
return false;
}
});
//子條目點擊事件監(jiān)聽 注意:適配器中isChildSelectable方法設(shè)置為true
elv.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Toast.makeText(MainActivity.this, childList.get(groupPosition).get(childPosition), Toast.LENGTH_SHORT).show();
return false;
}
});
//打開一個新的條目關(guān)閉其他條目
elv.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
int count = elv.getExpandableListAdapter().getGroupCount();
for (int i = 0; i < count; i++) {
if (i < groupPosition) {
elv.collapseGroup(i);
} else if (i > groupPosition) {
elv.collapseGroup(i);
}
}
}
});
二 側(cè)滑
2.1 側(cè)滑菜單
①添加依賴
(implementation'com.android.support:design:29.0.2')
②創(chuàng)建布局:
DrawerLayout、Toolbar厨钻、NavigationView(menu、header)
③設(shè)置actionbar:toolbar設(shè)置標(biāo)題、logo、關(guān)聯(lián)toolbar和側(cè)滑
④監(jiān)聽事件:頭部監(jiān)聽、側(cè)滑菜單監(jiān)聽蕾域、DrawerLayout脓杉、Home旋轉(zhuǎn)開關(guān)
⑤沉浸式狀態(tài)欄
//當(dāng)側(cè)滑的時候主界面跟隨 X 軸移動
dl.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
cl.setX(drawerView.getRight());
}
//此處省略三個方法......
}
2.2 選項菜單
①創(chuàng)建選項菜單(onCreateOptionsMenu)
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "線性布局").setIcon(R.mipmap.ic_launcher_round).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
return super.onCreateOptionsMenu(menu);
}
②選項菜單的點擊事件(onOptionsItemSelected)
③Fragment中加setHasOptionsMenu(true);
④使選項菜單內(nèi)容以標(biāo)題的樣式顯示在標(biāo)題上:
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
2.3 上下文菜單
①注冊上下文菜單(registerForContextMenu())
②創(chuàng)建上下文菜單(onCreateContextMenu)
③上下文菜單的點擊事件(onContextItemSelected)
Toolbar使用詳情
//側(cè)滑菜單item圖片顯示
nv.setItemIconTintList(null);
//設(shè)置 Logo
toolbar.setLogo(R.mipmap.logo);
// 設(shè)置主標(biāo)題
toolbar.setTitle("Title");
// 設(shè)置副標(biāo)題
toolbar.setSubtitle("Sub Title");
//設(shè)置toolbar糟秘,將Toolbar設(shè)置到界面上
setSupportActionBar(toolbar);
//左邊的小箭頭(注意某些版本api需要在setSupportActionBar(toolbar)之后才有效果)
toolbar.setNavigationIcon(R.mipmap.back);
//菜單點擊事件(注意需要在setSupportActionBar(toolbar)之后才有效果)
toolbar.setOnMenuItemClickListener(onMenuItemClick);
//點擊頭部
View headerView = nv.getHeaderView(0);
View iv = headerView.findViewById(R.id.iv);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點擊了頭部", Toast.LENGTH_SHORT).show();
}
});
//Home旋轉(zhuǎn)開關(guān)
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, dl, toolbar, R.string.app_name, R.string.app_name);
dl.addDrawerListener(toggle);
toggle.syncState();
android:fitsSystemWindows="true"
//在res文件夾下創(chuàng)建values-v21,復(fù)制styles.xml并添加屬性 注意:修改為.NoActionBar
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimary</item>
<item name="colorAccent">@color/colorAccent</item>
<!--透明狀態(tài)欄-->
<item name="android:statusBarColor">#00ffffff</item>
</style>
//選項菜單不遮蔽標(biāo)題欄
//1.在styles文件里編寫此代碼
<style name="OverflowMenuStyle" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
<item name="overlapAnchor">false</item>
</style>
//2.在toolbar中調(diào)用此方法:
android:theme="@style/OverflowMenuStyle"
三 RecyclerView
3.1 RecyclerView的使用步驟
①添加依賴(implementation 'com.android.support:recyclerview-v7:29.0.2')
②創(chuàng)建布局(寬、高必須充滿)
③找控件
④設(shè)置布局管理器(線性布局球散,網(wǎng)格布局和瀑布流)
⑤獲取數(shù)據(jù)(切換子線程的方法)
⑥創(chuàng)建適配器——重寫三個方法尿赚,通過接口回調(diào)實現(xiàn)點擊事件
⑦設(shè)置適配器
布局管理器:
//線性布局
rv.setLayoutManager(new LinearLayoutManager(this));
//網(wǎng)格布局
rv.setLayoutManager(new GridLayoutManager(this, 3));
//瀑布流
rv.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
3.2 接口回調(diào):
類A調(diào)用類B的方法b(),類B在回調(diào)類A的方法a(),期中方法a()是定義在接口中的,由類A來實現(xiàn),這是一個雙向調(diào)用的過程凌净。
//定義接口
public interface OnItemClickListener{
void onItemClick(int position);
}
//設(shè)置傳遞接口類實現(xiàn)對象的方法
private OnItemClickListeneronItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
//條目的監(jiān)聽事件
holder.itemView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View){
onItemClickListener.onItemClick(position);
}
});
3.3 RecyclerView多布局1:banner+recycleview
①RecyclerView基本使用
②定義類型常量
③重寫獲取條目根據(jù)位置分類的方法(getItemViewType)
④重寫onCreateViewHolder悲龟,根據(jù)類型創(chuàng)建不同的布局
⑤重寫onBindViewHolder,根據(jù)不同類型加載不同數(shù)據(jù)
-
注意:
①獲取條目總數(shù)(list.size()+1)
②onBindViewHolder:獲取列表條目數(shù)據(jù)的時候(position-1)
3.RecyclerView與ListView的對比
RecyclerView與ListView不同點
ListView:
①繼承BaseAdapter冰寻,需要重寫四個方法
②自定義ViewHolder與convertView的優(yōu)化(判斷是否為null)须教;
③可以直接使用item的點擊事件
④不用單獨設(shè)置分隔線
⑤不可以定向刷新某一條數(shù)據(jù)
RecyclerView:
①繼承RecyclerView.Adapter與RecyclerView.ViewHolder
②必須使用viewholder,封裝了view的復(fù)用
③設(shè)置LayoutManager,以及l(fā)ayout的布局效果
④點擊事件可以使用給控件設(shè)置點擊事件斩芭,也可以自定義點擊事件
⑤可以自定義繪制分隔線
⑥可以定向刷新某一條數(shù)據(jù)notifyItemChanged等方法
⑦可以自定義item刪除增加的動畫效果
3.4 RecyclerView多布局2:奇數(shù)位置左圖右文字+偶數(shù)位置左文字右圖片
①RecyclerView基本使用
②定義類型常量
③重寫獲取條目根據(jù)位置分類的方法(getItemViewType)
④重寫onCreateViewHolder
轻腺,根據(jù)類型創(chuàng)建不同的布局
⑤重寫onBindViewHolder
,根據(jù)不同類型加載不同數(shù)據(jù)
- 注意:不需要注意索引
3.5 RecyclerView通過接口回調(diào)實現(xiàn)點擊事件
①在adapter中定義一個內(nèi)部接口划乖,內(nèi)部接口定義一個方法贬养,方法參數(shù)是我們需要的返回的值;
②在adapter定義借口變量琴庵,并設(shè)置set方法误算;
③在onBindViewholder()
中,給條目做一個點擊事件
④在fragment或者activity對象調(diào)用點擊時間即可
3.6 RecyclerView下拉刷新上拉加載更多
①添加依賴
(implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0')
②在布局中添加刷新控件并找控件
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="wrap_content">
//下拉刷新
< com.scwang.smartrefresh.layout.header.ClassicHeader
android:layout_width="match_parent"
android:layout_height="match_parent">
//上拉加載更多
<com.scwang.smartrefresh.layout.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
③給刷新控件添加加載更多迷殿、下拉刷新添加監(jiān)聽儿礼,監(jiān)聽中寫具體代碼
//監(jiān)聽
srl.setOnRefreshLoadMoreListener(this);
//上拉加載更多
@Override
public void onLoadMore(@NonNull RefreshLayout refreshLayout){
page++;
//數(shù)據(jù)源
initData();
}
//下拉刷新
@Override
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
page = 1;
if (list != null && list.size() > 0) {
list.clear();
initData();
}
④刷新完畢列表,關(guān)閉SmartRefreshLayout頭和腳
srl.finishRefresh();
srl.finishLoadMore();
4 Fragment
4.1 Fragment的基本使用:
一贪庙、靜態(tài)創(chuàng)建fragment
①創(chuàng)建一個fragment
②創(chuàng)建布局蜘犁,把①中的fragment添加到布局中
- 注意:
①必須有設(shè)置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全名
4.2 動態(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();
4.3 Transaction常用方法
①add 添加
②remove 移除
③replace 替換
④hide 隱藏
⑤show 顯示
⑥attach 重建view視圖这橙,附加到UI上并顯示
⑦detach 會將view從UI中移除,和remove()不同,此時fragment的狀態(tài)依然由FragmentManager維護(hù)
⑧commit 提交事務(wù)
4.4 fragment生命周期
①onAttach() 當(dāng)Fragment與Activity發(fā)生關(guān)聯(lián)時調(diào)用
②onCreate()
③onCreateView() 創(chuàng)建該Fragment的視圖
④onActivityCreated() 當(dāng)Activity的onCreate方法返回時調(diào)用
⑤onStart()
⑥onResume()
⑦onPause()
⑧onStop()
⑨onDestroyView() 與onCreateView想對應(yīng),當(dāng)該Fragment的視圖被移除時調(diào)用
⑩onDestroy()
?onDetach() 與onAttach相對應(yīng)导披,當(dāng)Fragment與Activity關(guān)聯(lián)被取消時調(diào)用
4.5 fragment傳遞數(shù)據(jù)到activity
①獲取activity對象屈扎,調(diào)方法
//獲取getActivity(),強(qiáng)轉(zhuǎn)成MainActivity
MainActivity activity = (MainActivity) getActivity();
activity.getMsgFromFramgent("我是來自fragment的數(shù)據(jù)");
② 接口回調(diào)傳遞數(shù)據(jù)
Java接口與接口回調(diào)在Android中的使用
③通過fragment的有參構(gòu)造傳遞數(shù)據(jù)(不推薦)
4.6 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");
4.7 fragment與fragment之間傳遞數(shù)據(jù)
①通過構(gòu)造方式傳值(不推薦)
②通過FragmentManager找到對應(yīng)id或者Tag的Fragment撩匕,然后獲取里面的數(shù)據(jù)或者方法
③通過它們所在的Activity作為橋梁鹰晨,可以使用getActivity()或者接口回調(diào),達(dá)到獲取另一個Fragment數(shù)據(jù)的目的
4.8 RedioGroup底部導(dǎo)航結(jié)合Fragment切換
//創(chuàng)建布局找控件
fl_container = (FrameLayout) findViewById(R. id.fl_ container);
rb_a = (RadioButton) findViewById(R.id.rb_a);
rb_b = (RadioButton) findViewById(R.id.rb_b);
rg = (RadioGroup) findViewById(R. id.rg);
//獲取碎片管理器
fm = getSupportFragmentManager();
//開啟一個事物
FragmentTransaction fragmentTransaction = fm. beginTransaction();
aFragment = new AFragment();
bFragment = new BFragment();
//添加fragment并提交事務(wù)
fragmentTransaction. replace(R.id.fl_container, aFragment). replace(R.id.fl_container, bFragment)
.hide(bFragment).show(aFragment).commit();
//給RedioGroup設(shè)置監(jiān)聽并通過switch case顯示和隱藏fragment
rg. set0nCheckedChangeListener(new RadioGroup . OnCheckedChangeListener() (
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_a:
fm.beginTransaction().show( aFragment).hide(bFragment).commit();
break;
case R.id.rb_b:
fm.beginTransaction().show( bFragment).hide(aFragment).commit();
break;
}
}
]);
五 ViewPager
5.1 ViewPager+tablayout
①創(chuàng)建布局并找控件
②獲取數(shù)據(jù)集合(存放圖片的集合)
③創(chuàng)建適配器(四個方法):
//數(shù)量
getCount()
//判斷添加的識圖是否是當(dāng)前的view
isViewFronObject()
//
instantiateItem()
//
destroyItem()
④設(shè)置適配器
5.2 Viewpager結(jié)合Fragment實現(xiàn)導(dǎo)航
①創(chuàng)建布局找控件
②獲取fragment的集合fragments
③創(chuàng)建適配器:
FragmentStatePagerAdapter和FragmentPagerAdapter的區(qū)別(布局多的用加state,
不知道的可以用加state,兩個內(nèi)部方法一樣)
④設(shè)置適配器
5.3 Banner使用詳情
/**
* banner使用
* 1.添加依賴(implementation 'com.youth.banner:banner:1.4.10')
* 2.創(chuàng)建布局并找控件
* 3.獲取網(wǎng)數(shù)據(jù)
* 4.banner設(shè)置圖片集合并調(diào)用start()方法
*/
runOnUiThread(new Runnable() {
@Override
public void run() {
ArrayList<String> images = new ArrayList<>();
ArrayList<String> titles = new ArrayList<>();
for (int i = 0; i < bannerBean.getData().size(); i++) {
images.add(bannerBean.getData().get(i).getImagePath());
titles.add(bannerBean.getData().get(i).getTitle());
}
//設(shè)置圖片集合
banner.setImages(images)
//設(shè)置圖片加載器
.setImageLoader(new ImageLoader() {
@Override
public void displayImage(Context context, Object path, ImageView imageView) {
Glide.with(context).load(path).into(imageView);
}
})
//設(shè)置標(biāo)題 直接設(shè)置無效必須設(shè)置BannerStyle
.setBannerTitles(titles)
//設(shè)置banner樣式
.setBannerStyle(BannerConfig.NUM_INDICATOR_TITLE)
//設(shè)置banner動畫
.setBannerAnimation(Transformer.DepthPage)
//設(shè)置間隔時間
.setDelayTime(500)
//啟動輪播
.start();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
5.4 TVF
①創(chuàng)建布局找控件
vp = (ViewPager) findViewById(R.id.vp);
tab = (TabLayout) findViewById(R.id.tab);
②創(chuàng)建兩個集合:fragments和titles
③創(chuàng)建適配器:
public class MyViewpagerAdapter extends FragmentPagerAdapter {
ArrayList<PageFragment> pageFragmentList;
public MyViewpagerAdapter(FragmentManager fm, List<PageFragment> pageFragmentList) {
super(fm);
this.pageFragmentList = pageFragmentList;
}
@Override
public Fragment getItem(int i) {
return pageFragmentList.get(i);
}
@Override
public int getCount() {
return pageFragmentList.size();
}
}
④ 設(shè)置適配器
⑤TV結(jié)合:tab.settupWithViewPager(vp);
⑥設(shè)置圖片選擇器:tab.getTabAt(0).setIcon();
5.5 TVF涉及到的懶加載(為了避免頁面預(yù)加載)
//重寫過時方法setUserVisibleHint
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//判斷頁面是否可見
if (isVisibleToUser) {
//如果頁面可見加載數(shù)據(jù)
initData();
} else {
if (list != null && list.size > 0) {
list. clear();
}
}
}
六 彈窗
6.1 Popupwindow
//加載pop的布局
View view = LayoutInflater .from(this). inflate(R.layout.pop1, root: null);
//創(chuàng)建PopupWindow 對象
PopupWindow pop = new PopupWindow(view, ViewGroup. LayoutParams . WRAP_ CONTENT, ViewGroup . LayoutParam . WRAP_ CONTENT);
//聚焦 如果想在pop上編輯框需要設(shè)置該屬性
pop.setFocusable(true);
//pop進(jìn)出場動畫
pop.setAnimationStyle(R.style.pop_animation);
//想要實現(xiàn)點擊外消失需要設(shè)置一個背景
pop.setBackgroundDrawable(new colorDrawable);
//點擊范圍外消失
pop.setOutsideTouchable(true);
//設(shè)置全屏陰影
backgroundAlpha(0.5f);
//把pop設(shè)置到控件上
//pop.showAsDropDown(tv_ address, 0, 0);
//把pop設(shè)置到布局上
pop.showAtLocation(cl, Gravity.CONTENT, 0, 0);
//設(shè)置全屏陰影
private void backgroundAlpha(float alpha) {
Window window = getWindow();
WindowManager. LayoutParams attributes = window . getAttributes( );
attributes.alpha = alpha;
window. setAttributes(attributes );
}
//pop監(jiān)聽
pop.setOnDi smissListener new PopupWindow . OnDismissListener() {
@Override
public void onDismiss() {
//恢復(fù)透明度
backgroundAlpha(1f);
}
});
//style文件
<style name= "pop_ animation">
//進(jìn)場動畫
<item name="android windowEnterAnimation">@anim/anim_ enter</item>
//出場動畫
<item name="android :windowExitAnimation">@anim/anim_ eixt</item>
</style>
//進(jìn)場動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns :android= "http://schemas.android.com/apk/res/android"
android : duration="1500">
<alpha
android : fromAlpha="0"
android:toAlpha="1.0" />
<translate
android : fromXDelta="100%p"
android : fromYDelta="100%p"
android: toXDelta="0"
android :toYDelta="0" />
</set>
//出場動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns :android= "http://schemas.android.com/apk/res/android"
android : duration="1500">
<alpha
android : fromAlpha="1.0"
android:toAlpha="0" />
<translate
android : fromXDelta="0"
android : fromYDelta="0"
android: toXDelta="100%p"
android :toYDelta="100%p" />
</set>
七 通知
7.1Notification 通知
//創(chuàng)建通知管理器
NotificationManager nm = (NotificationManager) getSystemService (Context.NOTIFICATION_SERVICE);
//兼容O系統(tǒng):Build.VERSION.SDK_INT得到當(dāng)前手機(jī)的版本
String channelId = "1";
String channelName = "lu";
if (Build.VERSION.SDK INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true);
channel.setLightColor(Color.RED);
nm.createNotificationChannel(channe);
}
//延時意圖
Intent intent = new Intent(this, Main2Activity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//創(chuàng)建通知對象
Notification notification = new NotificationCompat.Builder(this, channelId)
//通知三要素圖標(biāo)止毕,標(biāo)題模蜡,內(nèi)容
.setSmallIcon(R.mipmap.ic_Launcher round)
.setContentTitle("標(biāo)題")
.setContentText("內(nèi)容")
//設(shè)置延時意圖
.setContentIntent(pendingIntent)
.build();
//發(fā)送通知
nm.notify(hd: 1, notification);
八 權(quán)限
8.1 分類:
①普通權(quán)限:不需要動態(tài)獲取
②危險權(quán)限:需要動態(tài)獲取
8.2 九大危險權(quán)限
3C 3S L M P
①CALENDAR 日歷
②CAMERA 相機(jī)
③CONTACTA 聯(lián)系人
④SEMSORS 傳感器
⑤SMS 短信
⑥STORAGE 存儲
⑦LOCATION 位置
⑧MICROPHONE 麥克風(fēng)
⑨PHONE 電話
8.3 如何動態(tài)的獲取權(quán)限
①在清單文件里添加打電話權(quán)限
<uses-permission android:name="android.permission.CALL_PHONE"/>
②檢查權(quán)限
//檢查是否授權(quán)
private void checkPhonePermission(){
if (ActivityCompat . checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED){
callPhone();
} else{
//如果沒有授權(quán)請求該權(quán)限
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;
}
//打電話
private void callPhone() {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
8.4 通過第三方框架獲取權(quán)限
①添加依賴
implementation 'com.github.dfqin:grantor:2.5'
②使用
private void authorityGranter() {
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)容提供者
9.1 內(nèi)容提供者步驟
①創(chuàng)建內(nèi)容提供者
new→Other→Content Provider
(1)URI格式 Main里面的全類名+.內(nèi)容提供者類名
(2)手動創(chuàng)建內(nèi)容提供者:自定義一個類繼承自ContentProvider,并重寫方法
②在清單文件里注冊
<provider
android:name=".ClContentProvider"
android:authorities="com.lulu.contentproviderr.ClContentProvider"
android:enabled="true"
android:exported="true/>
③創(chuàng)建SQL數(shù)據(jù)庫 繼承自 SQLitemOpenHelper 并且建庫建表
④在內(nèi)容提供者里面的重寫onCreate中獲取數(shù)據(jù)庫對象并返回對象扁凛,并補齊里面的增刪改查方法
⑤創(chuàng)建第二個類contentresolver
//獲取內(nèi)容解析器
ContentResolver contentResolver=getContentResolver();
//獲取URI(通用資源標(biāo)識符)
Uri uri = Uri.parse("content://+清單文件中的authoriries+/+庫名");
// insert 插入方法
ContentValues contentValues = new ContentValues();
contentValues.put("數(shù)據(jù)庫字段", "內(nèi)容");
contentResolver.insert(uri, contentValues);
-
常用Uri:
短信:Telephony.Sms.CONTENT_URI
通訊錄: ContactsContract.CommonDataKinds.Phone.CONTENT_URI
圖片:MediaStore.Images.Media.EXTERNAL_CONTENT_URI
音頻:MediaStore.Audio.Media.ENTERNAL_CONTENT_URI
視頻:MediaStpre.Video.Media.ENTERNAL_CONTENT_URI
十 Service
10.1 Service生命周期
①startService生命周期:
onCreate()(開啟服務(wù))-→onStartCommand()(服務(wù)運行)-→onDestory()(停止服務(wù))
②bindService生命周期:
onCreate()(開啟服務(wù))-→onBind()(綁定服務(wù))-→onUnbind(解綁服務(wù))-→onDestory(停止服務(wù))
10.2 startService和bindService區(qū)別
1.啟動服務(wù)中使用StartService()方法來進(jìn)行方法的調(diào)用忍疾,調(diào)用者和服務(wù)之間沒有聯(lián)系,即使調(diào)用者退出了谨朝,服務(wù)依然在進(jìn)行,onCreate()- >onStartCommand()->onDestroy()卤妒,注意其中沒有onStart()甥绿,主要是被onStartCommand()方法給取代了,onStart方法不推薦使用了则披。
2.綁定服務(wù)中使用bindService()方法來綁定服務(wù)共缕,調(diào)用者和綁定者綁在一起,調(diào)用者一旦退出服務(wù)也就終止了onCreate()->onBind()->onUnbind()->onDestroy()士复。
10.3 Activity和Service之間的數(shù)據(jù)傳遞
1.數(shù)據(jù)從Activity和到Service
intent方式:startService和bindService都可以
2.數(shù)據(jù)從Activity到Service
IBinder方式:bindService
3.數(shù)據(jù)從Service到Activity
接口回調(diào)和廣播
十二.音樂播放器
12.1 MediaPlayer創(chuàng)建方式
① 使用 new MediaPlayer 對象的方式
MediaPlayer mp = new MediaPlayer();
② 使用create的方式
MediaPlayer mp = MediaPlayer.create(this,R.raw.test);
12.2 四種資源
① 用戶在應(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](https://links.jianshu.com/go?to=http%3A%2F%2Fmusic.163.com%2Fsong%2Fmedia%2Fouter%2Furl%3Fid%3D139894.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();
}
12.3 assets和raw資源文件夾的區(qū)別:
res/raw不可以有目錄图谷,而assets則可以有目錄結(jié)構(gòu),也就是assets目錄下可以再建立文件夾
12.4 結(jié)合SeekBar實現(xiàn)拖動播放音樂功能
//創(chuàng)建seekbar布局
//seekbar設(shè)置監(jiān)聽阱洪,在停止拖動中player.seekTo(seekBar.getProgress());
//更新seekbar:
private void updataProgress(){
new Thread(newRunnable(){
@Override
public void run(){
while(player.isPlaying()){
try{
Thread.sleep(1000);
seekbar_mp.setMax(player.getDuration());
seekbar_mp.setProgress(player.getCurrentPosition());
}catch(Exceptione){
e.printStackTrace();
}
}
}
}).start();
}
12.5 結(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());
}