概述
1、获取全局Context
编写Application
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
//获取Context
context = getApplicationContext();
}
//返回
public static Context getContextObject(){
return context;
}
}
调用
MyApplication.getContextObject();
注:application需要注册
<application
android:name="包名.MyApplication"
....
>
2、使用autoLink属性 跳转网页,拨打电话,发送邮件等
只需android:autoLink=“web” 点击就能自动跳转网页,简单粗暴
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:text="www.jeean.cn "/>
只需android:autoLink=“phone” 点击就能自动拨打电话,一样的简单粗暴
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="phone"
android:text="18888888888"/>
3、代码中动态设置文字大小时,单位的问题
借助TypedValue设置单位
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);//14sp
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);//15dp
4、禁止EditText换行
singleLine已经过时,需要使用下面两个属性才能起到作用:
android:lines="1"
android:inputType="text"
5、recyclerview使用notifyDataSetChanged时,item里面EditText显示错乱或清空
解决方案有两种,这里只说一种最简单的,应为一般item里面使用EditText时,列表长度都是很有限的,所以直接禁止recyclerview的item的复用就行:
@Override
public void bindViewHolder(final FlexibleAdapter adapter, EntityViewHolder holder, final int position, List payloads) {
holder.setIsRecyclable(false);
...
holder.editText.setText(value);
holder.et_content.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
value = editable.toString();
}
});
}
6、recyclerview隐藏某个item后,该item仍然占位的问题
如果只是简单的设置隐藏,那么item虽然不可见了,但是其宽高依然占位,解决办法:
@Override
public void bindViewHolder(final FlexibleAdapter adapter, EntityViewHolder holder, final int position, List payloads) {
RecyclerView.LayoutParams param = (RecyclerView.LayoutParams) itemView.getLayoutParams();
itemView.setVisibility(View.GONE);
param.height = 0;
param.width = 0;
itemView.setLayoutParams(param);
}
7、TextView加载html并异步加载html中的网络图片
加载html一般使用webview,有一些情况,比如html比较简单或xml布局文件不适合嵌入webview,此时可以用TextView组件加载!
//适合加载纯文本
textView.setText(Html.fromHtml(html));
//可以加载带图片的html 如果是网络图片,还需要异步加载
textView.setText(Html.fromHtml(string, imgGetter, null));
第一种加载纯文本的情况不多说,下面重点说一说异步加载图片的情况:
public void parseHtml(final String html) {
final Html.ImageGetter imgGetter = new Html.ImageGetter() //格式语句不一定相同,只要进行网络加载图片即可
{
public Drawable getDrawable(String source)
{
Drawable drawable = null;
try
{
drawable = Drawable.createFromStream(new URL(source).openStream(), "");//加载网络图片资源核心语句
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getIntrinsicHeight());
}
catch (Exception e)
{
return new Drawable()
{
public void setColorFilter(ColorFilter cf) {}
public void setAlpha(int alpha) {}
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
public void draw(Canvas canvas) {}
};
}
return drawable;
}
};
new Thread(new Runnable()
{
@Override
public void run()
{
final Spanned text = Html.fromHtml(html,imgGetter,null);
handler.post(new Runnable()
{
@Override
public void run()
{
introServer.setText(text);
}
});
}
}).start();
}
}
8、沉浸式模式的实现
只有在Android 4.4及以上系统才支持沉浸式模式,需要重写Activity的onWindowFocusChanged()方法
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && Build.VERSION.SDK_INT >= 19) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
9、通过BaseActivity获取到当前启动的Activity名称
在onCreate里面实现下面的代码就行:
Logger.i("CurrentActivity","当前启动的Activity名称为: "+getClass().getSimpleName());
当前启动的Activity名称为: UXCarDetailActivity
当前启动的Activity名称为: GiveUpSeeCarActivity
10、App启动时黑屏或白屏的问题
不做任何处理,点开app时,会出现一瞬间的白屏或黑屏,解决办法是为启动页单独设置一个主题,如下:
@style/AppTheme.Launcher
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
为该主题设置属性android:windowBackground
<style name="AppTheme.Launcher" parent="AppTheme">
<item name="android:windowBackground">@drawable/xml_splash_logo</item>
</style>
xml_splash_logo.xml如下
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">
<item android:drawable="@android:color/white" />
<!--启动页展示之前 会先显示下面的图片 可以根据需求调整数量和样式-->
<item >
<bitmap
android:gravity="center"
android:src="@drawable/ud_splash_uxin_logo_normal" />
</item>
</layer-list>
11、GridView绘制行间分割线
需要自定义,重写dispatchDraw
方法即可:
public class CustomGridView extends GridView {
/**
* 绘制GirdView行间分割线: flag为true绘制,否则不绘制
*/
private boolean flag;
public void setFlag(boolean flag) {
this.flag = flag;
}
public CustomGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomGridView(Context context) {
super(context);
}
public CustomGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (flag){
customDraw(canvas);
}
}
/**
* 绘制GirdView行间分割线: flag为true绘制,否则不绘制
* @param canvas
*/
private void customDraw(Canvas canvas) {
Paint localPaint = new Paint();
localPaint.setStyle(Paint.Style.STROKE);
localPaint.setColor(getContext().getResources().getColor(R.color.base_D9D9D9));
int column = getNumColumns();
int childCount = getChildCount();
if (column < 1 || childCount <= column) {//只有一行或者没有列数不绘制
return;
}
int row = childCount % column == 0 ? childCount / column : childCount / column + 1;//行数
for (int i = 0; i < row - 1; i++) {
View view = getChildAt(i*column);//拿到第i行第一个子view来计算坐标位置
//getLeft() + DensityUtil.dip2px(view.getContext(), 20) 加号后面是为了绘制分割线左边距 不需要的可以去掉
//getRight() - DensityUtil.dip2px(view.getContext(), 20) 减号后面是右边距 不需要可以去掉
//view.getBottom() + CustomGridView.this.getVerticalSpacing()/2 绘制在每行底部 并考虑verticalSpace属性
canvas.drawLine(getLeft() + DensityUtil.dip2px(view.getContext(), 20), view.getBottom() + CustomGridView.this.getVerticalSpacing()/2, getRight() - DensityUtil.dip2px(view.getContext(), 20), view.getBottom() + CustomGridView.this.getVerticalSpacing()/2, localPaint);
}
}
}
12、实现ImageView宽度填满屏幕,高度自适应
这个还是比较简单的,主要是使用两个属性:
android:scaleType="fitXY"
它的意思是图片按照指定的大小在ImageView中显示,拉伸显示图片,不保持原比例
android:adjustViewBounds="true"
它的意思是保持宽高比
<ImageView
android:id="@+id/id_iv_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true"
/>
13、ConstraintLayout属性之Group
问题:当有多个group或者一个group多次设置setReferencedIds
时,Group控制的控件可能失效
原因:当group调用group.setVisibility(View.GONE)
, 触发重绘机制,内部会调用updatePreLayout(ConstraintLayout container)
方法,而其他状态setVisibility(View.VISIBLE)、setVisibility(View.INVISIBLE)
不会触发该方法!
解决方案:当调用group.setVisibility(View.VISIBLE)、group.setVisibility(View.INVISIBLE)
方法时,再调用一下group1.updatePreLayout(container)
方法(container时对应group所在的ConstraintLayout控件)即可!
示例
private void controlGroup() {
group.setReferencedIds(ids1);//ids1是group控制的组件id 是个数组
group.setVisibility(View.GONE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//5s之后先将原来隐藏的组件显示 改变控制的组件 再将其隐藏
group1.setVisibility(View.VISIBLE);
group1.updatePreLayout(cl3);
group1.setReferencedIds(ids2);
group1.setVisibility(View.GONE);
}
}, 5000);
}
14、Android 在使用WebView时页面显示不出来或显示空白
在我的项目里发现https
链接的就会出现这个问题,http
的没问题。解决办法如下:
webSetting.setDomStorageEnabled(true);//设置DOM Storage缓存
15、关于singleInstance模式的activity启动standard模式的activity的问题
- 如果当前进程中存在standard模式的activity,即:
standardA -> singleInstanceB -> standardA
, 这种是正常的,回退顺序是 A -> A -> B. - 如果当前进程中不存在standard模式的activity,如:
singleInstanceA -> standardB -> singleInstanceC -> standardB
, 这时候会有“异常”,理论上这时候回退的顺序是 BBCA, 而实际上B界面并没有再次创建,回退顺序是BCA.
无意中发现,特此记录。
16、解决ScrollView嵌套RecyclerView/ListView时顶部布局被顶出,RecyclerView抢占焦点的问题
解决办法也很简单,直接在ScrollView
的第一层子布局中加入以下代码
android:descendantFocusability="blocksDescendants"
descendantFocusability这个属性共有三个值可供选择:
blocksDescendants :覆盖所有子控件获取焦点(优先级最高)
beforeDescendants :优先于子控件获取焦点
afterDescendants :当子控件不需要焦点时,获取焦点
17、在部分Android手机(如oppoA59s)上webview显示白屏
部分Android手机上(如oppoA59s等)无法加载webview,经测试发现Android6.0以下都是白屏,原因是Android6.0以下webview不支持ES6语法,h5页面有部分代码没有转为ES5。
解决方案:让H5将所有ES6js语法转为ES5即可!
18、如何安全的手动终止线程
暂停、恢复和停止操作对应在线程Thread的API就是suspend()、resume()和stop(),他们都有一些问题,如suspend()挂起线程,线程锁同样挂起,容易造成死锁,stop()强制终止线程,容易造成资源来不及释放,造成内存泄漏!所以这些方法都已经废弃,不建议使用!
安全的终止线程的方法是调用线程的interrupt()
方法,并在被终止线程中调用isInterrupted()
方法进行判断!两个方法进行协作才可以终止线程!
public class TestThread {
public static void main(String[] args) throws ExecutionException, InterruptedException {
UseThread useThread = new UseThread();
useThread.start();
Thread.sleep(20);
useThread.interrupt();//在主线程睡眠20ms后 发出终止信号 需要配合isInterrupted()方法才有效
}
private static class UseThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("I am extends Thead!");
//isInterrupted(): if this thread has been interrupted, return true
// 在这里需要调用isInterrupted()进行判断 做一些资源关闭工作 如果不调用线程将不会被动终止
while (!isInterrupted()){
System.out.println("test interrupter!!!");
}
}
}
}
19、AndroidStudio编译失败如何定位问题
AndroidStudio编译代码有时会报Caused by: java.lang.RuntimeException
等难以判断问题原因的异常!如何定位问题:
打开AndroidStudio的terminal,在命令行输入命令:gradlew compileDebugSource --stacktrace -info
或gradlew assembleDebug --info
即可
20、EditText不显示光标的问题
原因:EditText行高定死,字体太大的缘故!
解决方案:减小字体或者增大行高或设置行高为wrap_content
。
如果还不生效,检查一下其外层布局是不是LinearLayout
,如果不是改为LinearLayout
21、EditText设置imeOptions/nextFocusForward不生效
EditText设置下一步时,出现无效的情况,检查一下是否设置android:singleLine="true"
,不过android:singleLine已经过时,可以进行如下设置:
android:lines="1"
android:inputType="text" //该属性可按需设置,如果没有要求就设置为text
22、string.xml里的转移字符的使用
xml里如果想使用%,不能直接单写一个符号,“”转义也不行,需要使用两个“%%”,即在xml里“%%”表示一个“%”
常见的转义字符还有:
$$—美元标志,%%—百分号,//—斜杠,’’—单引号等
23、ImageView倒圆角
不需要自定义View,自定义Drawable也能实现,而且更加简单、高效、使用范围更广,详见:
Android Drawable 那些不为人知的高效用法
24、Plurals的用法
plurals是value.xml中的一个标签属性,用于解决不同个数下使用不同字串的问题。
例如当有一条消息是显示“1 message”,多条时显示“n messages”.
在string.xml如下声明
<plurals name="ConversationAdapter_n_unread_messages">
<item quantity="one">%d new message</item>
<item quantity="other">%d new messages</item>
</plurals>
调用
mContext.getResources()
.getQuantityString(
R.plurals.ConversationAdapter_n_unread_messages, 1,1)
getQuantityString()方法的第一个参数是复数资源id,第二个参数选择要使用的字符串。第三个参数值为1时,按原样使用该字符串。当值不为1时,值放在%d所在的位置。如果在附属自愿中使用了一种格式化字符串,必须始终总有至少三个参数。第二个参数可能会令人困惑,这个参数的唯一差别就是值为1和不为1.
最后
以上就是如意水池为你收集整理的Android开发技巧总结的全部内容,希望文章能够帮你解决Android开发技巧总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复