【android】ListView 的 stackFromBottom 选项

## 目录 ##

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

操作环境

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

导读

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

调用方法

ListView.java

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

布局文件设置

    <ListView android:id="@+id/lv_test"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        <!-- 以下只能选择一项 -->
        android:stackFromBottom="true"
        android:stackFromBottom="false"
        >
    </ListView>

源码分析

分析内容主要为: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();
        }
    }
  • adapter 对应的数据集内容有更改的时候会检测 mStackFromBottom 的值,并设置对应的 mLayout 状态
@Override
protected void handleDataChanged() {
    ... 省略 ...
    mLayoutMode = mStackFromBottom ? LAYOUT_FORCE_BOTTOM : LAYOUT_FORCE_TOP;
    ... 省略 ...
}
  • 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;
    ... 省略 ...
}
  • 下面就看个从上到下显示的吧:
/**
     * 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);
    }
    /**
     * 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;
    }

实例

  • 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>
  • 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);
            }
        });
    }
  • 效果图:
    这里写图片描述
发布了15 篇原创文章 · 获赞 3 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览