Android应用开发常用知识(4)

2023-05-16

Android string 中product的使用

Android的资源文件string.xml会出现下面同名的字符串:

<string name="build_type" product="tv">"智能电视"</string>
<string name="build_type" product="tablet">"平板电脑"</string>
<string name="build_type" product="default">"智能手机"</string>

不同的product就会取不同的值。
注意不要把default放在第一个,否则会编译不过。
product的值在对应的device目录下的mk文件当中有定义:

PRODUCT_CHARACTERISTICS := tv

Android 横屏解锁引起Activity销毁重建

Activity设置为竖屏

android:screenOrientation="portrait"

桌面是可以横竖屏切换的,竖屏锁屏,横屏下解锁会引起Activity销毁,这个时候也要设置一下

android:configChanges="screenSize|keyboardHidden|orientation"

解决重复点击问题

private long mLashClick;


        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                long now = SystemClock.uptimeMillis();
                if(now - mLashClick > 500){
                    mLashClick = now;
                    //do something;
                }
            }
        });

自定义Toolbar style解决Toolbar位置问题

    <style name="AppTheme">
	……
        <item name="toolbarStyle">@style/MyToolbarStyle</item>
        ……
    </style>

    <style name="MyToolbarStyle" parent="Widget.AppCompat.Toolbar">
        <item name="contentInsetStart">@dimen/toolbar_content_inset</item>
        <item name="contentInsetEnd">@dimen/toolbar_content_inset</item>
    </style>

Activity实现180旋转

android:screenOrientation="fullUser"

Android:includeFontPadding

TextView中用来设置文本框是否包含顶部和底部留白(左右两侧默认没有留白),将其设置为false,TextView就会取消2px的留白

Fragment切换时使用不同的OptionsMenu

onCreate中调用setHasOptionsMenu(true);,在每个Fragment中重写public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)来实现;

LinearLayout添加分隔线

可以放置一个ImageView组件,然后将其设为分隔线的颜色或图形。

android:showDividers

在 Android3.0及以上版本,LinearLayout支持直接显示分隔线。设置标签的 android:showDividers属性可以在LinearLayout的相应位置显示分隔线。如果有多个LinearLayout,显示效果和在 LinearLayout之间加分隔线是一样的。
android:showDividers属性可以设置如下4个值:

  • none:不显示分隔线;
  • beginning:在LinearLayout的开始处显示分隔线;
  • end:在Linearlayout的结尾处显示分隔线;
  • middle:在LinearLayout中的每两个组件间显示分隔线:

除了需要设置android:showDividers属性外,还要设置android:divider属性,该属性表示分隔线的图像,需要一个Drawable ID。

添加快捷方式

   public void addShortCut(){
        Intent addShortCut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");

        //快捷方式的名称
        addShortCut.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Test");

        // 不允许重复创建
        addShortCut.putExtra("duplicate", false);
        addShortCut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(MainActivity.this,
                R.mipmap.ic_launcher));

        // 设置关联程序
        //启动MainActivity
        //设置action.MAIN和CATEGORY_LAUNCHER可以在卸载应用的时候同时删除桌面快捷方式
//        Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
//        launcherIntent.setClass(MainActivity.this, MainActivity.class);
//        launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        //打开网页
        Intent launcherIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.baidu.com"));

        addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launcherIntent);
        sendBroadcast(addShortCut);
    }

删除快捷方式

    private void removeShortcut() {
        Intent intent = new Intent("com.android.launcher.action.UNINSTALL_SHORTCUT");

        // 名字
        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Test");

        // 设置关联程序
        Intent launcherIntent = new Intent(MainActivity.this,
                MainActivity.class).setAction(Intent.ACTION_MAIN);

        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launcherIntent);

        sendBroadcast(intent);
    }

onNewIntent的调用时机以及于四种启动模式的关系

使用setTouchDelegate来扩大View的触摸范围

升级系统app后重启系统,app未升级

我们平时开发过程中可能遇到这样的问题:安装更新系统app后,重新开机启动,发现更新没有了,app有变成原来的样子,结果的办法是升级一下版本号就可以了,不知道原生逻辑是不是这样子的,有时间研究一下。

FLAG_SHOW_WHEN_LOCKED

使得应用程序窗口优先于锁屏界面,当屏幕锁定时,窗口可以被看到。

final Window win = activity.getWindow();
final WindowManager.LayoutParams params = win.getAttributes();
params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;

去除Activity的各种切换动画

