您的位置:首页 > 移动开发 > Android开发

【android】ListView 的 transcriptMode 选项

2017-01-13 16:47 483 查看
默认情况下,当添加的 Item 超出 ListView 的范围后,ListView 并没有刷新让最新一条显示出来。而在 qq/微信 聊天中,发新的消息后会自动滚动显示出最下面的一条信息。

调用方式

AbsListView.java:
public int getTranscriptMode()   // 用于查询当前的 transcript 模式
1
1
void setTranscriptMode(int mode)   // 用于设置 transcript 模式
1
1
AbsListView.TRANSCRIPT_MODE_DISABLED    // 禁用
AbsListView.TRANSCRIPT_MODE_NORMAL   // 正常状态
AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL   // 总是滚动到最新一条
1
2
3
1
2
3

布局文件设置

<ListView android:id="@+id/lv_test"
android:layout_width="match_parent"
android:layout_height="300dp"
<!-- 以下模式只能选一种 -->
android:transcriptMode="normal"
android:transcriptMode="disabled"
android:transcriptMode="alwaysScroll"
>
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8

源码分析

获取当前模式:
/**
* Returns the current transcript mode.
*
* @return {@link #TRANSCRIPT_MODE_DISABLED}, {@link #TRANSCRIPT_MODE_NORMAL} or
*         {@link #TRANSCRIPT_MODE_ALWAYS_SCROLL}
*/
public
4000
int getTranscriptMode() {
return mTranscriptMode;
}
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
设置模式:
/**
* Puts the list or grid into transcript mode. In this mode the list or grid will always scroll
* to the bottom to show new items.
*
* @param mode the transcript mode to set
*
* @see #TRANSCRIPT_MODE_DISABLED
* @see #TRANSCRIPT_MODE_NORMAL
* @see #TRANSCRIPT_MODE_ALWAYS_SCROLL
*/
public void setTranscriptMode(int mode) {
mTranscriptMode = mode;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
根据 mTranscriptMode 的值来对应设置 mLayoutMode 的状态: 
如果是 TRANSCRIPT_MODE_ALWAYS_SCROLL:则 强制 从 ListView 的底部开始刷新;
如果是 TRANSCRIPT_MODE_NORMAL:如果当前的最后一个 Item 在 ListView 显示范围内,adapter 数据集内容变化时就从滚动底部;否则不滚动到底部!

@Override
protected void handleDataChanged() {
... 省略 ...
if (mTranscriptMode == TRANSCRIPT_MODE_ALWAYS_SCROLL) {
mLayoutMode = LAYOUT_FORCE_BOTTOM;
return;
} else if (mTranscriptMode == TRANSCRIPT_MODE_NORMAL) {
if (mForceTranscriptScroll) {
mForceTranscriptScroll = false;
mLayoutMode = LAYOUT_FORCE_BOTTOM;
return;
}
final int childCount = getChildCount();
final int listBottom = getHeight() - getPaddingBottom();
final View lastChild = getChildAt(childCount - 1);
final int lastBottom = lastChild != null ? lastChild.getBottom() : listBottom;
if (mFirstPosition + childCount >= lastHandledItemCount &&
lastBottom <= listBottom) {
mLayoutMode = LAYOUT_FORCE_BOTTOM;
return;
}
// Something new came in and we didn't scroll; give the user a clue that
// there's something new.
awakenScrollBars();
}
... 省略 ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mSelector == null) {
useDefaultSelector();
}
final Rect listPadding = mListPadding;
listPadding.left = mSelectionLeftPadding + mPaddingLeft;
listPadding.top = mSelectionTopPadding + mPaddingTop;
listPadding.right = mSelectionRightPadding + mPaddingRight;
listPadding.bottom = mSelectionBottomPadding + mPaddingBottom;

// Check if our previous measured size was at a point where we should scroll later.
if (mTranscriptMode == TRANSCRIPT_MODE_NORMAL) {
final int childCount = getChildCount();
final int listBottom = getHeight() - getPaddingBottom();
final View lastChild = getChildAt(childCount - 1);
final int lastBottom = lastChild != null ? lastChild.getBottom() : listBottom;
mForceTranscriptScroll = mFirstPosition + childCount >= mLastHandledItemCount &&
lastBottom <= listBottom;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

实例

test_list_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ListView android:id="@+id/lv_test"
android:layout_width="match_parent"
android:layout_height="300dp"
>
</ListView>
<Button android:id="@+id/btn_add_item"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="增加新 item"
/>
<Button android:id="@+id/btn_set_disable"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="不滚动"
/>
<Button android:id="@+id/btn_set_normal"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="如果最后Item在显示范围内就滚动"
/>
<Button android:id="@+id/btn_set_always"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="总是滚动到最新一条"
/>

</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
MainActivity.java:
public class MainActivity extends Activity {

ArrayList<String> mItemStrArr = new ArrayList<>();
ArrayAdapter mAdapter;
int i = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_list_view);

this.testListViewTranscriptMode();
}

void testListViewTranscriptMode(){
Button btnAddItem = (Button) this.findViewById(R.id.btn_add_item);

Button btnSetDisable = (Button) this.findViewById(R.id.btn_set_disable);
Button btnSetNormal = (Button) this.findViewById(R.id.btn_set_normal);
Button btnSetAlways = (Button) this.findViewById(R.id.btn_set_always);

ListView lv = (ListView)this.findViewById(R.id.lv_test);
// 实例化对象
mAdapter = new ArrayAdapter(this, R.layout.test_item, R.id.tv_content, mItemStrArr);
// 设置适配器
lv.setAdapter(mAdapter);
btnAddItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemStrArr.add("item_" + i++);
mAdapter.notifyDataSetChanged();
}
});
// 设置监听
btnSetDisable.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ListView lv = (ListView)MainActivity.this.findViewById(R.id.lv_test);
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED);
}
});
btnSetNormal.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ListView lv = (ListView)MainActivity.this.findViewById(R.id.lv_test);
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_NORMAL);
}
});
btnSetAlways.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ListView lv = (ListView)MainActivity.this.findViewById(R.id.lv_test);
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
效果图: 
disable 状态: 



normal 状态: 



always 状态: 





顶0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: