Android 杂技

2023-12-01 21:40
文章标签 android 杂技

本文主要是介绍Android 杂技,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

图片之Exif信息设置

ExifInterface exif = new ExifInterface(filePath.getAbsolutePath());
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, GPS.convert(latitude));
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, GPS.latitudeRef(latitude));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, GPS.convert(longitude));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, GPS.longitudeRef(longitude));
exif.saveAttributes();
/** @author fabien*/
public class GPS {private static StringBuilder sb = new StringBuilder(20);/*** returns ref for latitude which is S or N.* @param latitude* @return S or N*/public static String latitudeRef(double latitude) {return latitude<0.0d?"S":"N";}/*** returns ref for latitude which is S or N.* @param latitude* @return S or N*/public static String longitudeRef(double longitude) {return longitude<0.0d?"W":"E";}/*** convert latitude into DMS (degree minute second) format. For instance<br/>* -79.948862 becomes<br/>*  79/1,56/1,55903/1000<br/>* It works for latitude and longitude<br/>* @param latitude could be longitude.* @return*/synchronized public static final String convert(double latitude) {latitude=Math.abs(latitude);int degree = (int) latitude;latitude *= 60;latitude -= (degree * 60.0d);int minute = (int) latitude;latitude *= 60;latitude -= (minute * 60.0d);int second = (int) (latitude*1000.0d);sb.setLength(0);sb.append(degree);sb.append("/1,");sb.append(minute);sb.append("/1,");sb.append(second);sb.append("/1000");return sb.toString();}
}

如何在Android上的exif数据中保存GPS坐标?

Render process (15791) kill (OOM or update) wasn’t handed by all associated webviews, killing application.

关闭硬件加速
android:hardwareAccelerated=“false”

H5 混合开发,软键盘挡住输入框问题的终极解决方案

https://www.jianshu.com/p/306482e17080

AndroidBug5497Workaround

public class AndroidBug5497Workaround {// For more information, see https://issuetracker.google.com/issues/36911528// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.public static void assistActivity (Activity activity) {new AndroidBug5497Workaround(activity);}private View mChildOfContent;private int usableHeightPrevious;private FrameLayout.LayoutParams frameLayoutParams;private AndroidBug5497Workaround(Activity activity) {FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);mChildOfContent = content.getChildAt(0);mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {public void onGlobalLayout() {possiblyResizeChildOfContent();}});frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();}private void possiblyResizeChildOfContent() {int usableHeightNow = computeUsableHeight();if (usableHeightNow != usableHeightPrevious) {int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();int heightDifference = usableHeightSansKeyboard - usableHeightNow;if (heightDifference > (usableHeightSansKeyboard/4)) {// keyboard probably just became visibleframeLayoutParams.height = usableHeightSansKeyboard - heightDifference;} else {// keyboard probably just became hiddenframeLayoutParams.height = usableHeightSansKeyboard;}mChildOfContent.requestLayout();usableHeightPrevious = usableHeightNow;}}private int computeUsableHeight() {Rect r = new Rect();mChildOfContent.getWindowVisibleDisplayFrame(r);return (r.bottom - r.top);}
}

Android Studio中不能展开jdk源码,无法import包

修改.idea->misc.xml,将project-jdk-name="JDK"改为对应的版本名字,如:11(Project Structure中配置的gradle jdk版本)

<?xml version="1.0" encoding="UTF-8"?>
<project version="4"><component name="DesignSurface"><option name="filePathToZoomLevelMap"><map><entry key="..\:/work/AndroidProject/DEMO/app/src/main/res/layout/activity_main.xml" value="0.20364583333333333" /></map></option></component><component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="JDK" project-jdk-type="JavaSDK"><output url="file://$PROJECT_DIR$/build/classes" /></component><component name="ProjectType"><option name="id" value="Android" /></component>
</project>

改为

  ...<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="11" project-jdk-type="JavaSDK"><output url="file://$PROJECT_DIR$/build/classes" /></component>...

原帖

Android Studio实现透明状态栏

    //是否使用特殊的标题栏背景颜色,android5.0以上可以设置状态栏背景色,如果不使用则使用透明色值protected boolean useThemestatusBarColor = true;//是否使用状态栏文字和图标为暗色,如果状态栏采用了白色系,则需要使状态栏和图标为暗色,android6.0以上可以设置protected boolean useStatusBarColor = true;protected void setStatusBar() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0及以上Window window = getWindow();window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//根据上面设置是否对状态栏单独设置颜色if (useThemestatusBarColor) {window.setStatusBarColor(getResources().getColor(R.color.blue));//设置状态栏背景色} else {window.setStatusBarColor(Color.TRANSPARENT);//透明}}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && useStatusBarColor) {//android6.0以后可以对状态栏文字颜色和图标进行修改getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);}}

