- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有一个按月和年(2010 年 6 月、2010 年 7 月等)分隔的事件列表。我启用了快速滚动,因为列表真的很长。我还实现了 SectionIndexer,以便人们在快速向下滚动事件列表时可以看到他们当前正在查看的月份和年份。
我对实现没有任何问题,只是信息的显示方式。使用 SectionIndexer 快速滚动似乎只能支持带有单个字母的标签。如果列表按字母顺序排列,那将是完美的,但我希望它显示更多文本。
如果您查看下面的屏幕截图,您会发现我遇到的问题。
(来源:matto1990.com)
我想知道的是:是否可以更改屏幕中央的文本显示方式。我可以以某种方式更改它以使其看起来正确(背景覆盖所有文本)。
提前致谢。如果您需要任何说明或代码,请询问。
最佳答案
编辑: 提供此解决方案的完整示例代码 here .
我遇到了同样的问题 - 我需要在覆盖矩形中显示全文,而不仅仅是单个字符。我设法使用以下代码作为示例来解决它:http://code.google.com/p/apps-for-android/source/browse/trunk/RingsExtended/src/com/example/android/rings_extended/FastScrollView.java
作者说这是从联系人应用程序复制的,它显然使用了自己的实现,而不是仅仅在 ListView
上设置 fastScrollEnabled="true"
。我对其进行了一些修改,以便您可以自定义覆盖矩形宽度、覆盖矩形高度、覆盖文本大小和滚动拇指宽度。
作为记录,最终结果如下所示:http://nolanwlawson.files.wordpress.com/2011/03/pokedroid_1.png
您需要做的就是将这些值添加到您的 res/values/attrs.xml:
<declare-styleable name="CustomFastScrollView">
<attr name="overlayWidth" format="dimension"/>
<attr name="overlayHeight" format="dimension"/>
<attr name="overlayTextSize" format="dimension"/>
<attr name="overlayScrollThumbWidth" format="dimension"/>
</declare-styleable>
然后使用这个 CustomFastScrollView 而不是链接中的那个:
public class CustomFastScrollView extends FrameLayout
implements OnScrollListener, OnHierarchyChangeListener {
private Drawable mCurrentThumb;
private Drawable mOverlayDrawable;
private int mThumbH;
private int mThumbW;
private int mThumbY;
private RectF mOverlayPos;
// custom values I defined
private int mOverlayWidth;
private int mOverlayHeight;
private float mOverlayTextSize;
private int mOverlayScrollThumbWidth;
private boolean mDragging;
private ListView mList;
private boolean mScrollCompleted;
private boolean mThumbVisible;
private int mVisibleItem;
private Paint mPaint;
private int mListOffset;
private Object [] mSections;
private String mSectionText;
private boolean mDrawOverlay;
private ScrollFade mScrollFade;
private Handler mHandler = new Handler();
private BaseAdapter mListAdapter;
private boolean mChangedBounds;
public static interface SectionIndexer {
Object[] getSections();
int getPositionForSection(int section);
int getSectionForPosition(int position);
}
public CustomFastScrollView(Context context) {
super(context);
init(context, null);
}
public CustomFastScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomFastScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void useThumbDrawable(Drawable drawable) {
mCurrentThumb = drawable;
mThumbW = mOverlayScrollThumbWidth;//mCurrentThumb.getIntrinsicWidth();
mThumbH = mCurrentThumb.getIntrinsicHeight();
mChangedBounds = true;
}
private void init(Context context, AttributeSet attrs) {
// set all attributes from xml
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.CustomFastScrollView);
mOverlayHeight = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayHeight, 0);
mOverlayWidth = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayWidth, 0);
mOverlayTextSize = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayTextSize, 0);
mOverlayScrollThumbWidth = typedArray.getDimensionPixelSize(
R.styleable.CustomFastScrollView_overlayScrollThumbWidth, 0);
}
// Get both the scrollbar states drawables
final Resources res = context.getResources();
Drawable thumbDrawable = res.getDrawable(R.drawable.scrollbar_handle_accelerated_anim2);
useThumbDrawable(thumbDrawable);
mOverlayDrawable = res.getDrawable(android.R.drawable.alert_dark_frame);
mScrollCompleted = true;
setWillNotDraw(false);
// Need to know when the ListView is added
setOnHierarchyChangeListener(this);
mOverlayPos = new RectF();
mScrollFade = new ScrollFade();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(mOverlayTextSize);
mPaint.setColor(0xFFFFFFFF);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
private void removeThumb() {
mThumbVisible = false;
// Draw one last time to remove thumb
invalidate();
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (!mThumbVisible) {
// No need to draw the rest
return;
}
final int y = mThumbY;
final int viewWidth = getWidth();
final CustomFastScrollView.ScrollFade scrollFade = mScrollFade;
int alpha = -1;
if (scrollFade.mStarted) {
alpha = scrollFade.getAlpha();
if (alpha < ScrollFade.ALPHA_MAX / 2) {
mCurrentThumb.setAlpha(alpha * 2);
}
int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
mCurrentThumb.setBounds(left, 0, viewWidth, mThumbH);
mChangedBounds = true;
}
canvas.translate(0, y);
mCurrentThumb.draw(canvas);
canvas.translate(0, -y);
// If user is dragging the scroll bar, draw the alphabet overlay
if (mDragging && mDrawOverlay) {
mOverlayDrawable.draw(canvas);
final Paint paint = mPaint;
float descent = paint.descent();
final RectF rectF = mOverlayPos;
canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2,
(int) (rectF.bottom + rectF.top) / 2 + descent, paint);
} else if (alpha == 0) {
scrollFade.mStarted = false;
removeThumb();
} else {
invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mCurrentThumb != null) {
mCurrentThumb.setBounds(w - mThumbW, 0, w, mThumbH);
}
final RectF pos = mOverlayPos;
pos.left = (w - mOverlayWidth) / 2;
pos.right = pos.left + mOverlayWidth;
pos.top = h / 10; // 10% from top
pos.bottom = pos.top + mOverlayHeight;
mOverlayDrawable.setBounds((int) pos.left, (int) pos.top,
(int) pos.right, (int) pos.bottom);
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
if (totalItemCount - visibleItemCount > 0 && !mDragging) {
mThumbY = ((getHeight() - mThumbH) * firstVisibleItem) / (totalItemCount - visibleItemCount);
if (mChangedBounds) {
final int viewWidth = getWidth();
mCurrentThumb.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
mChangedBounds = false;
}
}
mScrollCompleted = true;
if (firstVisibleItem == mVisibleItem) {
return;
}
mVisibleItem = firstVisibleItem;
if (!mThumbVisible || mScrollFade.mStarted) {
mThumbVisible = true;
mCurrentThumb.setAlpha(ScrollFade.ALPHA_MAX);
}
mHandler.removeCallbacks(mScrollFade);
mScrollFade.mStarted = false;
if (!mDragging) {
mHandler.postDelayed(mScrollFade, 1500);
}
}
private void getSections() {
Adapter adapter = mList.getAdapter();
if (adapter instanceof HeaderViewListAdapter) {
mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount();
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
if (adapter instanceof SectionIndexer) {
mListAdapter = (BaseAdapter) adapter;
mSections = ((SectionIndexer) mListAdapter).getSections();
}
}
public void onChildViewAdded(View parent, View child) {
if (child instanceof ListView) {
mList = (ListView)child;
mList.setOnScrollListener(this);
getSections();
}
}
public void onChildViewRemoved(View parent, View child) {
if (child == mList) {
mList = null;
mListAdapter = null;
mSections = null;
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mThumbVisible && ev.getAction() == MotionEvent.ACTION_DOWN) {
if (ev.getX() > getWidth() - mThumbW && ev.getY() >= mThumbY &&
ev.getY() <= mThumbY + mThumbH) {
mDragging = true;
return true;
}
}
return false;
}
private void scrollTo(float position) {
int count = mList.getCount();
mScrollCompleted = false;
final Object[] sections = mSections;
int sectionIndex;
if (sections != null && sections.length > 1) {
final int nSections = sections.length;
int section = (int) (position * nSections);
if (section >= nSections) {
section = nSections - 1;
}
sectionIndex = section;
final SectionIndexer baseAdapter = (SectionIndexer) mListAdapter;
int index = baseAdapter.getPositionForSection(section);
// Given the expected section and index, the following code will
// try to account for missing sections (no names starting with..)
// It will compute the scroll space of surrounding empty sections
// and interpolate the currently visible letter's range across the
// available space, so that there is always some list movement while
// the user moves the thumb.
int nextIndex = count;
int prevIndex = index;
int prevSection = section;
int nextSection = section + 1;
// Assume the next section is unique
if (section < nSections - 1) {
nextIndex = baseAdapter.getPositionForSection(section + 1);
}
// Find the previous index if we're slicing the previous section
if (nextIndex == index) {
// Non-existent letter
while (section > 0) {
section--;
prevIndex = baseAdapter.getPositionForSection(section);
if (prevIndex != index) {
prevSection = section;
sectionIndex = section;
break;
}
}
}
// Find the next index, in case the assumed next index is not
// unique. For instance, if there is no P, then request for P's
// position actually returns Q's. So we need to look ahead to make
// sure that there is really a Q at Q's position. If not, move
// further down...
int nextNextSection = nextSection + 1;
while (nextNextSection < nSections &&
baseAdapter.getPositionForSection(nextNextSection) == nextIndex) {
nextNextSection++;
nextSection++;
}
// Compute the beginning and ending scroll range percentage of the
// currently visible letter. This could be equal to or greater than
// (1 / nSections).
float fPrev = (float) prevSection / nSections;
float fNext = (float) nextSection / nSections;
index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev)
/ (fNext - fPrev));
// Don't overflow
if (index > count - 1) index = count - 1;
mList.setSelectionFromTop(index + mListOffset, 0);
} else {
int index = (int) (position * count);
mList.setSelectionFromTop(index + mListOffset, 0);
sectionIndex = -1;
}
if (sectionIndex >= 0) {
String text = mSectionText = sections[sectionIndex].toString();
mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') &&
sectionIndex < sections.length;
} else {
mDrawOverlay = false;
}
}
private void cancelFling() {
// Cancel the list fling
MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
mList.onTouchEvent(cancelFling);
cancelFling.recycle();
}
@Override
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
if (me.getX() > getWidth() - mThumbW
&& me.getY() >= mThumbY
&& me.getY() <= mThumbY + mThumbH) {
mDragging = true;
if (mListAdapter == null && mList != null) {
getSections();
}
cancelFling();
return true;
}
} else if (me.getAction() == MotionEvent.ACTION_UP) {
if (mDragging) {
mDragging = false;
final Handler handler = mHandler;
handler.removeCallbacks(mScrollFade);
handler.postDelayed(mScrollFade, 1000);
return true;
}
} else if (me.getAction() == MotionEvent.ACTION_MOVE) {
if (mDragging) {
final int viewHeight = getHeight();
mThumbY = (int) me.getY() - mThumbH + 10;
if (mThumbY < 0) {
mThumbY = 0;
} else if (mThumbY + mThumbH > viewHeight) {
mThumbY = viewHeight - mThumbH;
}
// If the previous scrollTo is still pending
if (mScrollCompleted) {
scrollTo((float) mThumbY / (viewHeight - mThumbH));
}
return true;
}
}
return super.onTouchEvent(me);
}
public class ScrollFade implements Runnable {
long mStartTime;
long mFadeDuration;
boolean mStarted;
static final int ALPHA_MAX = 200;
static final long FADE_DURATION = 200;
void startFade() {
mFadeDuration = FADE_DURATION;
mStartTime = SystemClock.uptimeMillis();
mStarted = true;
}
int getAlpha() {
if (!mStarted) {
return ALPHA_MAX;
}
int alpha;
long now = SystemClock.uptimeMillis();
if (now > mStartTime + mFadeDuration) {
alpha = 0;
} else {
alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration);
}
return alpha;
}
public void run() {
if (!mStarted) {
startFade();
invalidate();
}
if (getAlpha() > 0) {
final int y = mThumbY;
final int viewWidth = getWidth();
invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
} else {
mStarted = false;
removeThumb();
}
}
}
}
您还可以使用 ALPHA_MAX 调整滚动拇指的半透明度。
然后在你的布局 xml 文件中添加这样的内容:
<com.myapp.CustomFastScrollView android:layout_width="wrap_content"
android:layout_height="fill_parent"
myapp:overlayWidth="175dp" myapp:overlayHeight="110dp" myapp:overlayTextSize="36dp"
myapp:overlayScrollThumbWidth="60dp" android:id="@+id/fast_scroll_view">
<ListView android:id="@android:id/list" android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView android:id="@android:id/empty"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="" />
</com.myapp.CustomFastScrollView>
不要忘记在该布局 xml 文件中声明您的属性:
... xmlns:myapp= "http://schemas.android.com/apk/res/com.myapp" ...
您还需要从该 Android 源代码中获取 R.drawable.scrollbar_handle_accelerated_anim2
可绘制对象。上面的链接只包含 mdpi 之一。
关于android - ListAdapter 和 SectionIndexer 的快速滚动显示问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3225092/
是否可以使用自定义 View 作为部分索引器? IE。使它更透明并使用图像而不是字符? 是否可以在不禁用 FastScroll 功能的情况下按需启用/禁用 SectionIndexer 弹出窗口? 最
有没有人找到一种方法来设置使用 SectionIndexer 时出现的小部件的样式?样式更改,例如更改文本颜色或背景颜色。 最佳答案 找到答案 here 您必须创建一个主题并将其应用于 Activit
我正在尝试找到一种方法来使用 SectionIndexer,而不是 AlphabetIndexer。我感兴趣的是在节标题而不是字母表中包含字符串数组的元素。我无法使用节索引器找到任何示例代码。 这是
我有一个包含事件的自定义 ListView。 Adapters SectionIndexer 在快速滚动(例如,星期一 10:00)时索引星期几和事件的时间,但是使用快速滚动文本的默认样式,文本太大并
我一直在寻找在我的 listView 中对日期使用 SectionIndexer 的方法。我想在快速滚动列表时显示“短日期”。我看到几年前的一篇帖子,其中一个人说他已经成功了,但他遇到了不同的问题,但
下面是我的适配器的代码,它允许创建一个弹出窗口,其中包含我的 ListView 中每个项目的首字母,并提供类似于联系人应用程序的内容。 不幸的是,颜色不正确,文本是灰色背景上的黑色。 我的问题是: 我
我创建了一个 UITableView,它使用屏幕顶部的标题 View 和顶部的字母 sectionIndex 栏。我的 sectionIndex 栏是透明的,但它似乎延伸了我的 tableView 的
在将新项目添加到 ListView 后,有什么方法可以重新索引 SectionIndexer 吗? 我找到了这个 solution , 但刷新SectionIndexer后叠加层位于左上角。 有人有什
在实现 SectionIndexer 的 ArrayAdapter 中,有代码检查以相同首字母开头的列表项——因此可以合并。 像这样: alphaIndexer = new HashMap()
我已经使用 SectionIndexer 实现了一个 ListView。它在 99% 的时间里都能正常工作,但我发现有一种情况会出错。 错误是: java.lang.ArrayIndexOutOfBo
我实现了一个 ListView ,它实现了 SectionIndexer ...到目前为止一切都很好。 通常项目按名称排序,但我也提供以不同方式排序列表的选项 - 按距离(从用户到对象)。 因此,当列
有人知道如何使用 SectionIndexer 或 RecyclerView 的替代品吗? SectionIndexer 允许 ListView 在快速滚动时弹出部分。 最佳答案 问题在于 Recyc
我有一个按月和年(2010 年 6 月、2010 年 7 月等)分隔的事件列表。我启用了快速滚动,因为列表真的很长。我还实现了 SectionIndexer,以便人们在快速向下滚动事件列表时可以看到他
我写了一个实现 SectionIndexer 接口(interface)的 BaseAdapter 并且一切正常,我可以使用我的 ListView 的 setFastScrollingEnabled(
我正在从 PHChange 实例修改我的 UITableView 的数据源,这工作正常。我不明白的是,我无法更新 UITableView 右侧的 sectionIndex,除非您使用以下方法重新加载整
我使用实现了 SectionIndexer 的自定义适配器来创建 ListView。当我在 list 文件中仅键入 minSdkVersion = 8 时,一切正常。但是,如果我将 targetSdk
如何设置 UITableView 右侧 sectionIndex 的字体大小? 最佳答案 Try this solution, this will definitely help you -> Ste
我创建了一个使用 FastScroll 的 ListView。 (见图片)当用户单击以下任何按钮(即所有轨道、艺术家、专辑)时,每次调用以下自定义 ArrayAdater ArrayAdapter a
I created 3 headerViews and added check box, when select section0 check box i want to expand cells i
有没有办法以编程方式禁用/启用分段? 所以我可以在普通的 fastScroll 和 Indexes 之间进行选择,而无需制作两个适配器? 最佳答案 我终于自己找到了它。您只需将带有字母的数组设为空,瞧
我是一名优秀的程序员,十分优秀!