如何在键盘弹出时将整个视图向上推动,需要哪些布局更改?

8

当键盘弹出时,我遇到了将整个可回收视图推上去的麻烦,这会导致之前的消息被截断。我创建了一个类似于以下xml的聊天视图:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/commentsParentLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/noCommentsResults"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/lineSep"
        android:layout_alignParentTop="true"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:text="@string/noCommentsFound"
        android:textSize="20sp"
        android:visibility="gone" />

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToLoadMore"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/lineSep"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginTop="50dp"
        android:paddingBottom="10dp">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/comments_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="none"
            />
    </android.support.v4.widget.SwipeRefreshLayout>

    <View
        android:id="@+id/lineSep"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_above="@+id/commentsAddLayout"
        android:background="@color/horizontalLine" />

    <LinearLayout
        android:id="@+id/commentsAddLayout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:gravity="center"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/emojiSelector"
            android:layout_width="0dp"
            android:layout_height="36dp"
            android:layout_weight="1"
            android:src="@drawable/emoji" />

        <EditText
            android:id="@+id/commentText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_weight="4"
            android:background="@android:color/transparent"
            android:hint="@string/add_comment"
            android:maxLength="150" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:background="@color/horizontalLine" />

            <TextView
                android:id="@+id/sendComment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="@string/send"
                android:textSize="18sp" />
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

以下是我的 RecyclerView 代码:

 private void setupAdapter() {

        //stops lag for recycler view for load
        commentsRecyclerView.setHasFixedSize(true);
        commentsAdapter = new CommentsAdapter(this, dbCommentsList, TypeFaceProvider.getTypeFace(this, 0),
                TypeFaceProvider.getTypeFace(this, 1), TypeFaceProvider.getTypeFace(this, 2));
        LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
        mLayoutManager.setReverseLayout(true);
        mLayoutManager.setStackFromEnd(true);

        commentsRecyclerView.setLayoutManager(mLayoutManager);

        commentsRecyclerView.setItemAnimator(new DefaultItemAnimator());

        commentsAdapter.setOnEntryClickListener(new CommentsAdapter.OnEntryClickListener() {
            @Override
            public void onEntryClick(View view, int position) {
                DatabaseComment comment = dbCommentsList.get(position);
                TextView deleteBtn = (TextView) view.findViewById(R.id.commentUserRemove);
                if (view == deleteBtn) {

                    //used to remove the comment from db and the list
                    db.removeSingleComment(comment);
                    dbCommentsList.remove(position);
                    commentsAdapter.notifyDataSetChanged();

                } else {
                    takeToUserProfile(dbCommentsList.get(position));
                }
            }
        });

        commentsRecyclerView.setAdapter(commentsAdapter);
        commentsRecyclerView.scrollToPosition(0);

        hideProgressDialog();
    }