<style name="notAnimation"> 
   <item name="android:activityOpenEnterAnimation">@null</item> 
   <item name="android:activityOpenExitAnimation">@null</item> 
   <item name="android:activityCloseEnterAnimation">@null</item> 
   <item name="android:activityCloseExitAnimation">@null</item> 
   <item name="android:taskOpenEnterAnimation">@null</item> 
   <item name="android:taskOpenExitAnimation">@null</item> 
   <item name="android:taskCloseEnterAnimation">@null</item> 
   <item name="android:taskCloseExitAnimation">@null</item> 
   <item name="android:taskToFrontEnterAnimation">@null</item> 
   <item name="android:taskToFrontExitAnimation">@null</item> 
   <item name="android:taskToBackEnterAnimation">@null</item> 
   <item name="android:taskToBackExitAnimation">@null</item> 
</style>

打印当前堆栈

        new Throwable().printStackTrace();

延迟执行某个动作到给定条件发生时执行

方法一:http://blog.csdn.net/heqiangflytosky/article/details/49660617
方法二:可以先判断当前条件是否满足,如果不满足,就把要执行的代码放入到一个列表中,当条件满足是判断该列表是否有需要执行的代码,如过有的话就执行。
下面的例子是将代码的执行放到onRusume调用后再执行:

    private ArrayList<Runnable> mBindOnResumeCallbacks = new ArrayList<Runnable>();

    private void doSomeThing(){
        Runnable r = new Runnable() {
            public void run() {
                doSomeThing();
            }
        };
        if (waitUntilResume(r)) {
            return;
        }
        ……
    }
    
    private boolean waitUntilResume(Runnable run) {
        return waitUntilResume(run, false);
    }

    private boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
        if (mPaused) {
            Log.i(TAG, "Deferring update until onResume");
            if (deletePreviousRunnables) {
                while (mBindOnResumeCallbacks.remove(run)) {
                }
            }
            mBindOnResumeCallbacks.add(run);
            return true;
        } else {
            return false;
        }
    }

    @Override
    protected void onResume() {
        mPaused = false;
        if (mBindOnResumeCallbacks.size() > 0) {
            for (int i = 0; i < mBindOnResumeCallbacks.size(); i++) {
                mBindOnResumeCallbacks.get(i).run();
            }
        }
    }

Intent.getSourceBounds()

通过Intent.getSourceBounds()方法可以获取到Shortcut在Launcher中的坐标信息。

在onCreate()里面获取view的width和height

在onCreate()获取view的width和height会得到0.view.getWidth()和view.getHeight()为0的根本原因是控件还没有完成绘制,你必须等待系统将绘制完View时,才能获得。下面有一些可行的解决方案。

  • 监听Draw/Layout事件:ViewTreeObserver
    ViewTreeObserver监听很多不同的界面绘制事件。一般来说OnGlobalLayoutListener就是可以让我们获得到view的width和height的地方。下面onGlobalLayout内的代码会在View完成Layout过程后调用。
    view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int height = view.getHeight();
            view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });

但是要注意这个方法在每次有些view的Layout发生变化的时候被调用(比如某个View被设置为Invisible),所以在得到你想要的宽高后,记得移除 onGlobleLayoutListener

  • View.post()
    UI事件队列会按顺序处理事件。在setContentView()被调用后,事件队列中会包含一个要求重新layout的message,所以任何你post到队列中的东西都会在Layout发生变化后执行。
    view.post(new Runnable() {
        @Override
        public void run() {
            int height = view.getHeight();
        }
    });
  • 重写View的onLayout方法
    在onLayout()里面获取,需要注意的是onLayout()方法会调用很多次。

  • 另外可以在 Activity.onPostCreate() 方法中获取,这个是 Activity 彻底运行起来之后的回调方法。

Android intent-filter匹配自定义后缀文件

<intent-filter>
       <action android:name="android.intent.action.VIEW" />
       <category android:name="android.intent.category.DEFAULT" />
       <data android:scheme="file" />
       <data android:host="*" />
       <data android:mimeType="*/*" />
       <data android:pathPattern=".*\\.test" />
</intent-filter>

这里 pathPattern 里面的“.” 用来匹配任意字符,“.*” 就是用来匹配任意字符0次或更多,“\”是用来转义用的,之所以有两个是因为这里需要两次转义,读取 Xml 时转义一次,在 pathPattern 中使用又转义一次。

android:manageSpaceActivity

如果你想在应用管理中自定义应用数据管理,这个属性会帮助到你。设置这个属性会在设置的应用管理界面中出现一个空间管理按钮,点击之后进入你自定义的空间管理界面。

android:process

