android 5.0+
安卓运行时权限管理
当targetSdkVersion版本低于23时,程序可以再AndroidManifest.xml中配置所需权限,并在程序中直接使用权限。当sdk版本在23即android 6.0时部分权限需要在代码里即使获取,主要原因是android 6.0设置中提供了对应用的权限控制功能
主要权限如下:
身体传感器
日历
摄像头
通讯录
地理位置
麦克风
电话
短信
存储空间
如果用户在设置中关闭了这些权限在程序中就无法使用对应的功能而崩溃,我们所做的就是当程序需要相应权限时,判断当前系统版本如果是android 6.0以上(android 7.0已经开测,移除了GET_ACCOUNTS权限)需要去判断当前是否有 这些权限。方法:checkSelfPermission(Context,permission) (int)若返回值为packmananger.PERMISSION__GRANTED表示有权限 ,若返回packmanagr.PERMISSION_DENIED ,表示没有权限,此时就需要去即时申请权限了。 通过ActivityCompat.requestPermission()来请求权限
onRequestPermissionResult()回调来判断是否申请权限成功:
测试拨号功能,在安卓6.0系统上单单在清单文件中配置权限后实际上是权限默认是关闭的
`public class PhoneActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mEtPhoneNumber;
private Button mBtCall;
private final int REQUEST_CALL_PHONE_PERMISSION=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone);
mEtPhoneNumber=(EditText)findViewById(R.id.et_phone_number);
mBtCall=(Button)findViewById(R.id.bt_call);
mBtCall.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v==mBtCall)
{
String phoneNumber= mEtPhoneNumber.getText().toString().trim();
if(TextUtils.isEmpty(phoneNumber))
{
Toast.makeText(this,"号码不能为空!",Toast.LENGTH_SHORT).show();
}else{
//判断版本是否大于等于6.0
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M) {
//判断是否有呼叫权限
int permissionStatus= ContextCompat.checkSelfPermission(this, android.Manifest.permission.CALL_PHONE);
if(permissionStatus== PackageManager.PERMISSION_DENIED)
{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},REQUEST_CALL_PHONE_PERMISSION);
}
else{
call();
}
}else{
call();
}
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case REQUEST_CALL_PHONE_PERMISSION:
if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED)
{
call();
}
break;
}
}
private void call(){
String phoneNumber= mEtPhoneNumber.getText().toString().trim();
Intent callIntent=new Intent("android.intent.action.CALL", Uri.parse("tel:"+phoneNumber));
startActivity(callIntent);
}
}`
material design
SnackBar
使用起来很简单就像Toast一样 com.android.support.design包下。
Snackbar.make(v,”SnackBarTest!!!”,Snackbar.LENGTH_SHORT).show();
TexInputLayout
包 android.support.design
主要功能:提供更美观的输入框,当点击输入内容时会做优美的动画将hint内容设置到EditText上方。并支持错误提示 一个textinputlayout下只能有一个子view
通过getEditText获取子view,setHintTextAppearance()设置 提示样式、setError();来设置提示错误信息 、setError(null)清空信息 。setErrorEnabled()-true开启提示 false关闭提示,这个方法
对Edittext的padding有影响 如果不设置false的话一旦弹出错误信息即使消息清空也会占用一个空地,所以需要控制true或false来控制padding
部分代码
<android.support.design.widget.TextInputLayout
android:id="@+id/tl__password"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:inputType="textEmailAddress"
android:hint="密码"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
<Button
android:text="login"
android:id="@+id/bt_login"
android:layout_width="match_parent"
android:layout_height="50dp" />
java:
/**
* 处理密码输入域
*/
public void inputPassword(){
final EditText editText= mTlPassword.getEditText();
mTlPassword.setHintTextAppearance(R.style.hintStyle);
mBtLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(editText.getText().toString().trim().length()<5)
{
mTlPassword.setError("密码错误");
mTlPassword.setErrorEnabled(true);
}
else{
mTlPassword.setError(null);
mTlPassword.setErrorEnabled(false);
}
}
});
}
TabLayout
Google官方提供Viewpager 指示器 .
TabLayout.setupWithViewPager() 绑定Viewpager
TabLayout.setTabMode(); 来设置布局方式
使用一个集合存储标题 在适配器中的getPageTitle()方法根据页面下标返回标题
style :
<style name="tabStyle" parent="Widget.Design.TabLayout">
<item name="tabIndicatorColor">#7389ec</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">@style/textTitleStyle</item>
<item name="tabSelectedTextColor">#423fec</item>
</style>
java :
public class ViewPagerActivity extends AppCompatActivity {
private ViewPager mViewpager;
private TabLayout mTabLayout;
private ArrayList<Fragment>mFragments;
private String[]s={"音乐","电影"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
mViewpager=(ViewPager)findViewById(R.id.view_pager);
mTabLayout=(TabLayout)findViewById(R.id.tl_layout);
mFragments=new ArrayList<>();
Fragment blankFragment=new BlankFragment();
Fragment blankFragment2=new BlankFragment2();
mFragments.add(blankFragment);
mFragments.add(blankFragment2);
FragmentPagerAdapter fragmentPagerAdapter=new FragmentAdapter(getSupportFragmentManager());
mViewpager.setAdapter(fragmentPagerAdapter);
mTabLayout.setupWithViewPager(mViewpager);
mTabLayout.setTabMode(TabLayout.MODE_FIXED);
}
private class FragmentAdapter extends FragmentPagerAdapter{
public FragmentAdapter(FragmentManager fm) {
super(fm);
}
@Override
public CharSequence getPageTitle(int position) {
return s[position];
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
}
}
沉浸式状态栏
在android4.4后开始支持沉浸式状态栏
5.0修改状态栏颜色
通过设置getWindows.setStatusBarColor()和setNavigationBarColor()即可轻松修改状态栏和导航栏的颜色。(插:如果Activity继承的是AppCompatActivity那么如果在清单文件中设置theme为noTitleBar是会崩溃的,正确的用法是用AppCompat.Light.NoActionBar,才能去除标题栏)。这个只能在安卓5.0系统以上才支持,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.LOLLIPOP)
{
Window window=getWindow();
window.setStatusBarColor(getResources().getColor(R.color.colorPrimary));
window.setNavigationBarColor(getResources().getColor(R.color.colorPrimary));
}
setContentView(R.layout.activity_phone);
4.4系统以上使用的沉浸式
只需使用两句代码就能实现状态栏的透明样式
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT)
{
Window window=getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
//图
一个是Android 6.0一个是4.4,现在看起来样式已经大概实现了 但是别着急我们在xml布局顶部加入一个“header”你会发现布局也沉浸到了状态栏中,这个很容易解决只需要获取到状态栏高度并且设置一个padding给contentView即可。
View contentView=View.inflate(this,R.layout.activity_phone,null);
contentView.setPadding(0,getStatusBarHeight(),0,0);
setContentView(contentView);
/**
* 获取状态栏高度
*/
public int getStatusBarHeight(){
int result=0;
int resourceid=getResources().getIdentifier("status_bar_height","dimen","android");
if(resourceid>0)
{
result=getResources().getDimensionPixelSize(resourceid);
}
Toast.makeText(this,result+"resourceid:"+resourceid,Toast.LENGTH_SHORT).show();
return result;
}
//图
通过这种方式就能解决布局沉浸的问题。但是你现在可能发现4.4和6.0的状态栏透明度是不同的,6.0是半透明这个也能解决我们判断下版本是否大于等于5.0之后在进行设置 。
/**
* 5.0上状态栏改为全透明
*/
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
{
Window window=getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
//图
另外只需要在添加一行代码就能将导航栏也设为透明样式
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);