Android 问题整理 四

// Android限定EditText的输入类型为数字或者英文(包括大小写)

参考:Android限定EditText的输入类型为数字或者英文(包括大小写)

android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// shape 竖线

参考:Shark出品:Android Shape 实现 垂直 虚线

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <size
                android:width="2dp"
                android:height="@dimen/dp_60" />

            <stroke
                android:width="1.5dp"
                android:color="#FFCB9D"
                android:dashWidth="1.5dp"
                android:dashGap="1.5dp" />
        </shape>
    </item>
    <item android:left="0.5dp">
        <shape android:shape="rectangle">
            <solid android:color="#FFF5ED" />
        </shape>
    </item>

</layer-list>

// java 正则匹配方法

    public static boolean check(String string) {
        String regExp = "^1[3456789]{1}\\d{9}$"; // 正则表达式,这里展示的是手机号码,第一个数是1,第二个数不能是0和2 长度11位 纯数字
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(string);
        return m.find();
    }

// webview 闪退

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.AttributeSet;
import android.webkit.WebView;

public class LollipopFixedWebView extends WebView {

    public LollipopFixedWebView(Context context) {
        super(getFixedContext(context));
    }

    public LollipopFixedWebView(Context context, AttributeSet attrs) {
        super(getFixedContext(context), attrs);
    }

    public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(getFixedContext(context), attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
    }

    public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
        super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
    }

    public static Context getFixedContext(Context context) {
        if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23) // Android Lollipop 5.0 & 5.1
            return context.createConfigurationContext(new Configuration());
        return context;
    }
}

// logcat 格式化输出json

原文:https://blog.csdn.net/qingchunweiliang/article/details/51005676

import com.google.gson.Gson;

/**
 * json格式化工具
 * @author Young
 *
 */
public class JsonFormat {
 
    /**
     * 默认每次缩进两个空格
     */
    private static final String empty="  ";
 
    public static String format(Object json){
        if (json == null) {
            return "null";
        }
        String  jsonS = "{}";
        try {
            jsonS = new Gson().toJson(json);
            int empty=0;
            char[]chs=jsonS.toCharArray();
            StringBuilder stringBuilder=new StringBuilder();
            for (int i = 0; i < chs.length;) {
                //若是双引号,则为字符串,下面if语句会处理该字符串
                if (chs[i]=='\"') {
                    stringBuilder.append(chs[i]);
                    i++;
                    //查找字符串结束位置
                    for ( ; i < chs.length;) {
                        //如果当前字符是双引号,且前面有连续的偶数个\,说明字符串结束
                        if ( chs[i]=='\"'&&isDoubleSerialBackslash(chs,i-1)) {
                            stringBuilder.append(chs[i]);
                            i++;
                            break;
                        } else{
                            stringBuilder.append(chs[i]);
                            i++;
                        }
                    }
                }else if (chs[i]==',') {
                    stringBuilder.append(',').append('\n').append(getEmpty(empty));
                    
                    i++;
                }else if (chs[i]=='{'||chs[i]=='[') {
                    empty++;
                    stringBuilder.append(chs[i]).append('\n').append(getEmpty(empty));
                    
                    i++;
                }else if (chs[i]=='}'||chs[i]==']') {
                    empty--;
                    stringBuilder.append('\n').append(getEmpty(empty)).append(chs[i]);
                    
                    i++;
                }else {
                    stringBuilder.append(chs[i]);
                    i++;
                }
            }
            return stringBuilder.toString();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return jsonS;
        }
    }
    private static boolean isDoubleSerialBackslash(char[] chs, int i) {
        int count=0;
        for (int j = i; j >-1; j--) {
            if (chs[j]=='\\') {
                count++;
            }else{
                return count%2==0;
            }
        }
        return count%2==0;
    }
    /**
     * 缩进 
     * @param count
     * @return
     */
    private static String getEmpty(int count){
        StringBuilder stringBuilder=new StringBuilder();
        for (int i = 0; i < count; i++) {
            stringBuilder.append(empty) ;
        }
        return stringBuilder.toString();
    }
}

// RecyclerView 设置了GridLayoutManager 空白区域点击事件

原地址:https://blog.csdn.net/u013778491/article/details/92829738

recycle_foodl.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v.getId()!=0){
            //发现只有点击了空白处,v.getId,才能打印出东西
            //可以在此处做文章
            goodsAdapter.dimmMissll_edit();
        }
        return false;
    }
});

// recyclerview 的 item 中包含 recyclerview ,外层 recyclerview 无法滑动

外层 recyclerview 添加父布局 ScrollView

外层 recyclerview 的外层建议添加 RelativeLayout

内层 recyclerview 添加属性

android:nestedScrollingEnabled="false"

//USB调试不能弹出授权窗口 unauthorized 的解决办法

1.检查环境变量 https://blog.csdn.net/zhouzme/article/details/51471699

ANDROID_SDK_HOME

C:\Users\Administrator\AppData\Local\Android\Sdk

2.安装Total Control尝试连接

http://download.sigma-rt.com/tc/pc/Total_Control_7_0_0_u2640018_Install_x64.zip

// 读写权限都已经授权,但是还是出现 class java.io.FileNotFoundException: open failed: EACCES (Permission denied)错误

参考:https://blog.csdn.net/tm_6666/article/details/106792314

<application
    ...
    ...
    android:requestLegacyExternalStorage="true">
</application>

// 融云连接失败,可能是缺少 libsqlite.so 库

Android studio添加so文件

// 记录创建的 activity,与 finish() 记录中的 activity

public class ActivityManagerApplication extends Application {
    private static Map<String,Activity> destoryMap = new HashMap<>();
    /**
     * 添加到销毁队列
     *
     * @param activity 要销毁的activity
     */

    public   void addDestoryActivity(Activity activity, String activityName) {
        destoryMap.put(activityName,activity);
    }
    /**
     *销毁指定Activity
     */
    public   void destoryActivity(String activityName) {
        Set<String> keySet=destoryMap.keySet();
        for (String key:keySet){
            destoryMap.get(key).finish();
        }
    }
}
private ActivityManagerApplication activityManagerApplication = new ActivityManagerApplication();

activityManagerApplication.destoryActivity("SplashActivity");
activityManagerApplication.addDestoryActivity(this, "TabMainActivity");

