我想要获取ListView滚动的精确像素位置。
不,我并不是指第一个可见的位置。
有没有办法实现这个功能呢?
我想要获取ListView滚动的精确像素位置。
不,我并不是指第一个可见的位置。
有没有办法实现这个功能呢?
好的,我找到了一个解决方法,使用以下代码:
View c = listview.getChildAt(0);
int scrolly = -c.getTop() + listview.getFirstVisiblePosition() * c.getHeight();
它的工作原理是它获取第一个可见列表项的实际偏移量,并计算其距视图顶部的距离,以确定我们滚动了多少进入视图,现在我们知道了这一点,就可以使用常规的getFirstVisiblePosition方法来计算剩余部分。Math.max
,代码如下:View firstView = view.getChildAt(0); maxHeight = Math.max(maxHeight, firstView.getHeight()); int y = -firstView.getTop() + view.getFirstVisiblePosition() * maxHeight;
- ViliusKSaarraz1的回答只适用于ListView中所有行的高度相同且没有标题(或标题与行高度相同)的情况。
请注意,一旦行在屏幕顶部消失,你将无法访问它们,也就是说,你将无法追踪它们的高度。这就是为什么需要保存这些高度(或者所有高度的累积值)。我的解决方案需要保持一个按索引分组的高度字典(假定在第一次显示列表时滚动到顶部)。
private Dictionary<Integer, Integer> listViewItemHeights = new Hashtable<Integer, Integer>();
private int getScroll() {
View c = listView.getChildAt(0); //this is the first visible row
int scrollY = -c.getTop();
listViewItemHeights.put(listView.getFirstVisiblePosition(), c.getHeight());
for (int i = 0; i < listView.getFirstVisiblePosition(); ++i) {
if (listViewItemHeights.get(i) != null) // (this is a sanity check)
scrollY += listViewItemHeights.get(i); //add all heights of the views that are gone
}
return scrollY;
}
我能想到最简单的想法是扩展ListView并公开默认情况下受保护的“computeVerticalScrollOffset”,然后在你的xml布局中使用“com.your.package.CustomListView”。
public class CustomListView extends ListView {
public CustomListView(Context context) {
super(context);
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public int computeVerticalScrollOffset() {
return super.computeVerticalScrollOffset();
}
}
computeVerticalScrollOffset()
报告此标题视图展开的百分比。当我滚动更多时,结果单调增长,但我不确定如何从(虚拟)第一个标题的顶部将其转换为像素。 - Alex Cohny=super.computeVerticalScrollOffset();
if(listView.getFirstVisiblePosition() > 0){
y += (listView.getFirstVisiblePosition()-1)*listItemHeight+headerHeight;
}
- El'首先声明一个整型变量来保存位置。
int position = 0;
然后将 scrollListener 添加到您的 ListView 中,
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
position = firstVisibleItem;
}
});
然后,当您获得新数据或数据发生任何更改时,您需要设置ListView的当前位置。
listView.setSelection(position);
我已经使用了适配器进行设置,对我来说运行良好。
我知道我有点晚了,但我想分享一下我解决这个问题的方法。我有一个ListView,我试图找出我已经滚动了多少,以便相对于它滚动其他内容并引起视差效果。以下是我的解决方案:
public abstract class OnScrollPositionChangedListener implements AbsListView.OnScrollListener {
int pos;
int prevIndex;
int prevViewPos;
int prevViewHeight;
@Override
public void onScroll(AbsListView v, int i, int vi, int n) {
try {
View currView = v.getChildAt(0);
int currViewPos = Math.round(currView.getTop());
int diffViewPos = prevViewPos - currViewPos;
int currViewHeight = currView.getHeight();
pos += diffViewPos;
if (i > prevIndex) {
pos += prevViewHeight;
} else if (i < prevIndex) {
pos -= currViewHeight;
}
prevIndex = i;
prevViewPos = currViewPos;
prevViewHeight = currViewHeight;
} catch (Exception e) {
e.printStackTrace();
} finally {
onScrollPositionChanged(pos);
}
}
@Override public void onScrollStateChanged(AbsListView absListView, int i) {}
public abstract void onScrollPositionChanged(int scrollYPosition);
}
myListView.setOnScrollListener(
new OnScrollPositionChangedListener() {
@Override
public void onScroll(AbsListView v, int i, int vi, int n) {
super.onScroll(v, i, vi, n);
//Do your onScroll stuff
}
@Override
public void onScrollPositionChanged(int scrollYPosition) {
//Enjoy having access to the amount the ListView has scrolled
}
}
);
absoluteY += pos*listItemHeight;
public class CustomListView extends ListView {
private int listItemHeight = 140;
private int headerHeight = 200;
public CustomListView(Context context) {
super(context);
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public int computeVerticalScrollOffset() {
final int y = super.computeVerticalScrollOffset();
int absoluteY = y;
int pos = getFirstVisiblePosition();
if(pos > 0){
absoluteY += (pos-1)*listItemHeight+headerHeight;
}
//use absoluteY
return y;
}
public abstract class OnScrollPositionChangedListener implements AbsListView.OnScrollListener {
int pos;
public int viewHeight = 0;
public int listHeight = 0;
@Override
public void onScroll(AbsListView v, int i, int vi, int n) {
try {
if(viewHeight==0) {
viewHeight = v.getChildAt(0).getHeight();
listHeight = v.getHeight();
}
pos = viewHeight * i;
} catch (Exception e) {
e.printStackTrace();
} finally {
onScrollPositionChanged(pos);
}
}
@Override public void onScrollStateChanged(AbsListView absListView, int i) {}
public abstract void onScrollPositionChanged(int scrollYPosition);
}
public class MainActivity extends AppCompatActivity {
SeekBar seekBar;
ListView listView;
OnScrollPositionChangedListener onScrollPositionChangedListener = new OnScrollPositionChangedListener() {
@Override
public void onScroll(AbsListView v, int i, int vi, int n) {
super.onScroll(v, i, vi, n);
//Do your onScroll stuff
}
@Override
public void onScrollPositionChanged(int scrollYPosition) {
//Enjoy having access to the amount the ListView has scrolled
seekBar.setProgress(scrollYPosition);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar = (SeekBar) findViewById(R.id.mySeekBar);
listView = (ListView) findViewById(R.id.listView);
final String[] values = new String[]{"Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView.setAdapter(adapter);
listView.setOnScrollListener(onScrollPositionChangedListener);
seekBar.postDelayed(new Runnable() {
@Override
public void run() {
seekBar.setMax((onScrollPositionChangedListener.viewHeight * values.length) - onScrollPositionChangedListener.listHeight);
}
}, 1000);
seekBar.setEnabled(false);
}
}
compile 'com.h6ah4i.android.widget.verticalseekbar:verticalseekbar:0.7.0'
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.centsol.charexamples.MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadeScrollbars="false"
android:scrollbars="none"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
</ListView>
<!-- This library requires pair of the VerticalSeekBar and VerticalSeekBarWrapper classes -->
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_height="match_parent">
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar
android:id="@+id/mySeekBar"
android:layout_width="0dp"
android:progressDrawable="@drawable/progress"
android:thumb="@drawable/thumb"
android:layout_height="0dp"
android:splitTrack="false"
app:seekBarRotation="CW90" /> <!-- Rotation: CW90 or CW270 -->
</com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper>
<View
android:layout_width="1dp"
android:visibility="visible"
android:layout_alignParentRight="true"
android:layout_marginTop="16dp"
android:layout_marginRight="2.5dp"
android:layout_marginBottom="16dp"
android:background="@android:color/black"
android:layout_height="match_parent" />
</RelativeLayout>
背景 XML
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@android:color/transparent"/>
</shape>
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@android:color/transparent" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@android:id/background"
android:drawable="@drawable/background"/>
<item android:id="@android:id/progress">
<clip android:drawable="@drawable/fill" />
</item>
</layer-list>
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="@android:color/holo_red_dark" />
<size
android:height="5dp"
android:width="5dp" />
</shape>