在 manifest 中设置application或者activityandroid:process可以让应用或者组件运行在我们制定的进程中去。通过这个属性也可以让多个应用运行在同一个进程中,但前提条件是两个APP具有想同的user ID并且被同一个私钥签名。

编译Release版报错

遇到这种问题,在编译debug版本是好的,编译release版本是报错:

Warning: there were 664 unresolved references to classes or interfaces.
         You may need to add missing library jars or update their versions.
         If your code works fine without the missing classes, you can suppress
         the warnings with '-dontwarn' options.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)
Warning: there were 2 unresolved references to library class members.
         You probably need to update the library versions.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)
Warning: Exception while processing task java.io.IOException: Please correct the above warnings first.
:app:transformClassesAndResourcesWithProguardForRelease FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesAndResourcesWithProguardForRelease'.
> Job failed, see logs for details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

一般是混淆的问题,如果遇到上面这种错误,可以在 proguard-rules.pro 中加入 -ignorewarnings

使用 ids.xml

我们给一个 View 设置 id,最常用的方法就是在布局文件中使用 @+id/ 来设置,但我们经常遇到这种使用场景,代码中动态地添加 View,我们又想给它设置一个id,怎么办呢?
通常我们可以在 values 目录下面创建一个 ids.xml 资源文件,在里面列出 id 的名称:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item type="id" name="custom_view" />
    <item type="id" name="root_view" />
    <item type="string" name="str_test" />
</resources>

ids.xml 资源文件为应用的相关资源提供唯一的资源id,然后在代码中就可以引用了:

import com.X.X.R;
view.setId(R.id.root_view);
...
if (getId() == R.id.root_view)
...

另外,若在 ids.xml 中定义了ID,则在 layout 中可如下定义 @id/custom_view,否则@+id/custom_view

使用HandlerThread创建常驻子线程

private HandlerThread mUpdateStatusThread;
    {
        mUpdateStatusThread = new HandlerThread("update_download_status_thread");
        mUpdateStatusThread.start();
        mUpdateStatusHandler = new UpdateStatusHandler(mUpdateStatusThread.getLooper(), this);
    }

    {
            mUpdateStatusHandler.removeCallbacksAndMessages(null);
            mUpdateStatusThread.quitSafely();
    }

    {
           mUpdateStatusHandler.obtainMessage(UpdateStatusHandler.MSG_UPDATE_PROGRESS, downloadId)
                    .sendToTarget();
    }

    private static class UpdateStatusHandler extends Handler {
        static final int MSG_UPDATE_PROGRESS = 0;
        private WeakReference<DownloadObserver> mWeakReference;

        UpdateStatusHandler(Looper looper) {
            super(looper);
            mWeakReference = new WeakReference<>(downloadObserver);
        }

        @Override
        public void handleMessage(Message msg) {
            ....
            switch (msg.what) {
                case MSG_UPDATE_PROGRESS:
                    ......
                    break;
            }
        }
    }

解决点击 PopupWindow和ListPopupWindow外部区域底层View响应的问题

