总有那么些问题很常见又常忘,仅为了方便查看,主要介绍解决方法,原因不做过多说明,如有错误欢迎指正
禁止ScrollView 内容改变自动滚动(获取焦点)
修改布局文件方法
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/friend_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical" >
<!--......-->
</LinearLayout>
</ScrollView>
代码获取scrollView的 LinearLayout 进行设置
scrollView.getChildAt(0).setFocusable(ture);
scrollView.getChildAt(0).setFocusableInTouchMode(ture);
scrollView.getChildAt(0).requestFocus();
问题一般发生在ScrollView内嵌ListView等一些会获取焦点的控件,本质问题仅仅是焦点被内部控件获取的,通过.smoothScrollTo(0, 0)
在回到头部是不合理的
EditView 内容监听参数解读
Kotlin写法介绍, Java参考方法名注释
class MyTextWatcher(position: Int, id: Int) :TextWatcher {
override fun afterTextChanged(s: Editable?) {
//editView.getSelectionStart() 起始选中焦点, getSelectionEnd() 结束选中焦点 , 监听事件的start为起始焦点
//在TextWatcher中改变文本后需要重新设置焦点位置, 否则可能会焦点溢出崩溃 setSelection()
if (holder.itemView.name.text.length > 5)
holder.itemView.name.setSelection(0, 2)
Log.e(this.javaClass.simpleName + "ss", "afterTextChanged-- ${s.toString()}, " +
"selectStart: ${holder.itemView.name.selectionStart}, selectEnd: ${holder.itemView.name.selectionEnd}, " +
"name: ${holder.itemView.name.text.length}")
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
//s: 原始内容, start: 删除后(新增前)焦点 0开始, count: 删除数量, after: 新增数量
Log.e(this.javaClass.simpleName + "ss", "beforeTextChanged-- start: $start,count: $count, after: $after, ${s.toString()}")
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//s: 改变结果, start: 删除后(新增前)焦点, before: 删除数量, count: 新增数量
Log.e(this.javaClass.simpleName + "ss", "onTextChanged-- start: $start,before: $before, count: $count, ${s.toString()}")
}
})
需要注意的是EditText每次调用addTextChangedListener()
,这里是add不是set每次都会新增一个监听,不是替换掉原来的设置
关闭AlertDialog
AlertDialog.Builder 只有show()方法没有dismiss(),在create()或show()执行后会得到一个AlertDialog,即可执行dismiss()。了解设计模式一眼就可以看出是Builder
创建模式,本不是问题,看到用模拟back返回键的来关闭方法,好吧真会玩。
AlertDialog.Builder builder = newAlertDialog.Builder(this);
AlertDialog dialog = builder.show();
dialog.dismiss();
AlertDialog 更改默认按钮样式
AlertDialog有个getButton
方法可以获取三个默认按钮,之后就可以进行修改字体颜色之类的操作了
AlertDialog dialog = builder.create();
Button yBtn = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
Button nBtn = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
yBtn.setTextColor(getResource().getColor(R.color.green));
RecycleView 指定Item滚动到头部
类似ListView.smoothScrollToPositionFromTop()方法
Scroll RecyclerView to show selected item on top
RecycleView 刷新错误
判断RecycleView是否处于计算或滚动
!child_list.isComputingLayout() && (child_list.getScrollState() == RecyclerView.SCROLL_STATE_IDLE)
Handle 异步处理, 或者在ViewHolder中使用同一个监听器
问题一般发生RecycleAdapter在onBindViewHolder过程,为EditText添加TextWatcher
和CheckBox设置OnCheckedChangeListener
。当EditText内容或CheckBox状态改变,调用notifyDataSetChanged()刷新后,监听器发现内容又改变了,再次调用notifyDataSetChanged(),而此时RecycleView还处于计算布局状态,于是就报错了。即便不报错也会出现死循环,所以在RecycleView或ListView中慎用监听器。
Button 取消全部大写
android:textAllCaps="false"
Android 5.0 Button 去阴影
给Button添加stylestyle="?android:attr/borderlessButtonStyle"
或者android:stateListAnimator="@null"
borderlessButtonStyle
具体指向可以在源码的res目录下查看,在 themes_material
是style/Widget.Material.Light.Button.Borderless
添加默认点击效果
点击效果在不同Android版本是不同的,5.0以上是新增ripple
波纹效果,RelativeLayout等ViewGroup默认是没有点击效果的,一句话添加
android:background="?android:attr/selectableItemBackground"
删除ScrollView边界阴影方法方法
(1) 在xml中添加:android:fadingEdge=”none”
(2) 代码中添加:ScrollView.setHorizontalFadingEdgeEnabled(false);
(3)2.3及以上的 否则不用设置: android:overScrollMode="never"
模拟事件
Runtime runtime = Runtime.getRuntime();
//模拟返回键
runtime.exec("input keyevent " + KeyEvent.KEYCODE_BACK);
按键事件拦截
返回false表示拦截
//按下拦截
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
}
//松开拦截
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
switch (keyCode){
case KeyEvent.KEYCODE_BACK:
if (isRegister) {
//自定义处理
return false;
}
break;
}
return super.onKeyUp(keyCode, event);
}
注:无法拦截返回键关闭输入法
滚动条配置
TextView部分内容-设置高亮和点击
https://my.oschina.net/u/2283209/blog/465583
/**
* 关键字高亮显示
*
* @param target 需要高亮的关键字
* @param text 需要显示的文字
* @return spannable 处理完后的结果,记得不要toString(),否则没有效果
*/
public static SpannableStringBuilder highlight(String text, String target, final View.OnClickListener listener) {
SpannableStringBuilder spannable = new SpannableStringBuilder(text);
CharacterStyle span = null;
Pattern p = Pattern.compile(target);
Matcher m = p.matcher(text);
while (m.find()) {
//span = new ForegroundColorSpan(Color.RED);// 需要重复!
span = new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
//高亮颜色
ds.setColor(ds.linkColor);
//取消下滑线
ds.setUnderlineText(false);
}
@Override
public void onClick(View widget) {
if (listener != null)
listener.onClick(widget);
}
};
spannable.setSpan(span, m.start(), m.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannable;
}
//shop_treaty_tv.setText(text, BufferType.SPANNABLE);
//改变高亮颜色
shop_treaty_tv.setLinkTextColor(0xFFD8271C);
//设置高亮和点击事件
shop_treaty_tv.setText(highlight(shop_treaty_tv.getText().toString(), "《协议内容》", listenter));
shop_treaty_tv.setMovementMethod(LinkMovementMethod.getInstance());
输入法相关
设置android:windowFullscreen
后android:windowSoftInputMode的adjustResize
和adjustPan
将无效过
监听输入法状态
//输入模式
Log.e("softMode", "-" + getWindow().getAttributes().softInputMode);
//当前窗口是焦点
Log.e("focus", "-" + getCurrentFocus());
//输入法状态一直为true
Log.e("focus", "-" + inputMethodManager.isActive());
//EditView是输入的焦点
Log.e("focus", "-" + inputMethodManager.isActive(binding.mobileEdt));
//存在一个EditView有输入焦点
Log.e("focus", "-" + inputMethodManager.isAcceptingText());
ResultReceiver监听调用结果,设置Hander的作用仅为切换回调线程
new ResultReceiver(null){
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
switch (resultCode){
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
break;
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
break;
case InputMethodManager.RESULT_SHOWN:
//成功显示键盘回调
break;
case InputMethodManager.RESULT_HIDDEN:
//成功隐藏键盘回调
break;
}
Log.e("ResultReceiver", "-" + resultCode);
Log.e("ResultReceiver", "-" + resultData);
}
}
显示输入法
//显示软件盘
protected boolean showSoftKeyboard(View view){
final boolean[] isShow = {false};
if (view != null){
inputMethodManager.showSoftInput(view,
InputMethodManager.SHOW_FORCED, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == InputMethodManager.RESULT_SHOWN) {
//成功隐藏键盘回调
isShow[0] = true;
}
//Log.e("ResultReceiver", "-" + resultCode);
//Log.e("ResultReceiver", "-" + resultData);
}
}
);
}
return isShow[0];
}
隐藏输入法
//隐藏软键盘
protected boolean hideSoftKeyboard() {
final boolean[] isHide = {false};
if (getCurrentFocus() != null) {
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == InputMethodManager.RESULT_HIDDEN) {
//成功隐藏键盘回调
isHide[0] = true;
}
//Log.e("ResultReceiver", "-" + resultCode);
//Log.e("ResultReceiver", "-" + resultData);
}
}
);
}
return isHide[0];
}
切换显示隐藏
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
Android InputMethodManager输入法简介
获取状态栏高度
// 获取状态栏高度
public static int getStatusBarHeight(Context context) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
int x = Integer.parseInt(field.get(obj).toString());
return context.getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
Fragment 显示隐藏监听
分为三中情况,切换到其他Activity,FragmentTransaction切换,ViewPager中切换;
1). Activity 切换可在生命周期onResume,onPause中监听
2). FragmentTransaction 切换重写onHiddenChanged判断。
3). ViewPager 切换重写setUserVisibleHint 判断。
CoordinatorLayout RecycleView(NestedScrollView)滑动到顶部
Programmatically scroll to the top of a NestedScrollView
如何监听Activity生命周期
系统并没有直接监听Activity 生命周期的方法,那么换个思路新建一个没有视图的Fragment,添加Fragment到Activity ,监听Fragment的生命周期即可。
读取资源文件
文件类型 File、FileDescriptor、ParcelFileDescriptor
Returning an Input Stream from Parcel File Descriptor using Androids DownloadManager
how to get ParcelFileDescriptor for file content?
java io系列09之 FileDescriptor总结
ContentResolver contentResolver = context.getContentResolver();
// file:///android_asset/
// android.resource://package_name/type/resource_id
// Android.resource://package_name/type/resource_name
// eg. "android.resource://package_name/raw/" + R.raw.music
InputStream is = contentResolver.openInputStream(uri);
ParcelFileDescriptor rdesc = contentResolver.openAssetFileDescriptor(uri, "r").getParcelFileDescriptor();
ParcelFileDescriptor wdesc = contentResolver.openFileDescriptor(uri, "w");
渲染方式(硬件加速)
view.setLayerType(View.LAYER_TYPE_NONE, mPaint); //默认渲染
view.setLayerType(View.LAYER_TYPE_SOFTWARE, mPaint); //软件渲染
view.setLayerType(View.LAYER_TYPE_HARDWARE, mPaint); //硬件加速
xml配置
android:layerType="software"
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。转载请保留作者及原文链接