原帖

再学一遍android:fitsSystemWindows属性
Android关于StatusBar(状态栏)总结

ARouter报错Manifest merger failed

需要在项目的gradle.properties中添加

android.useAndroidX=true
android.enableJetifier=true
  • android.useAndroidX=true
    表示“Android插件会使用对应的AndroidX库,而非Support库”;未设置时默认为false;
  • android.enableJetifier=true
    表示Android插件会通过重写其二进制文件来自动迁移现有的第三方库,以使用AndroidX依赖项;未设置时默认为false

android添加依赖ARouter报错Manifest merger failed

gradle中配置android.useAndroidX与android.enableJetifier使应用对support库的依赖自动转换为androidx的依赖

Android矢量图

Android矢量图(三)–VectorDrawable渐变色

onNewIntent 的调用时机

不是每次都会调用onRestart()

Android activity onNewIntent 调用时机

兼容性registerForActivityResult替代onActivityResult

How to Select Files in Android Easily? Connecting Storage Access Framework and Activity Result API

Android Studio 报错 Invalid Gradle JDK configuration found.

将.idea路径下的gradle.xml文件删除,再sync
参考

使用buildSrc目录提取gradle配置变量

object Apps {const val compileSdk: Int = 30const val minSdk = 21const val targetSdk = 30
//    const val versionCode = 1
//    const val versionName = "1.0.0"
}

报错

问题:报 Overload resolution ambiguity错误
解决:删除掉buildSrc目录下的.gradle和build目录,再gradle编译生成新的
删除圈起的文件夹

Android业务组件化之URL Scheme使用

链接:https://www.jianshu.com/p/da801097c79d

Android使用MediaStore获取手机上的文件

链接:https://blog.csdn.net/yann02/article/details/92844364

彻底搞懂Android文件存储—内部存储,外部存储以及各种存储路径解惑

链接:https://blog.csdn.net/u010937230/article/details/73303034

AndroidStudio Build Output 日志乱码

D:\work\AndroidProject\xx\app\build\generated\ap_generated_sources\devDebug\out\com\xx\DataBinderMapperImpl.java:9: ����: �Ҳ�������
import com.xx.databinding.FragmentMeBindingImpl;^����:   �� FragmentMeBindingImpl�: ����� com.xx.databinding

方法:Help->Edit Custom VM Options… 打开 studio64.exe.vmoptions 文件,加入-Dfile.encoding=UTF-8,重启即可

# custom Android Studio VM options, see https://developer.android.com/studio/intro/studio-config.html
-Dfile.encoding=UTF-8
D:\work\AndroidProject\xx\app\build\generated\ap_generated_sources\devDebug\out\com\xx\DataBinderMapperImpl.java:9: 错误: 找不到符号
import com.xx.databinding.FragmentMeBindingImpl;^符号:   类 FragmentMeBindingImpl位置: 程序包 com.xx.databinding

参考

Android相关路径自定义

1. Android Studio配置:idea.properties文件

 idea.config.path=D:/Android/.AndroidStudio/configidea.system.path=D:/Android/.AndroidStudio/systemidea.plugins.path=${idea.config.path}/pluginsidea.log.path=${idea.system.path}/log

idea.properties截图

2. ANDROID_HOME

Android的SDK位置 例如:D:\Android\sdk

也可用以下操作修改SDK路径:Appearance & Behavior → System Settings → Android SDK中,点击 Android SDK Location → Edit
在这里插入图片描述

3. ANDROID_AVD_HOME

Android 虚拟机的保存位置,例如:D:\Android\avd
在这里插入图片描述

4. GRADLE_USER_HOME

gradle仓库存放路径,例如:D:\Android.gradle
在这里插入图片描述

Android Q分区存储

关于Android Q分区存储的一些适配心得

Android10填坑适配指南,实际经验代码,拒绝翻译

开源中国客户端 Android Q 经验适配指南,含代码

Android-Q适配-存储方式

java的四舍五入