这是我的评论适配器:
public class CommentsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static OnEntryClickListener mOnEntryClickListener;
    private List<DatabaseComment> dbCommentsList;
    private Typeface typeFace, italicTypeface, boldTypeface;

    public CommentsAdapter(Context mContext, List<DatabaseComment> comments, Typeface myTypeface, Typeface myTypefaceItalic, Typeface myTypefaceBold) {
        Context context = mContext;
        dbCommentsList = comments;
        typeFace = myTypeface;
        italicTypeface = myTypefaceItalic;
        boldTypeface = myTypefaceBold;
    }

    public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
        mOnEntryClickListener = onEntryClickListener;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case 0:
                return new MyFeatureViewHolder(LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.comment_business_item, parent, false));
            case 1:
                return new MyViewHolder(LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.comment_user_item, parent, false));
        }

        return new MyViewHolder(LayoutInflater.from(parent.getContext())
                .inflate(R.layout.comment_user_item, parent, false));


    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        int pos = getItemViewType(position);

        //is a business comment
        if (pos == 0) {
            MyFeatureViewHolder featureViewHolder = (MyFeatureViewHolder) holder;

            DatabaseComment dbComment = dbCommentsList.get(position);

            featureViewHolder.commentCompany.setTypeface(boldTypeface);
            featureViewHolder.commentCompanyMsg.setTypeface(typeFace);
            featureViewHolder.commentCompanyDate.setTypeface(italicTypeface);

            featureViewHolder.commentCompany.setText(dbComment.getUsername());
            featureViewHolder.commentCompanyMsg.setText(dbComment.getCommentText());

            Calendar date = Calendar.getInstance();
            date.setTimeInMillis(dbComment.getCommentDate());
            int newMonth = date.get(Calendar.MONTH) + 1;
            String commentDateTxt = (newMonth + "." + date.get(Calendar.DAY_OF_MONTH) + "." + date.get(Calendar.YEAR));

            featureViewHolder.commentCompanyDate.setText(commentDateTxt);


        }



        //anything greater than 0 is a user comment - with emoji
        if (pos == 1) {
            MyViewHolder myViewHolder = (MyViewHolder) holder;

            if (dbCommentsList.get(position).getIsChanged() == 1) {
                myViewHolder.commentUserRemove.setVisibility(View.VISIBLE);
            } else {
                myViewHolder.commentUserRemove.setVisibility(View.GONE);
            }

            DatabaseComment dbComment = dbCommentsList.get(position);

            myViewHolder.commentUsername.setTypeface(boldTypeface);
            myViewHolder.commentUserMsg.setTypeface(typeFace);
            myViewHolder.commentUserDate.setTypeface(italicTypeface);

            myViewHolder.commentUsername.setText(dbComment.getUsername());
            myViewHolder.commentUserMsg.setText(dbComment.getCommentText());

            Calendar date = Calendar.getInstance();
            date.setTimeInMillis(dbComment.getCommentDate());

            //Note only one plus one because of new comments added will
            int newMonth = date.get(Calendar.MONTH) + 1;
            String commentDateTxt = (newMonth + "." + date.get(Calendar.DAY_OF_MONTH) + "." + date.get(Calendar.YEAR));

            myViewHolder.commentUserDate.setText(commentDateTxt);

            int[] commentsImageList = new int[]{R.drawable.e1, R.drawable.e1, R.drawable.e2, R.drawable.e3, R.drawable.e4,
                    R.drawable.e5, R.drawable.e6, R.drawable.e7, R.drawable.e8, R.drawable.e9, R.drawable.e10,
                    R.drawable.e11, R.drawable.e12, R.drawable.e13, R.drawable.e14,
                    R.drawable.e15, R.drawable.e16, R.drawable.e17, R.drawable.e18, R.drawable.e19};
            myViewHolder.emojiIcon.setImageResource(commentsImageList[dbComment.getIsType()]);


        }


    }

    @Override
    public int getItemCount() {
        return dbCommentsList.size();
    }

    @Override
    public int getItemViewType(int position) {
        if (dbCommentsList.get(position).getIsType() == 0) {
            return 0;
        } else {
            return 1;
        }
    }


    public interface OnEntryClickListener {
        void onEntryClick(View view, int position);
    }

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView commentUsername, commentUserMsg, commentUserDate, commentUserRemove;
        public ImageView emojiIcon;


        public MyViewHolder(View view) {
            super(view);
            commentUsername = (TextView) view.findViewById(R.id.commentUsername);
            commentUserMsg = (TextView) view.findViewById(R.id.commentUserMsg);
            commentUserDate = (TextView) view.findViewById(R.id.commentUserDate);
            commentUserRemove = (TextView) view.findViewById(R.id.commentUserRemove);
            emojiIcon = (ImageView) view.findViewById(R.id.emojiIcon);

            view.setOnClickListener(this);
            commentUserRemove.setOnClickListener(this);

        }

        @Override
        public void onClick(View v) {
            if (mOnEntryClickListener != null) {
                mOnEntryClickListener.onEntryClick(v, getAdapterPosition());

            }
        }
    }

    public class MyFeatureViewHolder extends RecyclerView.ViewHolder {
        public TextView commentCompany, commentCompanyMsg, commentCompanyDate;
        public ImageView emojiIcon;


        public MyFeatureViewHolder(View view) {
            super(view);
            commentCompany = (TextView) view.findViewById(R.id.commentCompany);
            commentCompanyMsg = (TextView) view.findViewById(R.id.commentCompanyMsg);
            commentCompanyDate = (TextView) view.findViewById(R.id.commentCompanyDate);
            emojiIcon = (ImageView) view.findViewById(R.id.emojiIcon);


        }


    }
}

当选择编辑文本框时,列表视图中的消息不会向上移动,但发送按钮和其他内容会向上移动,因此我不确定需要做什么才能推送评论视图?看起来可能是布局问题,但是尝试其他答案中的解决方法并没有解决我的问题:
解决方法1: adjustpan将视图向上推得太高,超过了电池和状态栏中的时间,并在键盘弹出时略微剪裁了视图底部。
解决方法2: adjustresize没有任何作用,视图仍然保持不变。

最后一个布局必须正确地对齐到底部。为了实现这一点。 - Zar E Ahmer
你能详细说明一下吗?我需要添加什么呢?谢谢! - Lion789
你想从底部推上来的部分必须正确地与底部对齐,否则它的一半视图会被裁剪或者它无法向上推。 - Zar E Ahmer
所以它与底部对齐并且看起来正确。我在相对布局中将其与父项底部对齐... 我是否遗漏了什么?另外,您知道为什么adjust pan会截断它 - 以及如何避免adjust pan覆盖菜单栏顶部。 - Lion789
好的,它并没有改变任何东西,虽然进行了这些更改,布局看起来仍然相同,但它仍然会截断底部视图的一部分,并且评论会覆盖状态栏。 - Lion789
显示剩余2条评论
1个回答

6
如果您希望在软键盘打开时调整内容大小,请使用adjust resize。
<application ... >
    <activity
        android:windowSoftInputMode="adjustResize" ... >
        ...
    </activity>
    ...
</application>

如果您想让屏幕顶部获得推动效果,请在清单文件中使用 adjustPan。
<application ... >
    <activity
        android:windowSoftInputMode="adjustPan" ... >
        ...
    </activity>
    ...
</application>

2
第一个不会对其产生任何影响,情况相同,而进行第二个操作会有一定效果,但会截断聊天框底部的一部分,并且电池和时间状态栏会覆盖顶部评论。 - Lion789
@Lion789 你需要将整个内容包装在类似于NestedScrollView的可滚动视图中。否则,adjustResize不会起作用。是的,AdjustPan只能像那样工作。 - Oğuzhan Döngül
滚动视图必须是父级视图还是包裹在线性布局中的所有内容?我用滚动视图包裹了所有内容 - 现在我的“发送”和底部栏在启动时移到了最顶部,键盘也立即弹出... - Lion789
1
@Lion789 我不知道你的问题具体是什么,但对我来说,在我的 ScrollView 中添加 android:fitsSystemWindows="true" 解决了我的问题。现在它的工作方式就像我预期的那样。 - Sufian
@oguzhand 这个解决方案非常好,但我需要像这里建议的那样添加 android:fitsSystemWindows="true"。它需要添加到可滚动的视图中。 - Sufian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接