//此效果主要通过动态设置windowSoftInputMode三种状态的切换实现:SOFT_INPUT_ADJUST_NOTHING、SOFT_INPUT_ADJUST_PAN、SOFT_INPUT_ADJUST_RESIZE。
1.第一步 导入需要用到的依赖库:
//RecyclerView implementation 'com.android.support:recyclerview-v7:28.0.0' //RecyclerAdapter implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28'
2.第二步 新建SeamlessSwitchActivity页面,注意manifest里设置windowSoftInputMode为stateHidden|adjustResize:
//manifest:
<activity android:name=".phone.activity.SeamlessSwitchActivity" android:launchMode="singleTop" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden|adjustResize" tools:ignore="LockedOrientationActivity" />
//activity:
/** * @author CJF */ public class SeamlessSwitchActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener { private final LinearLayoutManager manager = new LinearLayoutManager(this); private final SdkAdapter adapter = new SdkAdapter(R.layout.sdk_item); private SystemKeyboardUtils systemKeyboardUtils; private View mSeamlessSwitchBottomLayout; private RecyclerView mSeamlessSwitchRecy; private ImageView mSeamlessSwitchMore; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_seamless_switch); mSeamlessSwitchMore = findViewById(R.id.mSeamlessSwitchMore); mSeamlessSwitchBottomLayout = findViewById(R.id.mSeamlessSwitchBottomLayout); mSeamlessSwitchRecy = findViewById(R.id.mSeamlessSwitchRecy); mSeamlessSwitchMore.setOnClickListener(this); mSeamlessSwitchRecy.setOnTouchListener(this); //软键盘布局监听 systemKeyboardUtils = new SystemKeyboardUtils(this, mSeamlessSwitchBottomLayout); systemKeyboardUtils.setOnKeyBoardListener(new SystemKeyboardUtils.OnKeyBoardListener() { @Override public void onShow(int height) { Log.e("TAG1231", "onShow height:" + height); //显示底部布局 systemKeyboardUtils.showBottomLayout(height); //列表反转后滑到底部,0即为底部 manager.scrollToPosition(0); //设置图片 mSeamlessSwitchMore.setImageResource(R.drawable.svg_sms_more); } @Override public void onHide(int height) { Log.e("TAG1231", "onHide height:" + height); //设置图片 mSeamlessSwitchMore.setImageResource(R.drawable.svg_keyboard); } }); //列表反转 manager.setReverseLayout(true); mSeamlessSwitchRecy.setLayoutManager(manager); mSeamlessSwitchRecy.setAdapter(adapter); //列表反转后滑到底部,0即为底部 manager.scrollToPosition(0); List<String> list = new ArrayList<>(); for (int i = 0; i < 20; i++) { list.add("数据" + i); } adapter.addData(list); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.mSeamlessSwitchMore: //判断软键盘是否开启 boolean show = systemKeyboardUtils.isShow(); Log.e("TAG1231", "show:" + show); if (show) { //隐藏软键盘 systemKeyboardUtils.hideSoftInput(); //切换图片 mSeamlessSwitchMore.setImageResource(R.drawable.svg_keyboard); } else { //开启软键盘 systemKeyboardUtils.showSoftInput(); //切换图片 mSeamlessSwitchMore.setImageResource(R.drawable.svg_sms_more); } break; default: break; } } /** * 触摸列表布局隐藏底部布局 * * @param v * @param event * @return */ @Override public boolean onTouch(View v, MotionEvent event) { //隐藏底部布局 boolean hideBottomLayout = systemKeyboardUtils.hideBottomLayout(); if (hideBottomLayout) { //切换图片 mSeamlessSwitchMore.setImageResource(R.drawable.svg_keyboard); } return false; } @Override protected void onDestroy() { super.onDestroy(); //移除布局监听 systemKeyboardUtils.onDestroy(); } }
3.第三步 新建SystemKeyboardUtils工具类:
/** * 软键盘布局监听 * * @author CJF */ public class SystemKeyboardUtils { /** * activity的根视图 */ private View rootView; /** * 纪录根视图的显示高度 */ private int rootViewVisibleHeight; /** * 判断软键盘是否开启 */ private boolean isShow = false; /** * 上下文 */ private Activity activity; /** * 需要显示与隐藏的底部布局 */ private View bottomLayout; /** * 动画时长 */ private final int animatorDuration = 300; private OnKeyBoardListener onKeyBoardListener; private final InputMethodManager imm; /** * @param activity 上下文 * @param bottomLayout 需要显示与隐藏的底部布局 */ public SystemKeyboardUtils(Activity activity, View bottomLayout) { this.activity = activity; this.bottomLayout = bottomLayout; //获取activity的根视图 rootView = activity.getWindow().getDecorView(); //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变 rootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); //软键盘管理 imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); } /** * 布局监听 */ private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = () -> { //获取当前根视图在屏幕上显示的大小 Rect r = new Rect(); rootView.getWindowVisibleDisplayFrame(r); int visibleHeight = r.height(); if (rootViewVisibleHeight == 0) { rootViewVisibleHeight = visibleHeight; return; } //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变 if (rootViewVisibleHeight == visibleHeight) { return; } //根视图显示高度变小超过200,可以看作软键盘显示了 if (rootViewVisibleHeight - visibleHeight > 200) { if (onKeyBoardListener != null) { onKeyBoardListener.onShow(rootViewVisibleHeight - visibleHeight); } rootViewVisibleHeight = visibleHeight; isShow = true; return; } //根视图显示高度变大超过200,可以看作软键盘隐藏了 if (visibleHeight - rootViewVisibleHeight > 200) { if (onKeyBoardListener != null) { onKeyBoardListener.onHide(visibleHeight - rootViewVisibleHeight); } rootViewVisibleHeight = visibleHeight; isShow = false; return; } }; /** * 判断软键盘是否开启 * * @return */ public boolean isShow() { return isShow; } /** * 显示底部布局 * * @param height */ public void showBottomLayout(int height) { //软键盘设置先动态设置为SOFT_INPUT_ADJUST_NOTHING 此时布局更改监听不到了 activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); //显示布局 bottomLayout.setVisibility(View.VISIBLE); //更改高度 ViewGroup.LayoutParams params = bottomLayout.getLayoutParams(); params.height = height; bottomLayout.setLayoutParams(params); //软键盘设置最后再设置为SOFT_INPUT_ADJUST_PAN 此时布局更改又能监听到了 activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); } /** * 隐藏底部布局 */ public boolean hideBottomLayout() { //底部布局隐藏与软键盘无显示的情况下 不执行 if (bottomLayout.getVisibility() == View.GONE && !isShow()) { return false; } //隐藏软键盘 hideSoftInput(); //设置为视图不可见,但占用布局空间 bottomLayout.setVisibility(View.INVISIBLE); //获取底部布局高度 int measuredHeight = bottomLayout.getMeasuredHeight(); //动画 final ValueAnimator foldAnimator = ValueAnimator.ofInt(measuredHeight, 0); foldAnimator.setDuration(animatorDuration); foldAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { //更改高度 final ViewGroup.LayoutParams lp = bottomLayout.getLayoutParams(); lp.height = (int) valueAnimator.getAnimatedValue(); bottomLayout.setLayoutParams(lp); } }); foldAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); //底部布局隐藏 bottomLayout.setVisibility(View.GONE); //软键盘设置最后再设置为SOFT_INPUT_ADJUST_RESIZE 此时布局更改又能监听到了 activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); } }); foldAnimator.start(); return true; } /** * 移除布局监听 */ public void onDestroy() { rootView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener); } /** * 隐藏软键盘 */ public void hideSoftInput() { if (imm == null) { return; } imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0); } /** * 开启软键盘 */ public void showSoftInput() { if (imm == null) { return; } imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); } public void setOnKeyBoardListener(OnKeyBoardListener onKeyBoardListener) { this.onKeyBoardListener = onKeyBoardListener; } public interface OnKeyBoardListener { void onShow(int height); void onHide(int height); } }
4.第四步 新建SdkAdapter适配器类,适配一些简单的数据:
public class SdkAdapter extends BaseQuickAdapter<String, BaseViewHolder> { public SdkAdapter(int layoutResId) { super(layoutResId); } @Override protected void convert(BaseViewHolder helper, String item) { helper.setText(R.id.mOppoSdkTextPosition, String.valueOf(helper.getAdapterPosition())); helper.setText(R.id.mOppoSdkText, item); } }
5.第五步 各个xml布局文件,以及svg图片资源文件:
//activity_seamless_switch:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/mSeamlessSwitchRecy" android:layout_width="match_parent" android:layout_weight="1" android:layout_height="0dp"/> <LinearLayout android:background="@drawable/background_white" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <ImageView android:id="@+id/mSeamlessSwitchMore" android:layout_width="0dp" android:layout_height="@dimen/dp_50" android:layout_gravity="center" android:layout_weight="1" android:background="@drawable/background_white" android:padding="@dimen/dp_8" android:src="@drawable/svg_keyboard" /> <EditText android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/dp_20" android:layout_marginTop="@dimen/dp_20" android:layout_marginRight="@dimen/dp_20" android:layout_weight="5" android:background="@drawable/sms_details_bg" android:gravity="center|left" android:hint="输入" android:maxHeight="@dimen/dp_200" android:minHeight="@dimen/dp_40" android:paddingBottom="@dimen/dp_10" android:paddingLeft="@dimen/dp_10" android:paddingTop="@dimen/dp_10" android:textColor="@color/black" android:textColorHint="@color/color_657091" android:textSize="@dimen/sp_15" /> </LinearLayout> <TextView android:visibility="gone" android:gravity="center" android:text="内容布局" android:id="@+id/mSeamlessSwitchBottomLayout" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> </LinearLayout>
//sdk_item:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/dp_5" android:layout_marginLeft="@dimen/dp_20" android:layout_marginRight="@dimen/dp_20" android:layout_marginTop="@dimen/dp_5" android:background="@drawable/selector_common_item" android:gravity="center" android:orientation="horizontal"> <TextView android:id="@+id/mOppoSdkTextPosition" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:background="@drawable/selector_common_item" android:gravity="center" android:minHeight="@dimen/dp_50" android:padding="@dimen/dp_10" android:text="0" android:textColor="@color/black" android:textSize="@dimen/sp_15" /> <TextView android:id="@+id/mOppoSdkText" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="8" android:background="@drawable/selector_common_item" android:gravity="left|center_vertical" android:minHeight="@dimen/dp_50" android:padding="@dimen/dp_10" android:text="text" android:textColor="@color/black" android:textSize="@dimen/sp_15" /> </LinearLayout>
//svg图片文件 svg_keyboard:
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:tint="#E7E9EF" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="#ffffffff" android:pathData="M20,5L4,5c-1.1,0 -1.99,0.9 -1.99,2L2,17c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,7c0,-1.1 -0.9,-2 -2,-2zM11,8h2v2h-2L11,8zM11,11h2v2h-2v-2zM8,8h2v2L8,10L8,8zM8,11h2v2L8,13v-2zM7,13L5,13v-2h2v2zM7,10L5,10L5,8h2v2zM16,17L8,17v-2h8v2zM16,13h-2v-2h2v2zM16,10h-2L14,8h2v2zM19,13h-2v-2h2v2zM19,10h-2L17,8h2v2z" /> </vector>
// svg图片文件 svg_sms_more:
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:alpha="0.85" android:autoMirrored="true" android:tint="#E7E9EF" android:viewportHeight="24" android:viewportWidth="24"> <path android:fillColor="#ffffffff" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z" /> </vector>
//-----------------------------------------------------------END---------------------------------------------------------------