目前java支持7中舍入法:

  1. ROUND_UP:远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。
  2. ROUND_DOWN:趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。
  3. ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。
  4. ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。
  5. HALF_UP:最近数字舍入(5进)。这是我们最经典的四舍五入。
  6. HALF_DOWN:最近数字舍入(5舍)。在这里5是要舍弃的。
  7. HAIL_EVEN:银行家舍入法。

方法一:四舍五入

double f = 111231.5585;
BigDecimal b = new BigDecimal(f);
double f1 = b.setScale(2, RoundingMode.HALF_UP).doubleValue();
// 在这里使用BigDecimal ,并且采用setScale方法来设置精确度,
//同时使用RoundingMode.HALF_UP表示使用最近数字舍入法则来近似计算。

方式二:

new java.text.DecimalFormat("#.00").format(3.1415926)
// #.00 表示两位小数 #.0000四位小数 以此类推…

方式三:

double d = 3.1415926;
String result = String .format("%.2f");
// %.2f %. 表示 小数点前任意位数   2 表示两位小数 格式后的结果为f 表示浮点型。

引自 https://www.cnblogs.com/chenssy/p/3366632.html

手势操作onScroll没有执行(以及onFling问题)

现象1

将某一手势操作交给GestureDetector时,GestureDetector重写了几个方法,但是onScroll没有执行,其他的onDOwn,OnLongPress都有执行。

解决:onDOwn方法的返回值返回true

现象2

虽然此时onScroll(滑动)方法调用了,但是打印结果表示:该方法会调用多次,有时并不是我所需要的,而onFling表示滑动,当手离开时调用,但是打印的结果显示并没有调用;

解决:在之前的基础上再将onScroll返回false即可!

原文链接:https://blog.csdn.net/flycatdeng/article/details/18267133

ImageSpan

