Android程序员面试宝典
自定义控件
- 一分钟实现贴纸功能
- 一分钟实现TextView高亮
- 一分钟实现新手引导页
- 一分钟实现ViewPager卡片
- 一分钟实现轮播图
- 一分钟实现GridView拖拽
- 一分钟实现底部导航栏
- 一分钟实现底部FragmentTabhost
- 一分钟实现多张图片选择
- 一分钟实现仿美拍直播的点赞动画
- 一分钟实现高仿今日头条视频列表
- 一分钟实现购物车加减控件
- 一分钟实现省市县三级联动
- 一分钟实现二维码生成和扫描
- 一分钟实现沉浸式状态栏
- 一分钟实现图片裁剪
- 一分钟实现视频弹幕
- 一分钟实现图片缩放
- 一分钟实现旋转选择器
- 一分钟实现ofo小黄车的引导界面
- 一分钟实现自定义ImageView外貌
- 一分钟实现向左拖拽跳转详情页
- 一分钟实现QQ首页动画特效
- 一分钟实现ViewPager上下滑动
联网
- 一分钟学会Retrofit并且进行实战
- 一分钟实现OkHttp3
工具
- 一分钟实现RecyclerView
- 一分钟实现H5和Android通信
- 一分钟实现pinyin4j
- 一分钟实现分析内存泄漏
数据库
- 一分钟实现LitePal数据库
- 一分钟实现ormlite数据库
- 一分钟实现GreenDao数据库
源码分析相关面试题
- Volley源码分析
- 注解框架实现原理
- okhttp3.0源码分析
- onSaveInstanceState源码分析
- 静默安装和源码编译
Activity相关面试题
- 保存Activity的状态
- 深刻剖析activity启动模式(一)
- 深刻剖析activity启动模式(二)
- 深刻剖析activity启动模式(三)
- Activity Task和Process之间的关系
- 源码分析service开启Activity抛异常?activity不会抛异常
- Activity优雅退出
- onCreate源码分析
Service相关面试题
- IntentService源码分析
- Service是否在main thread中执行, service里面是否能执行耗时的操作?
- Service不死之身
与XMPP相关面试题
- XMPP协议优缺点
- 极光消息推送原理
与性能优化相关面试题
- 内存泄漏和内存溢出区别
- UI优化和线程池实现原理
- 代码优化
- 内存性能分析
- 内存泄漏检测
- App启动优化
- 与IPC机制相关面试题
与登录相关面试题
- oauth认证协议原理
- token产生的意义
- 微信扫一扫实现原理
与开发相关面试题
- 迭代开发的时候如何向前兼容新旧接口
- 手把手教你如何解决as jar包冲突
- context的原理分析
- 解决ViewPager.setCurrentItem中间很多页面切换方案
- 字体适配
- 软键盘适配
- 机型适配,例如三星、小米、华为、魅族等
- CardView 设置水波纹效果
与人事相关面试题
- 人事面试宝典
错误的打开方式
错误的打开姿势.gif
解决方法一:
最外层套ScrollView,控件多的时候可以自由滚动。
效果如下图:
套了ScrollView之后,虽然可以滚动了,马马虎虎也算解决了问题。
解决方法二:优雅解决
在activity当中调用setScroll();
//键盘不遮挡按钮
private void setScroll() {
KeyboardUtil.assistActivity(this, R.id.scroll_view); //这个是别人给我的工具类,只用这个会有
parent.setOnTouchListener(new View.OnTouchListener() { //parent为Editext外面那层布局
@Override
public boolean onTouch(View v, MotionEvent event) {
parent.setFocusable(true);
parent.setFocusableInTouchMode(true);
parent.requestFocus();
InputMethodManager imm = (InputMethodManager) MainActivity.this
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(account.getWindowToken(), 0); //隐藏键盘,account为Editext,随便一个就好
return false;
}
});
scroll.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { //scroll为parent外面那层布局()最好用NestedScrollView,ScrollView会有版本问题
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
v.scrollTo(0,450); //这个是滑动距离,随便大一点就好
}
});
}
键盘工具类:
public class KeyboardUtil {
private static final String TAG = "KeyboardUtil";
public static void assistActivity(Activity activity, int viewId) {
new KeyboardUtil(activity, viewId);
}
private View mChildOfContent;
private NestedScrollView mScrollView;
private RelativeLayout.LayoutParams relativeLayoutParams;
private KeyboardUtil(Activity activity, int viewId) {
FrameLayout content = (FrameLayout) activity
.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
mScrollView = (NestedScrollView) content.findViewById(viewId);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
}
private void possiblyResizeChildOfContent() {
int contentHeight = mChildOfContent.getRootView().getHeight();
int curDisplayHeight = computeUsableHeight();
if (contentHeight - curDisplayHeight > contentHeight / 4) {
Log.e(TAG, "possiblyResizeChildOfContent: 1" );
mScrollView.scrollTo(0,600);
// mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
} else {
Log.e(TAG, "possiblyResizeChildOfContent: 2" );
}
}
/**
* 获取屏幕可显示区域高度
*
* @return
*/
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return r.height();
}
}
自定义布局:
public class KeyboardLayout extends FrameLayout {
private KeyboardLayoutListener mListener;
private boolean mIsKeyboardActive = false; //输入法是否激活
private int mKeyboardHeight = 0; // 输入法高度
public KeyboardLayout(Context context) {
this(context, null, 0);
}
public KeyboardLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public KeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 监听布局变化
getViewTreeObserver().addOnGlobalLayoutListener(new KeyboardOnGlobalChangeListener());
}
public void setKeyboardListener(KeyboardLayoutListener listener) {
mListener = listener;
}
public KeyboardLayoutListener getKeyboardListener() {
return mListener;
}
public boolean isKeyboardActive() {
return mIsKeyboardActive;
}
/**
* 获取输入法高度
*
* @return
*/
public int getKeyboardHeight() {
return mKeyboardHeight;
}
public interface KeyboardLayoutListener {
/**
* @param isActive 输入法是否激活
* @param keyboardHeight 输入法面板高度
*/
void onKeyboardStateChanged(boolean isActive, int keyboardHeight);
}
private class KeyboardOnGlobalChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {
int mScreenHeight = 0;
private int getScreenHeight() {
if (mScreenHeight > 0) {
return mScreenHeight;
}
mScreenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getHeight();
return mScreenHeight;
}
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
// 获取当前页面窗口的显示范围
((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int screenHeight = getScreenHeight();
int keyboardHeight = screenHeight - rect.bottom; // 输入法的高度
boolean isActive = false;
if (Math.abs(keyboardHeight) > screenHeight / 4) {
isActive = true; // 超过屏幕五分之一则表示弹出了输入法
mKeyboardHeight = keyboardHeight;
}
mIsKeyboardActive = isActive;
if (mListener != null) {
mListener.onKeyboardStateChanged(isActive, keyboardHeight);
}
}
}
}
当前Activity清单文件配置:
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
欢迎关注微信公众号,长期推荐技术文章和技术视频
微信公众号名称:Android干货程序员