设置Dialog从底部弹出:
//设置Dialog从窗体底部弹出
Window dialogWindow = dialog.getWindow();
dialogWindow.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
dialogWindow.setAttributes(lp);
——————————————————————————————————————————————
隐式启动来分享:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, "镜花水月");
shareIntent.setType("text/plain");
startActivity(shareIntent);
——————————————————————————————————————————————
调用系统浏览器
Uri uri = Uri.parse("http://www.baidu.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
——————————————————————————————————————————————
65535问题:
Moudle下的build.gradle中defaultConfig节点下添加:
multiDexEnabled true
dependencies节点下添加:
compile 'com.android.support:multidex:1.0.1'
最后MyApplication中添加:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
——————————————————————————————————————————————
再按一次退出应用的提示:
/**
* 捕捉返回事件按钮并判断的两次点击事件的时间差
*
*/
private long exitTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0){
if(System.currentTimeMillis()-exitTime>2000){
Toast.makeText(MainActivity.this,"再按一次退出应用",Toast.LENGTH_SHORT).show();
exitTime=System.currentTimeMillis();
}else{
finish();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
——————————————————————————————————————————————
7.0安装apk:
private void installApk(File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(this, "包名.fileprovider", file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
startActivity(intent);
}
——————————————————————————————————————————————
根据Uri获取图片或者文件的路径
@SuppressLint("NewApi")
public class UriUtils {
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
*/
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}
——————————————————————————————————————————————
6.0权限用户拒绝后进入设置页面:
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivity(intent);
——————————————————————————————————————————————
打开手电筒:
private TextView tv_flashLight;//控制按钮(默认显示:打开)
private Camera camera;
private Camera.Parameters parameters;
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},0);//动态获取权限
//点击事件
tv_flashLight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
camera = Camera.open();
parameters = camera.getParameters();
if (tv_flashLight.getText().toString().equals("打开")){
tv_flashLight.setText("关闭");
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}else {
tv_flashLight.setText("打开");
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
camera.setParameters(parameters);
}
});
权限:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
——————————————————————————————————————————————
设置TextView超过多少字后显示省略号
关于网上最多的结果就是这样的:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:maxEms="4"
android:paddingLeft="20dp"
android:text="乌鲁木齐" />
比如上面的这个,我想实现“”乌鲁…“”经过测试发现,不是绝对的准确,这个与字体大小以及宽度等等也有一定的关系,我感觉最好的方法就是确定好字体大小和想预留几个汉字,最后进行适当的调试。
——————————————————————————————————————————————
自定义TabLayout字体大小:
先自定义一个style
<style name="MyTabStyle" parent="TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse">
<item name="android:textSize">16sp</item>
<item name="android:textAllCaps">true</item>
</style>
然后引用即可:
app:tabTextAppearance="@style/MyTabStyle"
——————————————————————————————————————————————
检测手机的通知和状态栏是否开启允许通知,不然推送了消息也不显示:
private boolean isNotificationEnabled(Context context) {
String CHECK_OP_NO_THROW = "checkOpNoThrow";
String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
ApplicationInfo appInfo = context.getApplicationInfo();
String pkg = context.getApplicationContext().getPackageName();
int uid = appInfo.uid;
Class appOpsClass = null;
/* Context.APP_OPS_MANAGER */
try {
appOpsClass = Class.forName(AppOpsManager.class.getName());
Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE,
String.class);
Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
int value = (Integer) opPostNotificationValue.get(Integer.class);
return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
检测某个Service是否正在运行:
public static boolean isServiceExisted(Context context, String className) {
ActivityManager activityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager
.getRunningServices(Integer.MAX_VALUE);
if (!(serviceList.size() > 0)) {
return false;
}
for (int i = 0; i < serviceList.size(); i++) {
ActivityManager.RunningServiceInfo serviceInfo = serviceList.get(i);
ComponentName serviceName = serviceInfo.service;
if (serviceName.getClassName().equals(className)) {
return true;
}
}
return false;
}
第二个参数:Service包名路径
——————————————————————————————————————————————
底部导航栏总是被输入框顶上去,很烦!有时在manifest中设置属性windowSoftInputMode然并卵,可以在代码中setContentView之前设置:getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
——————————————————————————————————————————————
动态代码设置shape颜色:
先设置样式,solid颜色为透明。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:bottomLeftRadius="5dp" android:topLeftRadius="5dp"/>
<solid android:color="#00000000"/>
</shape>
布局里background引用此样式,最后动态设置颜色即可:
GradientDrawable grad = (GradientDrawable)view.getBackground();
grad.setColor("颜色");
——————————————————————————————————————————————
遍历Map
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : map.entrySet()) {
sb.append(entry.getKey() + ":" + entry.getValue() + ",");
}
Log.e("-----sb",sb.toString());
遍历map,并对map进行删减操作
Iterator<Map.Entry<Integer, String>> iterator = imageUrlMapNew.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
if (entry.getValue().equals(picPath)) {
iterator.remove();
}
}
——————————————————————————————————————————————
密码框设置密码显示或者隐藏:
if (isChecked) { // 显示
passwordEditText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
showToast("显示");
} else {
passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
showToast("隐藏");
}
————————————————————————————————————————————
打开手机拨号页面和通讯录页面,别忘了先获取权限
//拨号
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);//跳转到拨号界面,手机号自动填充
Uri data = Uri.parse("tel:" + number);
intent.setData(data);
startActivity(intent);
//通讯录
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
startActivityForResult(intent, OPEN_CONTACTS);
然后onActivityResult回调
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == OPEN_CONTACTS) {
try {
JSONObject contactObj = ContactUtil.getContact(this, data.getData());
Log.e("==name:", contactObj.optString("username"));
Log.e("==phone:", contactObj.optString("phoneNumber"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
——————————————————————————————————————————————————————————
1、获取系统当前时间(以年月日为例):yyyy-MM-dd对应格式:2017-01-01,根据需求自己改变格式
public String getDate() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(new Date());
}
——————————————————————————————————————————————————
设置EditText软键盘显示搜索按钮,自动弹出软键盘:
显示搜索按钮,xml的editText设置2行即可:
android:imeOptions="actionSearch"
android:singleLine="true"
设置EditText显示多行:
android:layout_height="100dp"//设置一个固定高度
android:inputType="textMultiLine"
android:gravity="top"//让输入内容从左上角开始
事件监听:
searchText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_SEARCH) {
SoftInputUtil.hideSoftInput(MainActivity.this, searchText);
Log.e("==search",v.getText().toString());
}
return true;
}
});
public class SoftInputUtil {
public SoftInputUtil() {
}
public static void showSoftInput(Context context) {
InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, 2);
}
public static void hideSoftInput(Context context, View view) {
InputMethodManager immHide = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
immHide.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
——————————————————————————————————————————————————
1、设置EdiText的光标的颜色以及大小:
添加属性:
android:textCursorDrawable="@drawable/color_cursor"
自定义一个光标color_cursor:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:width="1.5dp" />
<solid android:color="#7B3A94" />
</shape>
————————————————————————————————————————————————————————————
2、让EditText默认事先失去焦点,不让光标闪动:
找到EditText的父控件设置:
android:focusable="true"
android:focusableInTouchMode="true"
———————————————————————————————————————————————————————————
3、ListView设置空View:
if(addressAdapter==null||addressAdapter.isEmpty()){
View empityView = View.inflate(this,R.layout.empty,null);
((ViewGroup) delivery_address_listView.getParent()).addView(empityView, delivery_address_listView.getLayoutParams());
delivery_address_listView.setEmptyView(empityView);
}
—————————————————————————————————————————————————————————
4、强制所有页面竖屏:
可以在你的基类里添加:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
——————————————————————————————————————————————————————————
5、TextView设置下划线:
textView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG );
textView.getPaint().setAntiAlias(true);
——————————————————————————————————————————————————————————
7.系统AlertDialog设置按钮字体颜色大小(非自定义Dialog):
private AlertDialog dialog;
public void showDialog(View view){
dialog = new AlertDialog.Builder(this).create();
dialog.setMessage("确定要删除?");
dialog.setButton(AlertDialog.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"删除",Toast.LENGTH_SHORT).show();
}
});
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
//注意:设置的这些属性(字体颜色、大小)都要在show之后,不然报空指针
Button btnPositive = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button btnNegative = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
btnPositive.setTextColor(Color.parseColor("#7B3A94"));
btnNegative.setTextColor(Color.parseColor("#7B3A94"));
}
——————————————————————————————————————————————————————————
8.SpannableString设置String给TextView分段显示不同的颜色:
String price = "售价: ¥585";
比如我想让前面的“售价:”显示的是黑色,后面的价格“¥585”显示的是红色
就可以在item中设置TextView的时候字体颜色先全部设置成红色
然后在adapter中绑定数据的时候设置
SpannableString ss_price= new SpannableString(price);
ss_price.setSpan(new ForegroundColorSpan(Color.parseColor("#131313")),0,3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//设置文本的前景色
item.wine_selling_price.setText(ss_price);
————————————————————————————————————————————————————————————
9、Android系统为了跟IOS不一样,当界面OverScroll的时候会显示一个阴影。为了达到更好的显示效果,最好禁用系统的overScrollMode,如根布局添加android:overScrollMode=”never”
————————————————————————————————————————————————————————————
10、关于字节byte、进制以及IP的转换问题
/**
* byte字节数组转换成16进制
*/
public String toHexString(byte[] bytes) {
BigInteger bigInteger = new BigInteger(1, bytes);
return bigInteger.toString(16);
}
/**
* 16进制转IP
*/
public String HEXToIp(String hex){
//要先将其转换成10进制long整型,再转换成ip;
return longToIP(Long.parseLong(hex,16));
}
/**
* 10进制long类型整数,转换为 IP
*/
public String longToIP(long longIp) {
StringBuffer sb = new StringBuffer("");
// 直接右移24位
sb.append(String.valueOf((longIp >>> 24)));
sb.append(".");
// 将高8位置0,然后右移16位
sb.append(String.valueOf((longIp & 0x00FFFFFF) >>> 16));
sb.append(".");
// 将高16位置0,然后右移8位
sb.append(String.valueOf((longIp & 0x0000FFFF) >>> 8));
sb.append(".");
// 将高24位置0
sb.append(String.valueOf((longIp & 0x000000FF)));
return sb.toString();
}
/**
* Ip 转换为 long类型 10 进制整数
*/
public Long ipToLong(String ipString) {
Long[] ip = new Long[4];
int pos1= ipString.indexOf(".");
int pos2= ipString.indexOf(".",pos1+1);
int pos3= ipString.indexOf(".",pos2+1);
ip[0] = Long.parseLong(ipString.substring(0 , pos1));
ip[1] = Long.parseLong(ipString.substring(pos1+1 , pos2));
ip[2] = Long.parseLong(ipString.substring(pos2+1 , pos3));
ip[3] = Long.parseLong(ipString.substring(pos3+1));
return (ip[0]<<24)+(ip[1]<<16)+(ip[2]<<8)+ip[3];
}
/**
* 将16进制Id转换成10进制Id
*/
private String SixTeenToTen(String each_collecter) {
String eachId = each_collecter.substring(0, 8);
String a = eachId.substring(0, 2);
String b = eachId.substring(2, 4);
String c = eachId.substring(4, 6);
String d = eachId.substring(6, 8);
return String.valueOf(Integer.parseInt(a, 16) + Integer.parseInt(b, 16) * 256 +
Integer.parseInt(c, 16) * 256 * 2 + Integer.parseInt(d, 16) * 256 * 3);
}
———————————————————————————————————————————————————————————
12、ListView定位问题:
当打开列表的其中一项,然后返回时 需要定位到之前滚动到的位置
private int index;
private int top;
//在列表点击事件setOnItemClickListener里记录滚动到的位置
index = listView.getFirstVisiblePosition();
View v = listView.getChildAt(0);
top = (v == null) ? 0 : v.getTop();
//当返回时,再恢复到原来的位置
listView.setSelectionFromTop(index, top);
———————————————————————————————————————————————————————————
13、ListView点击item中的子控件,需获取当前点击item的position:有些容易获取,直接用getView()中的position就行,有些就不行,比如item中有Spinner控件,如何判断是点击的那个item中的Spinner呢
在Adapter的getView()方法中绑定数据的地方设置Tag,item.spinner.setTag(position);
最后在子控件的点击事件setOnItemSelectedListener中再取出position就行了:
itemPosition = (int) parent.getTag()
itemPosition就跟列表中的position对应。
———————————————————————————————————————————————————————————
13、Home键的监听:
@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
Log.e("-----Home","应用进入后台");
}
———————————————————————————————————————————————————————————
14、实现横向和纵向虚线,都是通过shape样式来实现
横向比较简单:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line">
<stroke android:width="1dp" android:dashGap="2dp" android:dashWidth="2dp" android:color="#f00"/>
</shape>
然后布局里引用即可:
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layerType="software"
android:background="@drawable/dot_line_horizontal"/>
注意两点:1、该view高度不能小于样式中的width。2、添加android:layerType=”software”,不然显示实线。
下面看竖线,竖线主要就是比横线多了一个旋转。
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="90"
android:toDegrees="90">
<shape android:shape="line">
<stroke android:width="1dp" android:color="#f00" android:dashGap="2dp" android:dashWidth="2dp" />
</shape>
</rotate>
然后布局引用:
<View
android:layout_width="match_parent"
android:layout_height="30dp"
android:layerType="software"
android:background="@drawable/dot_line_vertical"/>
这里也要额外注意一点:width宽度为啥是铺满全屏,因为这里的宽度是旋转前的线条长度,并不是旋转后的,当然heigth是旋转后显示后的竖线条的高度,理解这一点就可以了。