// 第一种
Drawable drawable = getResources().getDrawable(R.drawable.ic_coin);
drawable.setBounds(0,0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
// 第一种
ImageSpan imageSpan = new ImageSpan(mContext, R.drawable.ic_coin);stringBuilder.setSpan(imageSpan, size-1, size, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

FragmentPagerAdapter与FragmentStatePagerAdapter区别

https://www.cnblogs.com/lianghui66/p/3607091.html

判断 RecyclerView 到达底部的方法

第1种
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {private boolean isToBottom = false;@Overridepublic void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);if (newState == RecyclerView.SCROLL_STATE_IDLE && isToBottom) {loadMore();}}@Overridepublic void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);isToBottom = isSlideToBottom(recyclerView);swipeRefresh.setEnabled(isSlideToTop(recyclerView));}});/*** 判断是否滑动到底部*/public static boolean isSlideToBottom(RecyclerView recyclerView) {if (recyclerView == null) return false;return recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()>= recyclerView.computeVerticalScrollRange();}/*** 判断是否滑动到顶部*/public static boolean isSlideToTop(RecyclerView recyclerView) {if (recyclerView == null) return false;return recyclerView.computeVerticalScrollOffset() == 0;}
第2种
	/*** 判断是否滑动到底部*/public static boolean isSlideToBottom(RecyclerView recyclerView) {return !recyclerView.canScrollVertically(1); //表示是否能向上滚动,false 表示已经滚动到底部 }/*** 判断是否滑动到顶部*/public static boolean isSlideToTop(RecyclerView recyclerView) {return !recyclerView.canScrollVertically(-1); // 表示是否能向下滚动,false 表示已经滚动到顶部}
第3种
	RecyclerView rvMessage = findViewById(R.id.rv_message);GridLayoutManager layoutManager = new GridLayoutManager(this, 1, RecyclerView.VERTICAL, false);rvMessage.setLayoutManager(layoutManager);MessageAdapter messageAdapter = new MessageAdapter();rvMessage.setAdapter(messageAdapter);rvMessage.addOnScrollListener(new RecyclerView.OnScrollListener() {private int lastVisible = 0;@Overridepublic void onScrollStateChanged([@NonNull](https://my.oschina.net/u/2981441) RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);if (newState == RecyclerView.SCROLL_STATE_IDLE &&lastVisible + 1 == messageAdapter.getItemCount()) {// 已滑动到底部}}[@Override](https://my.oschina.net/u/1162528)public void onScrolled([@NonNull](https://my.oschina.net/u/2981441) RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);lastVisible = layoutManager.findLastCompletelyVisibleItemPosition();}});

参考

http://quanzhan.applemei.com/webStack/TVRrNE9RPT0=

将十六进制 颜色代码 转换为int类型数值

Color.parseColor(“#FF00FF”)

getColor在6.0中过时

MainActivity.this.getResources().getColor(R.color.colorTest)

用以下替换

ContextCompat.getColor(context, R.color.my_color)

//源码 
public static final int getColor(Context context, int id)
{
final int version = Build.VERSION.SDK_INT;
if (version >= 23) {return ContextCompatApi23.getColor(context, id);       
} else {return context.getResources().getColor(id);}
}

SparseArray

SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch)

Listview的Adapter的转换

如果ListView没有headerView或者footerView的时候,与listView相关联的Adapter就是传进来的参数Adapter,如果有,就将原来的Adapter包装成HeaderViewListAdapter,HeaderViewListAdapter有个方法getWrappedAdapter,该方法能返回被包装的HeaderViewListAdapter的ListAdapter。

HeaderViewListAdapter headerViewListAdapter = (HeaderViewListAdapter) listView.getAdapter(); 
ContactAdapter contactAdapter = (ContactAdapter) headerViewListAdapter.getWrappedAdapter();

使用View做虚线分割线

drawable/line_dash.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="line"><stroke android:color="@color/colorBlack"android:dashGap="2dp"android:dashWidth="5dp"android:width="1dp" /><size android:width="1dp" />
</shape>

布局文件中:(需要设置 layerType为software)

<Viewandroid:layout_width="match_parent"android:layout_height="2dp"android:background="@drawable/line_dash"android:layerType="software"/>

Android api23 删除HttpClient 相关类

在Module的gradle.build文件添加依赖,和 packagingOptions,和 useLibrary ‘org.apache.http.legacy’

android {compileSdkVersion 23buildToolsVersion "23.0.2"defaultConfig {applicationId "com.egrid.webdemo"minSdkVersion 16targetSdkVersion 23versionCode 1versionName "1.0"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}packagingOptions {exclude 'META-INF/DEPENDENCIES'exclude 'META-INF/NOTICE'exclude 'META-INF/LICENSE'exclude 'META-INF/LICENSE.txt'exclude 'META-INF/NOTICE.txt'}//会加载Andrdoid自带的jar包 org.apache.http.legacy.jaruseLibrary 'org.apache.http.legacy'
}dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])testCompile 'junit:junit:4.12'compile 'com.android.support:appcompat-v7:23.1.1'//下面这些不会起作用compile 'org.apache.httpcomponents:httpclient:4.3.6'compile 'org.apache.httpcomponents:httpcore:4.3.2'
}

在xml中使用系统的actionBarSize

  1. 在attrs.xml文件中定义
<resources><declare-styleable name="app"><attr name="toolbarHeight" format="dimension" /></declare-styleable>
</resources>
  1. 在styles.xml中自定义toolbarHeight为actionBarSize
 <style name="BaseTheme" parent="Theme.AppCompat.Light.DarkActionBar"><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/colorAccent</item><item name="colorButtonNormal">@color/blueLight</item><item name="colorControlHighlight">@color/background</item><item name="toolbarHeight">?android:attr/actionBarSize</item></style>
  1. 在布局xml中使用
 <androidx.appcompat.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/toolbarHeight"app:contentInsetStart="0dp"app:layout_collapseMode="pin" />

Splash 的最佳实践

此方法是给主界面设置闪屏页主题,在主界面中再用代码换回主界面主题,实现无闪屏Activity达到闪屏页的效果。

  1. 闪屏主题
<resources><!-- 主界面主题 --><style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/colorAccent</item></style><!-- 闪屏主题 --><style name="AppTheme.Launcher"><item name="android:windowBackground">@drawable/launch_screen</item></style>
<resources>
  1. 闪屏界面背景drawable/launch_screen.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"android:opacity="opaque"><item android:drawable="@color/white" /><bitmapandroid:gravity="center"android:src="@drawable/img_splash" />
</layer-list>
  1. 主界面设置主题
<activityandroid:name=".ui.activity.MainActivity"android:theme="@style/AppTheme.Launcher"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>
  1. 主界面super.onCreate() 之前调用 onCall() 方法设置回应用主题
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceStated) {setTheme(R.style.AppTheme);super.onCreate(savedInstanceStated);// ...}
}

注:若有闪屏Activity可以直接使用主题设置闪屏背景,无需在布局设置背景,所以没有背景显示时的切换问题

链接:https://blog.csdn.net/zujack/article/details/69499350

TextView 设置和取消删除线的两种方法

设置删除线
  1. (推荐)通过按位或运算符|,将 TextView 原本的 Flags 属性和删除线一块设置。setPaintFlags内会对 TextView 进行重绘。
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
  1. 获取画笔后设置属性,重绘 TextView 。此方式有个问题,会把 TextView 原本的 Flags 属性替代,例如抗锯齿等。仔细查看,你会发现通过这种方式,文字有了锯齿。
tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
tv.invalidate();
取消删除线
  1. (推荐)先对 Paint.STRIKE_THRU_TEXT_FLAG 属性取反,再用按位与运算符&,除去了删除线属性并保留了 TextView 原本的 Flags 属性。setPaintFlags内会对 TextView 进行重绘。
tv.setPaintFlags(tv.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
  1. 获取画笔后,清空 Flags 属性,再重绘 TextView 。此方式有个问题,会把 TextView 原本的所有 Flags 属性清空,例如抗锯齿等。仔细查看,你会发现通过这种方式,文字有了锯齿;
tv.getPaint().setFlags(0);
tv.invalidate();

参考:https://www.jb51.net/article/136661.htm

RecyclerView滚动到指定位置并置顶

  • https://blog.csdn.net/weimingjue/article/details/82805361
 // 自定义类public class TopSmoothScroller extends LinearSmoothScroller {public TopSmoothScroller(Context context) {super(context);}@Overrideprotected int getHorizontalSnapPreference() {return SNAP_TO_START;//具体见源码注释}@Overrideprotected int getVerticalSnapPreference() {return SNAP_TO_START;//具体见源码注释}
}// 使用LinearSmoothScroller scroller = new TopSmoothScroller(CourseActivity.this);scroller.setTargetPosition(position);linearLayoutManager.startSmoothScroll(scroller);

用shape画的虚线在真机上无法显示

在布局View添加属性 android:layerType=“software”

安装debug包时手机(OPPO VIVO)显示INSTALL_FAILED_TEST_ONLY无法安装

Android Studio 3.0以后会在debug apk的manifest文件中加android:testOnly=”true” 属性,此属性无法在非开发者模式的手机上安装,VIVO OPPO即使在开发者模式也不能安装。

解决: 在gradle.properties文件中添加android.injected.testOnly=false

沉浸式模式

Android关于沉浸式状态栏总结

https://juejin.im/post/5989ded56fb9a03c3b6c8bde

Android状态栏微技巧,带你真正理解沉浸式模式

https://blog.csdn.net/guolin_blog/article/details/51763825

Android 沉浸式状态栏必知必会

https://juejin.im/entry/58cb481744d9040069f57266

刘海屏适配cutout

刘海屏适配 与WindowInsets,DisplayCutout使用

https://blog.csdn.net/yi_master/article/details/80309757

Android Studio配置文件路径修改

.AndroidStudio文件夹修改

修改文件C:\Program Files\Android\Android Studio\bin\idea.properties中的

idea.config.path=D:/Android/.AndroidStudio/config
idea.system.path=D:/Android/.AndroidStudio/system

.gradle文件夹的修改

设置Android Studio中的
Settings->Build,Execution,Deployment->Gradle 中的Service directory path为D:/Android/.gradle

.android文件夹的修改
添加一个系统的环境变量ANDROID_SDK_HOME为D:/Android/avd

https://www.jianshu.com/p/7a58c5f154c5

Android 常用尺寸

密度ldpimdpihdpixhdpixxhdpixxxhdpi
比例0.7511.5234
密度数120dpi160dpi240dpi320dpi480dpi640dpi
代表分辨率240*320320*480480*800720*12801080*19201440*2560
Launcher And Home36*3648*4872*7296*96144*144192*192
Action Bar And Tab24*2432*3248*4864*6496*96128*128
Notification18*1824*2436*3648*4872*7296*96
Background320*426320*470480*640720*12801080*19201440*2560

Android Studio一直 Fetching Documentation…

修改“C:\Users\Administrator\.AndroidStudio2.3\config\options\jdk.table.xml”文件<javadocPath><root type="composite"><root type="simple" url="file://D:/Android/sdk/platforms/reference/" /></root>
</javadocPath>

Android 颜色透明度换算

100% — FF
95% — F2
90% — E6
85% — D9
80% — CC
75% — BF
70% — B3
65% — A6
60% — 99
55% — 8C
50% — 80
45% — 73
40% — 66
35% — 59
30% — 4D
25% — 40
20% — 33
15% — 26
10% — 1A
5% — 0D
0% — 00

TabLayout添加 tab分割线

    LinearLayout linearLayout = (LinearLayout) tabContent.getChildAt(0);linearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);linearLayout.setDividerPadding(CommonUtils.dp2px(this, 8));linearLayout.setDividerDrawable(ContextCompat.getDrawable(this,R.drawable.layout_divider_vertical));

