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

【android】ListView 的 transcriptMode 选项

2016-03-10 21:04 393 查看

目录

操作环境

导读

调用方式

布局文件设置

源码分析

实例

操作环境

操作系统: win7-64bit 旗舰版

android 版本: android-23

模拟器:海马玩模拟器 0.9.0 Beta( android 4.2.2 )

导读

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

调用方式

AbsListView.java:

public int getTranscriptMode()   // 用于查询当前的 transcript 模式


void setTranscriptMode(int mode)   // 用于设置 transcript 模式


AbsListView.TRANSCRIPT_MODE_DISABLED    // 禁用
AbsListView.TRANSCRIPT_MODE_NORMAL   // 正常状态
AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL   // 总是滚动到最新一条


布局文件设置

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


源码分析

获取当前模式:

/**
* Returns the current transcript mode.
*
* @return {@link #TRANSCRIPT_MODE_DISABLED}, {@link #TRANSCRIPT_MODE_NORMAL} or
*         {@link #TRANSCRIPT_MODE_ALWAYS_SCROLL}
*/
public int getTranscriptMode() {
return mTranscriptMode;
}


设置模式:

/**
* 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;
}


根据 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();
}
... 省略 ...
}


@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;
}
}


实例

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>


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);
}
});
}


效果图:

disable 状态:



normal 状态:



always 状态:

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