本文主要是介绍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
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中舍入法:
- ROUND_UP:远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。
- ROUND_DOWN:趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。
- ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。
- ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。
- HALF_UP:最近数字舍入(5进)。这是我们最经典的四舍五入。
- HALF_DOWN:最近数字舍入(5舍)。在这里5是要舍弃的。
- 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
- 在attrs.xml文件中定义
<resources><declare-styleable name="app"><attr name="toolbarHeight" format="dimension" /></declare-styleable>
</resources>
- 在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>
- 在布局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达到闪屏页的效果。
- 闪屏主题
<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>
- 闪屏界面背景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>
- 主界面设置主题
<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>
- 主界面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 设置和取消删除线的两种方法
设置删除线
- (推荐)通过按位或运算符|,将 TextView 原本的 Flags 属性和删除线一块设置。setPaintFlags内会对 TextView 进行重绘。
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
- 获取画笔后设置属性,重绘 TextView 。此方式有个问题,会把 TextView 原本的 Flags 属性替代,例如抗锯齿等。仔细查看,你会发现通过这种方式,文字有了锯齿。
tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
tv.invalidate();
取消删除线
- (推荐)先对 Paint.STRIKE_THRU_TEXT_FLAG 属性取反,再用按位与运算符&,除去了删除线属性并保留了 TextView 原本的 Flags 属性。setPaintFlags内会对 TextView 进行重绘。
tv.setPaintFlags(tv.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
- 获取画笔后,清空 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 常用尺寸
密度 | ldpi | mdpi | hdpi | xhdpi | xxhdpi | xxxhdpi |
---|---|---|---|---|---|---|
比例 | 0.75 | 1 | 1.5 | 2 | 3 | 4 |
密度数 | 120dpi | 160dpi | 240dpi | 320dpi | 480dpi | 640dpi |
代表分辨率 | 240*320 | 320*480 | 480*800 | 720*1280 | 1080*1920 | 1440*2560 |
Launcher And Home | 36*36 | 48*48 | 72*72 | 96*96 | 144*144 | 192*192 |
Action Bar And Tab | 24*24 | 32*32 | 48*48 | 64*64 | 96*96 | 128*128 |
Notification | 18*18 | 24*24 | 36*36 | 48*48 | 72*72 | 96*96 |
Background | 320*426 | 320*470 | 480*640 | 720*1280 | 1080*1920 | 1440*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 杂技的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!