layout_divider_vertical.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="@color/grayDark"/><size android:width="1dp"/>
</shape>

将十六进制 颜色代码 转换为int类型数值

Color.parseColor(“#FF00FF”)

getColor在6.0中过时

MainActivity.this.getResources().getColor(R.color.colorTest)

用一下替换

    ContextCompat.getColor(context, R.color.my_color)//源码 public static final int getColor(Context context, int id) { final int version = Build.VERSION.SDK_INT; if (version >= 23) { return ContextCompatApi23.getColor(context, id);} else {return context.getResources().getColor(id);  }}

SparseArray

SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch)

Listview的Adapter的转换

如果ListView没有headerView或者footerView的时候,与listView相关联的Adapter就是传进来的参数Adapter,如果有,就将原来的Adapter包装成HeaderViewListAdapter,HeaderViewListAdapter有个方法getWrappedAdapter,该方法能返回被包装的HeaderViewListAdapter的ListAdapter。

HeaderViewListAdapter headerViewListAdapter = (HeaderViewListAdapter) listView.getAdapter();
ContactAdapter contactAdapter = (ContactAdapter) headerViewListAdapter.getWrappedAdapter();

使用View做虚线分割线

drawable/line_dash.xml

    <?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="line"><stroke android:color="@color/colorBlack"android:dashGap="2dp"android:dashWidth="5dp"android:width="1dp"/><size android:width="1dp" /></shape>