如果是 PopupWindow 可以通过 setFocusable(true)来解决。
如果是 ListPopupWindow 则要通过反射解决:

        try {
            Field popField = listPopupWindow.getClass().getDeclaredField("mPopup");
            popField.setAccessible(true);
            PopupWindow pop = (PopupWindow) popField.get(listPopupWindow);
            pop.setFocusable(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

水平线性布局下,如何最左或者最右

如果用RelativeLayout就比较好解决,如果用LinearLayout可以使用多放置一个透明的空间,设置为透明,并把 android:layout_weight设置为1,这样就可以把其他组件挤到左边或右边或者两边。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
    <View
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginTop="40dp"
        android:layout_marginRight="10dp"/>
    <View
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginTop="40dp"
        android:layout_marginEnd="10dp"/>
</LinearLayout>

设置透明背景

        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>

设置沉浸模式,隐藏状态栏

        <item name="android:windowTranslucentStatus">true</item>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android应用开发常用知识(4) 的相关文章

随机推荐

  • Android中锁定文件的方法

    androidSDK中并没有锁定文件相关的api 但是android是基于linux操作系统的 linux比较底层 灵活性也更大 为了实现锁定文件的效果 大概有以下几种办法 用chmod命令修改文件读写权限利用linux中的多线程独占锁 启
  • 远程控制Ubuntu

    远程控制Ubuntu 在Ubuntu上安装team viewer或者向日葵 xff0c 进行远程控制 xff0c 这里记录采用team viewer方式的配置过程 xff0c 向日葵等远程控制类似 安装Ubuntu 官方下载Ubuntu系统
  • 信号降噪方法

    傅里叶变换 只能获取一段信号总体上包含哪些频率的成分 xff0c 但是对各成分出现的时刻并无所知 对非平稳过程 xff0c 傅里叶变换有局限性 短时傅里叶变换 xff08 Short time Fourier Transform STFT
  • C++ 带通滤波

    Butterworth Filter Coefficients The following files are for a library of functions to calculate Butterworth filter coeff
  • python之collections

    collections是日常工作中的重点 高频模块 xff0c 包含了一些特殊的容器 xff0c 针对Python内置的容器 xff0c 例如list dict set和tuple xff0c 常用类型有 xff1a namedtuple
  • git 指定下载文件,目录

    1 创建路径 mkdir gitfile cd lt 路径 gt eg xff1a cd home gitfile 2 创建一个空的本地仓库 git init 3 连接远程仓库GitHub git remote add f origin l
  • Ubuntu v4l2 视屏流花屏问题

    之前用的好好解析YUV xff0c MJPEG 换了个核心板就不好使了 xff0c opencv3 4 6 gt gt gt opencv4 5 5 xff0c Mat xff0c cvMat xff0c IplImage 的类型转换也不好
  • qt qmake .qrc hasmodification time xxx in the future

    原因 xff1a 跨平台生成的 qrc 文件创建时间与目标平台时间不一致导致 xff0c 如win写的 copy 到 Linux xff0c 再编译可能会遇到该bug 导致无法qmake 与 build 解决 xff1a touch qrc
  • (转)python图像操作

    转自 xff1a zbxzc 侵删 使用PIL完成 python view plain copy span class hljs keyword import span Image span class hljs comment 打开图像
  • 关于input to reshape is a tensor 的问题

    span class hljs keyword for span index name span class hljs operator in span enumerate classes class path 61 cwd 43 name
  • mobileNet训练自己的样本

    span class hljs keyword import span matplotlib pyplot span class hljs keyword as span plt span class hljs keyword import
  • 关于屏幕适配之比例布局

    对于平板等需求场合 xff0c 它们的屏幕比例以16 xff1a 10和16 xff1a 9等为主 xff0c 但是屏幕尺寸各异 xff0c 分辨率各异 xff0c 即便是同一尺寸也有多种分辨率 xff0c 这种时候无论是使用dp还是px
  • 机器学习实战:ValueError: invalid literal for int() with base 10: '0.000000'

    在logistic回归一章中 xff0c 在将训练数据转换为int型时 xff0c 会出现日下报错 xff1a ValueError invalid literal for int with base 10 0 000000 只需将下面一句
  • cuda-8.0安装心得

    cuda 8 0安装 xff08 这两天不小心把原来的显卡驱动搞崩 xff0c 挣扎了好久 xff0c 只好重新走一遍 xff09 cuda 安装条件 gcc5 3 0 xff08 版本不能太高 xff09 sudo apt get ins
  • 在GPU刨过的坑

    这两天回学校这两天先是把自己的linux系统给强制删除了 xff0c 然后导致重启无法正常引导进入win xff0c 最后win也救不活了 xff0c 还不好重装系统 xff0c 各种文件损坏 xff0c 简单粗暴的翻车血泪史 捷径路上总是
  • [ArchLinux] 搜狗拼音输入法的安装

    配置源 在ArchlinuxCN源中有很多方便中国用户使用的包 xff0c 其中也包含了经常使用的搜狗拼音输入法 xff0c 于是我们需要先配置ArchlinuxCN源 xff0c 这样我们就可以使用自带的包管理器Pacman直接安装搜狗拼
  • [ArchLinux] 安装及KDE桌面环境安装配置

    ArchLinux 安装及KDE桌面环境安装配置 首先 xff0c 安装之前 xff0c 需要一个 启动介质 xff0c 我这里习惯使用USB设备作为启动介质 xff0c 这是由于ArchLinux滚动更新的特性 xff0c 而且占用空间很
  • 使用crontab执行定时任务时加flock独占锁防止进程堆积

    使用crontab执行定时任务 此处为每分钟执行一次 加flock独占锁防止进程堆积 注意给 var run 读写权限 xff0c 或者放到一个有读写权限的文件夹 span class token operator span span cl
  • macOs 安装liplpcap

    1 xff0c 下载liplpcap http www tcpdump org 1 在tcpdump网站下载libpcap的latest release 2 tar zxvf 3 configure make amp make instal
  • Android应用开发常用知识(4)

    Android string 中product的使用 Android的资源文件string xml会出现下面同名的字符串 xff1a lt string name 61 34 build type 34 product 61 34 tv 3