// 隐藏软键盘,隐藏输入法

    private InputMethodManager imm;
	
	// public static final String INPUT_METHOD_SERVICE = "input_method"
        imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        

    public void hideInput() {
        if (getActivity() != null && getActivity().getCurrentFocus() != null && isInputMethodShow()) {
            imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
                    InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    public boolean isInputMethodShow() {
        return imm.isActive();
    }

// 获取 Assets 目录下指定文件的 AssetsFileDescriptor 对象

参考:https://blog.csdn.net/Greathfs/article/details/52123984

// 打开指定音乐文件,获取assets目录下指定文件的AssetFileDescriptor对象  
AssetFileDescriptor afd = am.openFd(music);  
mPlayer.reset();  
// 使用MediaPlayer加载指定的声音文件。  
mPlayer.setDataSource(afd.getFileDescriptor(),  
    afd.getStartOffset(), afd.getLength());  
// 准备声音  
mPlayer.prepare();  
// 播放  
mPlayer.start(); 

// Android 软键盘弹出时把布局顶上去或者覆盖上去需求解决方案

参考:https://blog.csdn.net/lvshuchangyin/article/details/73825933

 android:windowSoftInputMode="adjustPan"

        <activity
            android:name=".surface.activity.EditWorksActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustPan" />

// Android Studio 清除未使用的资源、未使用的文件、未使用的图片


// mvp 网络请求返回 5000 访问异常,请稍后重试

参考:Gson解析错误

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 22 path $.data


// 微信登录点击同意后报错

参考:android问题:You need to use a Theme.AppCompat theme (or descendant) with this activity.

You need to use a Theme.AppCompat theme (or descendant) with this activity.

当前 Activity 继承的 Activity 与清单文件中使用的主题所使用的的 Activity 的主题不一致。


// Parcelable encountered IOException writing serializable object

参考:https://blog.csdn.net/qq_32452623/article/details/51851002

要解析的实体类以及内部包含的所有实体类都要实现接口 Serializable


// Intent 传递对象 Activity 

    public static void startSelf(Activity context, boolean view, XXXBean bean, double radius) {
        Intent intent = new Intent(context, XXXActivity.class);
//        Bundle bundle = new Bundle(1);
//        bundle.putSerializable("xxx_bean", bean);
//        intent.putExtras(bundle);
        intent.putExtra("xxx_bean", bean);
        context.startActivityForResult(intent, 1);
    }

    XXXActivity.startSelf(this, false, mBean, radius);

    XXXBean mBean = (XXXBean) getIntent().getSerializableExtra("xxx_bean");

    int xxxSize = mBean.getXxxx().size();

// java 中文转Unicode 以及 Unicode转中文

参考:java 中文转Unicode 以及 Unicode转中文

  private static String unicodeToCn(String unicode) {
        /** 以 \ u 分割,因为java注释也能识别unicode,因此中间加了一个空格*/
        String[] strs = unicode.split("\\\\u");
        String returnStr = "";
        // 由于unicode字符串以 \ u 开头,因此分割出的第一个字符是""。
        for (int i = 1; i < strs.length; i++) {
            returnStr += (char) Integer.valueOf(strs[i], 16).intValue();
        }
        return returnStr;
    }

// ImageLoader 加载网络图片展示 加载本地图片展示

xbanner 相关用法:参考1 参考2

 XBanner xBanner = mItemView.findViewById(R.id.item_xbannerViewPager);
            xBanner.setPageTransformer(Transformer.Stack);
            xBanner.setBannerData(data.getImages());
            xBanner.loadImage(new XBanner.XBannerAdapter() {
                @Override
                public void loadBanner(XBanner banner, Object model, View view, int position) {
//                加载网络图片展示
                    ImageLoader.image(context, ((ImageView) view), ((HomePageBean.ImagesBean) model).getImage_url());

//                加载本地图片展示 不需要自定义
//                    ((ImageView) view).setImageResource((Integer) ((HomePageBean.ImagesBean) model).getXBannerUrl());
                }
            });
            xBanner.setAllowUserScrollable(false);
            xBanner.setPointsIsVisible(false);
            xBanner.setAutoPalyTime(1000);
            xBanner.setAutoPlayAble(false);
    /**
     * 加载网络图片
     */
    public static void image(Context context, ImageView imageView, String url) {
        Glide.with(checkContext(context))
                .load(checkUrl(url))
                .into(imageView);
    }

// fragment 可见与不可见

    // 解决华为手机,强制离线后无法重新获取首页数据的问题
    @Override
    public boolean getUserVisibleHint() {//切换到其他activity,再切换回来时执行
        presenter.getLocation();
        return super.getUserVisibleHint();
    }

    @Override// 点击我的后 hidden = true 点击首页 hidden = false
    public void onHiddenChanged(boolean hidden) {// 使用 show hide 方式切换 fragment,当前 fragment 可见时 hidden 为true
        super.onHiddenChanged(hidden);
        if (hidden) {
            stop();
        } else {
            presenter.getLocation();
            if (isAdded() && UserUtils.getInstance().isLogin()) {
                presenter.getMsgNum();
            }
            changePlay(indexBefore);
        }
    }

// dialog 、自定义 dialog 自动弹出输入法

参考:https://blog.csdn.net/liang5630/article/details/43482691

    public void onTextModeClick() {
        if (mTextDialog == null) {
            mTextDialog = new EditWorksTextDialog(this, this);
            mTextDialog.setOnShowListener(this);
            mTextDialog.setOnDismissListener(this);
        }
        mTextDialog.show();
        //设置可获得焦点
        mTextDialog.getViewEdit().setFocusable(true);
        mTextDialog.getViewEdit().setFocusableInTouchMode(true);
        //请求获得焦点
        mTextDialog.getViewEdit().requestFocus();
        InputMethodUtils.show(mTextDialog.getViewEdit());
    }

// dispatchTouchEvent 拦截、监听是否点击了某一个view

参考1:Android dispatchTouchEvent检测多点触摸事件是否落入在某一个View区域内

参考2:Android 判断触摸点是否在某个view的区域,解决子view与parent的touch事件冲突

@Override
    public boolean dispatchTouchEvent(MotionEvent event) {
            float x = event.getRawX();
            float y = event.getRawY();
 
            if (touchEventInView(text1, x, y)) {
                Toast.makeText(this, "text1", Toast.LENGTH_SHORT).show();
            }
 
            if (touchEventInView(text2, x, y)) {
                Toast.makeText(this, "text2", Toast.LENGTH_SHORT).show();
            }
 
        return super.dispatchTouchEvent(event);
    }


/**
     * 该方法检测一个点击事件是否落入在一个View内,换句话说,检测这个点击事件是否发生在该View上。
     *
     * @param view
     * @param x
     * @param y
     * @return
     */
    private boolean touchEventInView(View view, float x, float y) {
        if (view == null) {
            return false;
        }
 
        int[] location = new int[2];
        view.getLocationOnScreen(location);
 
        int left = location[0];
        int top = location[1];
 
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
 
        if (y >= top && y <= bottom && x >= left && x <= right) {
            return true;
        }
 
        return false;
    }

    //(x,y)是否在view的区域内
    private boolean isTouchPointInView(View view, int x, int y) {
        if (view == null) {
            return false;
        }
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        int left = location[0];
        int top = location[1];
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
        //view.isClickable() &&
        if (y >= top && y <= bottom && x >= left
                && x <= right) {
            return true;
        }
        return false;
    }
  

// 实现View的拖拽,拖动控件

public class MainActivity extends AppCompatActivity {

    private TextView text;
    double lastx;
    double lastY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        text = (TextView) findViewById(R.id.text);
        text.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                double x=event.getRawX();
                double y=event.getRawY();
//                Log.d(TAG, "onTouch: "+event.getAction());
                if (event.getAction()==MotionEvent.ACTION_DOWN){
                    lastx=x;
                    lastY=y;
                }else if (event.getAction()==MotionEvent.ACTION_MOVE){
                    double dx=x-lastx;
                    double dy=y-lastY;
//                    Log.d(TAG, "onTouch: dx=="+dx+",dy=="+dy);
//            startAnimation(dx,dy);

                    //  moveMethod1(dx, dy);
                    moveMethod2(dx, dy);

                    lastx=x;
                    lastY=y;
                }
//                text.setTranslationX(x);
                return true;
            }
        });
    }


    //根据属性动画的原理
    private void moveMethod2(double dx, double dy) {

        text.setTranslationX((float) (text.getTranslationX()+dx));
        text.setTranslationY((float) (text.getTranslationY()+dy));
    }

    //根据margin 原理
    private void moveMethod1(double dx, double dy) {
        ViewGroup.MarginLayoutParams marginLayoutParams= (ViewGroup.MarginLayoutParams) text.getLayoutParams();
        marginLayoutParams.leftMargin+=dx;
        marginLayoutParams.topMargin+=dy;
        text.setLayoutParams(marginLayoutParams);
    }

    private void startAnimation(double dx, double dy) {
        ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(text,"translationX", (float) (text.getTranslationX()+dx)).setDuration(3000);
        objectAnimator.start();

        ObjectAnimator objectAnimator2=ObjectAnimator.ofFloat(text,"translationY", (float) (text.getTranslationY()+dy)).setDuration(3000);
        objectAnimator2.start();
    }
}

