ListView 的 stackFromBottom 选项

http://blog.csdn.net/natloc/article/details/50849700

http://blog.csdn.net/natloc/article/details/50849700

http://blog.csdn.net/natloc/article/details/50849700




【android】ListView 的 stackFromBottom 选项

标签: androidstackBottomFORCE-TOPlistview
  863人阅读  评论(0)  收藏  举报
  分类:

目录(?)[+]

## 目录 ##

  • 操作系统
  • 导读
  • 调用方法
  • 布局文件设置
  • 源码分析
  • 实例

操作环境

  • 操作系统: win7-64bit 旗舰版
  • android 版本: android-23
  • 模拟器:海马玩模拟器 0.9.0 Beta( android 4.2.2 )

导读

默认情况下,ListView 是从上到下逐条显示 item 的;但我们可以根据实际需要,让其按照从下到上的方式显示。

调用方法

ListView.Java

  • 用于检测当前的状态是否为 从下到上 的方式
public boolean isStackFromBottom()
   
   
  • 1
  • 1
  • 用于设置 ListView 中 item 顺序的显示方式( 设置后会立刻刷新 ListView 的显示 )
public void setStackFromBottom(boolean stackFromBottom)
   
   
  • 1
  • 1

布局文件设置

    <ListView android:id="@+id/lv_test"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        <!-- 以下只能选择一项 -->
        android:stackFromBottom="true"
        android:stackFromBottom="false"
        >
    </ListView>
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

源码分析

分析内容主要为:boolean 值对于 Item 布局顺序的影响

  • 设置状态:其中修改了 mStackFromBottom 的值;
/**
     * When stack from bottom is set to true, the list fills its content starting from
     * the bottom of the view.
     *
     * @param stackFromBottom true to pin the view's content to the bottom edge,
     *        false to pin the view's content to the top edge
     */
    public void setStackFromBottom(boolean stackFromBottom) {
        if (mStackFromBottom != stackFromBottom) {
            mStackFromBottom = stackFromBottom;
            requestLayoutIfNecessary();
        }
    }
   
   
  • 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
  • adapter 对应的数据集内容有更改的时候会检测 mStackFromBottom 的值,并设置对应的 mLayout 状态
@Override
protected void handleDataChanged() {
    ... 省略 ...
    mLayoutMode = mStackFromBottom ? LAYOUT_FORCE_BOTTOM : LAYOUT_FORCE_TOP;
    ... 省略 ...
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • ListView 在刷新布局时会根据 mLayoutMode 状态来实现具体的 Item 显示顺序
@Override
protected void layoutChildren() {
    ... 省略 ...
            case LAYOUT_FORCE_BOTTOM:
                sel = fillUp(mItemCount - 1, childrenBottom);
                adjustViewsUpOrDown();
                break;
            case LAYOUT_FORCE_TOP:
                mFirstPosition = 0;
                sel = fillFromTop(childrenTop);
                adjustViewsUpOrDown();
                break;
    ... 省略 ...
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 下面就看个从上到下显示的吧:
/**
     * Fills the list from top to bottom, starting with mFirstPosition
     *
     * @param nextTop The location where the top of the first item should be
     *        drawn
     *
     * @return The view that is currently selected
     */
    private View fillFromTop(int nextTop) {
        mFirstPosition = Math.min(mFirstPosition, mSelectedPosition);
        mFirstPosition = Math.min(mFirstPosition, mItemCount - 1);
        if (mFirstPosition < 0) {
            mFirstPosition = 0;
        }
        return fillDown(mFirstPosition, nextTop);
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
    /**
     * Fills the list from pos down to the end of the list view.
     *
     * @param pos The first position to put in the list
     *
     * @param nextTop The location where the top of the item associated with pos
     *        should be drawn
     *
     * @return The view that is currently selected, if it happens to be in the
     *         range that we draw.
     */
    private View fillDown(int pos, int nextTop) {
        View selectedView = null;

        int end = (mBottom - mTop);
        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
            end -= mListPadding.bottom;
        }

        while (nextTop < end && pos < mItemCount) {
            // is this the selected item?
            boolean selected = pos == mSelectedPosition;
            View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected);

            nextTop = child.getBottom() + mDividerHeight;
            if (selected) {
                selectedView = child;
            }
            pos++;
        }

        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
        return selectedView;
    }
   
   
  • 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
  • 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

实例

  • 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_true"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="设置为 true"
        />
    <Button android:id="@+id/btn_set_false"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="设置为 false"
        />

</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
  • 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
  • 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.testListViewStackFromBottom();
    }

    void testListViewStackFromBottom(){
        Button btnAddItem = (Button) this.findViewById(R.id.btn_add_item);
        Button btnSetTrue = (Button) this.findViewById(R.id.btn_set_true);
        Button btnSetFalse = (Button) this.findViewById(R.id.btn_set_false);

        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();
            }
        });
        // 设置监听
        btnSetTrue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ListView lv = (ListView)MainActivity.this.findViewById(R.id.lv_test);
                lv.setStackFromBottom(true);
            }
        });
        btnSetFalse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ListView lv = (ListView)MainActivity.this.findViewById(R.id.lv_test);
                lv.setStackFromBottom(false);
            }
        });
    }
   
   
  • 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
  • 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
  • 效果图: 
    这里写图片描述
0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值