119.Android 简单的软键盘和菜单无缝切换效果,聊天界面软键盘无缝切换

//此效果主要通过动态设置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---------------------------------------------------------------

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值