布局文件中:(需要设置 layerType为software)

    <Viewandroid:layout_width="match_parent"android:layout_height="2dp"android:background="@drawable/line_dash"android:layerType="software"/>

Android api23 删除HttpClient 相关类

在Module的gradle.build文件添加依赖,和 packagingOptions,和 useLibrary ‘org.apache.http.legacy’

    android {compileSdkVersion 23buildToolsVersion "23.0.2"defaultConfig {applicationId "com.egrid.webdemo"minSdkVersion 16targetSdkVersion 23versionCode 1versionName "1.0"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}packagingOptions {exclude 'META-INF/DEPENDENCIES'exclude 'META-INF/NOTICE'exclude 'META-INF/LICENSE'exclude 'META-INF/LICENSE.txt'exclude 'META-INF/NOTICE.txt'}//会加载Andrdoid自带的jar包 org.apache.http.legacy.jaruseLibrary 'org.apache.http.legacy'}dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])testCompile 'junit:junit:4.12'compile 'com.android.support:appcompat-v7:23.1.1'//下面这些不会起作用compile 'org.apache.httpcomponents:httpclient:4.3.6'compile 'org.apache.httpcomponents:httpcore:4.3.2'}

横竖屏切换

android:configChanges="orientation|keyboardHidden|screenSize"

移动Android Studio默认的AVD目录(.android)

Move .android folder to E:\Android\
Create environment variable called ANDROID_SDK_HOME and set its value to E:\AndroidSetting environment variable in Windows XP:Right-click on My Computer and choose "Properties")Click the "Advanced" tabClick the button "Environment Variables".Add New variablehttps://stackoverflow.com/questions/3109473/moving-default-avd-configuration-folder-android

获取当前Activity的根视图

View rootView = getWindow().getDecorView().findViewById(android.R.id.content); 
或者:
View rootView = findViewById(android.R.id.content); 
或者:
View rootView = findViewById(android.R.id.content).getRootView(); 
关于android.R.id.content,开发者文档中并没有给予说明,但经过测试它应该是用来获取setContentView()中设置的View。http://www.cnblogs.com/littlepanpc/p/4506294.html

Activity启动模式

https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en

语言的复数形式

getQuantityString() <resources><pluralsname="plural_name"><itemquantity=["zero" | "one" | "two" | "few" | "many" | "other"]>text_string</item></plurals>
</resources>https://developer.android.com/guide/topics/resources/string-resource.html#Plurals
http://blog.csdn.net/a78270528/article/details/46791533

应用运行检测

