注册

使用PullToRefreshListView代替ChatFragment里的SwipeRefreshLayout时出现的界面适配问题

在聊天界面ChatFragment里下拉刷新的控件使用的是google官方的SwipeRefreshLayout,当我换成PullToRefreshListView这个控件时,界面出现了不能随着键盘的弹出/收回自动适配界面的bug。此问题困扰了我两三天,google多次无果。

于是我写了个简单的demo,里面只有一个Activity,fragment。fragment布局上有个TextView充当TitleBar,下方有个EditText充当输入框,中间有个PullToRefreshListView充当聊天内容。当最外层布局为RelativeLayout时,随着键盘的弹出/收回,界面可以自适应。但是当最外层的布局为LinearLayout时,输入框被挤上去之后,就下不来了。到此,不敢说是PullToRefreshListView在fragment里有问题,因为毕竟这个控件的使用量非常大,如果有问题,不可能google不到同样的问题的。

最终在StackOverflow上发现一篇文章:点击http://stackoverflow.com/questions/25303285/activity-with-fragments-does-not-resize-when-the-keyboard-opens?answertab=votes#tab-top
这篇文章中提到了键盘弹出界面适配的原理:
1.如果界面上包含ListView,ScrollView,应用会缩放这两个view的尺寸以显示全部的内容。2.如果这方法不可用,则滚动整个view,以确保当前获取焦点的view不被遮挡。但是LinearLyout是不支持滚动的,所以1和2都无效。


When the soft keyboard appears on the screen, the amount of space available for the application's UI reduces. The system makes decision on how to organize the available space between the application's UI and soft keyboard.

If the window content contains ListView, ScrollView, the application's window is resized provided all the content is visible.
If re-sizing is not feasible, pan and scan approach is used, which simply involves scrolling the application's window so that the currently focused view is visible.

Since your layout does not contain any ListView, ScrollView, re-sizing is ruled out.

The window's root view is a FrameLayout to which you were originally adding LinearLayout. Since LinearLayout does not support scrolling, pan and scan approach is also ruled out. Hence wrapping the layout inside ScrollView solves the scrolling issue.


于是我想到了如果让RelativeLayout加上可以滚动的属性,是不是就能解决问题了。我的chatFragment布局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:background="#f2f0eb" >

<com.hyphenate.easeui.widget.EaseTitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleBarBackground="#F15645"
app:titleBarLeftImage="@drawable/back_icon"
app:titleBarRightImage="@drawable/ic_share" />

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/input_menu"
android:layout_below="@id/title_bar" >

<****.ease.widget.ChatMessageListLife
android:id="@+id/message_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<****.ease.widget.VoiceRecorderViewLife
android:id="@+id/voice_recorder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="invisible" />
</RelativeLayout>

<com.hyphenate.easeui.widget.EaseChatInputMenu
android:id="@+id/input_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />

</RelativeLayout>

ChatMessageListLife是继承自EaseChatMessageList
package *****.ease.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ListView;

import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.hyphenate.easeui.widget.EaseChatMessageList;
import ******.R;

public class ChatMessageListLife extends EaseChatMessageList {

protected static final String TAG = "EaseChatMessageList";
private PullToRefreshBase<ListView> ptrListView;

public ChatMessageListLife(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs);
}

public ChatMessageListLife(Context context, AttributeSet attrs) {
super(context, attrs);
}

public ChatMessageListLife(Context context) {
super(context);
}

protected void init(Context context) {
this.context = context;
LayoutInflater.from(context).inflate(
R.layout.ease_chat_message_list_life, this);
ptrListView = (PullToRefreshBase<ListView>) findViewById(R.id.listView1);
listView = ptrListView.getRefreshableView();
}

public PullToRefreshBase<ListView> getRefreshListView() {
return ptrListView;
}
}










R.layout.ease_chat_message_list_life就是我替换PullToRefreshListView的布局:
<?xml version="1.0" encoding="utf-8"?>
<com.handmark.pulltorefresh.library.PullToRefreshListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/listView1"
style="@style/pulltorefresh_style"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="alwaysScroll"
ptr:ptrMode="pullFromStart" >

</com.handmark.pulltorefresh.library.PullToRefreshListView>

 
现在重新回到chatFragment布局。最外层是RelativeLayout,于是我尝试着在chatFragment布局聊天内容的RelativeLayout中增加了
android:scrollbars="vertical"
    <RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/input_menu"
android:layout_below="@id/title_bar"
[b]android:scrollbars="vertical"[/b] >

<****.ease.widget.ChatMessageListLife
android:id="@+id/message_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<****.ease.widget.VoiceRecorderViewLife
android:id="@+id/voice_recorder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="invisible" />
</RelativeLayout>

这个属性。谢天谢地,it works.

5 个评论

发错了,应该发文章的,这个问题还删不掉。编辑器还超难用。
谢谢分享,很不错的一篇文章,问题我已经帮你删掉,编辑这块我重新给你编辑了下。已赞赏,快去提现看看
感谢~
42424
放松放松

要回复文章请先登录注册