开发中的小知识点汇总(持续更新)

设置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是旋转后显示后的竖线条的高度,理解这一点就可以了。

猜你喜欢

转载自blog.csdn.net/AndroidStudioo/article/details/52786268
今日推荐