/*** 检测应用是否在后台运行* [@param](https://my.oschina.net/u/2303379) context context* [@return](https://my.oschina.net/u/556800) true 后台运行*/
public static boolean isBackgroundRunning(final Context context) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(am.getRunningAppProcesses().size());for (ActivityManager.RunningTaskInfo runningTaskInfo : tasks) {if (runningTaskInfo.topActivity.getPackageName().equals(context.getPackageName())) {Log.d(TAG, "packageName:" + runningTaskInfo.topActivity.getPackageName());Log.d(TAG, "className:" + runningTaskInfo.topActivity.getClassName());return true;}}return false;
}/*** 检测应用是否在后台运行* [@param](https://my.oschina.net/u/2303379) context context* [@return](https://my.oschina.net/u/556800) true 前台运行*/
public static boolean isFrontRunning(Context context) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {for (String activeProcess : processInfo.pkgList) {if (activeProcess.equals(context.getPackageName())) {Log.d(TAG, "packageName:" + activeProcess);Log.d(TAG, "className:" + processInfo.processName);return true;}}}}return false;
}

app过大错误

问题:

Error:Execution failed for task ':app:transformClassesWithDexForDevDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

修改文件:

build.gradle 文件

android {compileSdkVersion 21buildToolsVersion "21.1.0"defaultConfig {...minSdkVersion 14targetSdkVersion 21...// Enabling multidex support.multiDexEnabled true}...
}dependencies {compile 'com.android.support:multidex:1.0.0'
}

Application类

<application...android:name="com.test.TestApplication">...
</application>public class TestApplication extends Application {protected void attachBaseContext(Context base) {super.attachBaseContext(base);MultiDex.install(this);}
}

详情:

https://developer.android.com/studio/build/multidex.html
http://stackoverflow.com/questions/26609734/how-to-enable-multidexing-with-the-new-android-multidex-support-library/38473900#38473900

Android 应用图标

m		1		48*48px
h		1.5		72*72px
xh		2		96*96px
xxh		3		144*144px
xxxh	4		192*192px1.CTRL+A  再选择编辑中的“描边”就行。(选择自己喜欢的颜色、设置自己需要的宽度) 
2.新建图层--矩形选框--反选--填充--快速蒙板--滤镜(多用几个)--退出蒙板--图层效果
3.矩形选区--快速蒙板--滤镜(各种滤镜有不同的效果,可以同时用多个滤镜)--退出蒙板--反选--删除--描边

ios和安卓切图换算比例

1dp(Android)=1pt(iOS)

以48dp@160dpi计算的话

mdpi 48px (160dpi, 1x) 基础尺寸

hdpi 72px (240dpi, 1.5x)

xhdpi 96px (320dpi, 2x) 同iOS @2x

xxdpi 144px (480dpi, 3x) 同iOS @3x

xxxdpi 192px (640dpi, 4x)

链接:http://www.zhihu.com/question/27038815/answer/34992846

android网络请求与页面切换

在android开发中会遇到使用fragment切换页面,并且切换的页面都会有网络请求,网络请求成功后会更新相应的fragment页面。如果使用异步网络请求组件android-async-http,会出现这样的情况,当你快速的切换fragment时,每个fragment都会发出新的请求。例如:fragmentA发了网络请求,又切换到了fragmentB,fragmentB又发了网络请求,然后快速的切换两个fragment,切换多次后可能会出现,fragmentA发出的请求返回成功并且使用handler发出消息请求改变fragmentA中的UI时,这时当前的页面正是fragmentB。此时会报空指针错误。

解决此类问题,可以通过第一次加载时缓存,再次切换到此页面时,只有下拉才能请求新数据。另一种方法是,设置一个public static volatile int flag;变量,如果flag为1时则表示当前页面在fragmentA中,当flag为2时表示当前页面在fragmentB中,只当handler收到消息并且flag=1时才能更新fragmentA中的数据。第二种方法实现起来比较繁锁,推荐使用第一种方法。其中1、2、3这些最好存放在一个枚举类型中。

[转]http://blog.csdn.net/wode_dream/article/details/41480271

访问UI线程

1)Activity.runOnUiThread(Runnable)

2)View.post(Runnable)

public void onClick(View v) {new Thread(new Runnable() {public void run() {final Bitmap b = loadImageFromNetwork();mImageView.post(new Runnable() {public void run() {mImageView.setImageBitmap(b);}});}}).start();
}

3)View.postDelayed(Runnable, long)

4)Handler