// 包名,Android 获取当前屏幕上显示的 activity

参考:查看Android应用包名、Activity名

C:\Users\Administrator>adb shell dumpsys window | findstr mCurrentFocus
  mCurrentFocus=Window{614737a u0 cn.xuexi.android/com.alibaba.android.rimet.biz
.home.activity.HomeActivity}

C:\Users\Administrator>adb uninstall cn.xuexi.android
Success

C:\Users\Administrator>

// 隐藏华为手机虚拟按键,底部虚拟按键

参考:Android 隐藏底部虚拟键


    protected void hideBottomUIMenu() {
        //隐藏虚拟按键,并且全屏
        if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
            View v = this.getWindow().getDecorView();
            v.setSystemUiVisibility(View.GONE);
        } else if (Build.VERSION.SDK_INT >= 19) {
            //for new api versions.
            View decorView = getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(uiOptions);

        }
    }

// 启动第三方app工具类

/**
 * 描述: 启动第三方app工具类
 *
 * @author hujw
 * @date 2019/9/20 0020
 */
public final class LaunchAppUtils {
    /**
     * 这里是判断APP中是否有相应APP的方法
     *
     * @param context 上下文对象
     * @param packageName 需要跳转的app包名
     * @return
     */
    public static boolean isAppInstalled(Context context, String packageName) {
        try {
            context.getPackageManager().getPackageInfo(packageName, 0);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 启动第三方app
     */
    public static void launchApp(Context context,String appPackageName) {
        if (isAppInstalled(context, appPackageName)){
            context.startActivity(context.getPackageManager().getLaunchIntentForPackage(appPackageName));
        }else{
            ToastMaker.showShort("请先安装此App");
        }
    }
}

// Android studio 打包输出配置

 

    // 执行配置
    applicationVariants.all { variant ->

        // Apk 输出配置
        variant.outputs.all { output ->
            def appName = "Jwcy110"
            if (variant.buildType.name == 'debug') {
                outputFileName = appName + '_v' + versionName + '_' + variant.buildType.name + '.apk'
            } else {
                outputFileName = appName + '_v' + versionName + '_' + new Date().format("yyyyMMdd") + '_' + variant.buildType.name + '.apk'
            }
        }
    }

 

发表评论

zh_CNChinese
zh_CNChinese