final Handler myHandler = new Handler();(new Thread(new Runnable() {@Overridepublic void run() {final Bitmap b = loadImageFromNetwork();myHandler.post(new Runnable() {                           @Overridepublic void run() {mImageView.setImageBitmap(b);}});}})).start();                
}

ListView嵌套 父ListView高度设置

        /*** 调整ListView嵌套后,根据子ListView的高度重设父ListView的高度* @param listView*/public static void setListViewHeightBasedOnChildren(ListView listView) {ListAdapter listAdapter = listView.getAdapter();if (listAdapter == null) {return;}int totalHeight = 0;for (int i = 0; i < listAdapter.getCount(); i++) {View listItem = listAdapter.getView(i, null, listView);listItem.measure(0, 0);totalHeight += listItem.getMeasuredHeight();}ViewGroup.LayoutParams params = listView.getLayoutParams();params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));listView.setLayoutParams(params);}

代码创建控件

    ImageView imageView = new ImageView(getActivity());//父控件是LinearLayoutLinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);//相当于android:layout_gravity属性  params.gravity = Gravity.CENTER_VERTICAL;imageView.setLayoutParams(params);imageView.setScaleType(ImageView.ScaleType.FIT_XY);Button button = new Button(getActivity());LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);button.setLayoutParams(params);//相当于android:gravity属性 button.setGravity(Gravity.CENTER_VERTICAL);linearLayout.addView(imageView);linearLayout.addView(button);

文本拼接

// %1表示第一个位置,$d表示数字,$s表示文本<string name="sale_comment_text1">%1$d】</string><string name="sale_comment_text2">%1$s评价%2$s</string>getString(R.string.sale_comment_text1,pojo.getCommentType())getString(R.string.sale_comment_text2,pojo.getCustomerName(),pojo.getSalesName())//    拼接文本为:【2】,张三评价李四

textAppearance

textAppearanceInverse/

textAppearanceLarge/

textAppearanceLargeInverse/

textAppearanceMedium/

textAppearanceSmallInverse/

textAppearanceMediumInverse/

textAppearanceSmall/

代码中加下划线
textView.getPaint().setFlags(Paint. UNDERLINE_TEXT_FLAG ); //下划线
textView.getPaint().setAntiAlias(true);//抗锯齿

转:http://www.cnblogs.com/-cyb/archive/2011/08/02/Android_textAppearance.html

gradle dependencies 设置 版本号

ext{compileLibVersion = '23.3.0'
}dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])testCompile 'junit:junit:4.12'compile "com.android.support:appcompat-v7:[$compileLibVersion]"
}

隐藏/移除ActionBar

    //隐藏掉整个ActionBar,包括下面的Tabs  getSupportActionBar().hide();//或requestWindowFeature(Window.FEATURE_NO_TITLE);  //会保留tab标签//高版本可以换成 ActionBar actionBar = getActionBar();  ActionBar actionBar = getSupportActionBar();actionBar.setDisplayShowTitleEnabled(false);  actionBar.setDisplayShowHomeEnabled(false);  

判断SDK版本

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {Window window = getWindow();// Translucent status barwindow.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);}

Android M运行权限问题

一行代码解决Android M新的运行时权限问题:
http://www.jianshu.com/p/d3a998ec04ad

Android Build.VERSION.SDK_INT兼容介绍

http://aijiawang-126-com.iteye.com/blog/1481572

这篇关于Android 杂技的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/442792

相关文章

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

Android逆向(反调,脱壳,过ssl证书脚本)

文章目录 总结 基础Android基础工具 定位关键代码页面activity定位数据包参数定位堆栈追踪 编写反调脱壳好用的脚本过ssl证书校验抓包反调的脚本打印堆栈bilibili反调的脚本 总结 暑假做了两个月的Android逆向,记录一下自己学到的东西。对于app渗透有了一些思路。 这两个月主要做的是代码分析,对于分析完后的持久化等没有学习。主要是如何反编译源码,如何找到

android系统源码12 修改默认桌面壁纸--SRO方式

1、aosp12修改默认桌面壁纸 代码路径 :frameworks\base\core\res\res\drawable-nodpi 替换成自己的图片即可,不过需要覆盖所有目录下的图片。 由于是静态修改,则需要make一下,重新编译。 2、方法二Overlay方式 由于上述方法有很大缺点,修改多了之后容易遗忘自己修改哪些文件,为此我们采用另外一种方法,使用Overlay方式。