滚动前:
滚动期间
我在滚动期间的期望:
我的HorizontalScrollView有问题。当我从这个视图中选择一个元素时,我通过调用:
将焦点设置为该元素else if (v.getParent() == candidatesScrollView.getChildAt(0))
{
Button candidateButton = (Button) v;
v.requestFocusFromTouch();
v.setSelected(true);
(...)
}
之后,当我滚动列表而不选择其他元素时,我将失去先前所选元素的焦点。我对这个主题做了一些研究,但没有解决方案可以对我有用......如何在不丢失选定元素焦点的情况下滚动我的HorizontalScrollList?任何帮助都会得到赞赏。自从我提出这个问题以来,已经过了大约14天,但仍未找到解决方案。请帮忙。
以下是我的XML的一部分:
<HorizontalScrollView
android:id="@+id/CandidatesHorizontalScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/linearLayout2"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:visibility="gone" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:orientation="horizontal" >
<Button
android:id="@+id/horizontalscrollview1_button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:textSize="25sp" />
(...)
// 11 more buttons
</LinearLayout>
</HorizontalScrollView>
更新
我当前的解决方案#1(工作不正常): 滚动后,再滚动(例如向后滚动),滚动从所选元素开始。
我创建了自定义HorizontalScrollView类,在其中我重写了onTouchEvent()方法。我认为这不是最佳方式,因为在这种情况下,每次移动一个像素时我都要进行计算。例如,如果我将toast.show()添加到下面的方法中,它将尝试显示尽可能多的我移动像素的吐司(如果我移动10个像素,它将尝试显示10个Toast)。无论如何,它对我有用,并且保留了选择和关注。
请帮我修改此代码,以便最终解决该已知问题:
@Override
public boolean onTouchEvent(MotionEvent ev)
{
int i = 0;
Button button = null;
for (; i < 11; i++)
{
button = (Button)((LinearLayout)getChildAt(0)).getChildAt(i);
if(button.isSelected())
break;
}
super.onTouchEvent(ev);
button.setSelected(true);
button.requestFocusFromTouch();
return true;
}
为了确保上面的代码能够正常工作,你需要在HorizontalScrollView中一次只有一个选中的项目,即当你按不同的按钮时,你需要使前一个代码设置为setSelected(false)
MY CURRENT SOLUTION#2(无法正常工作):
我试图实现的解决方案#2,认为第一个不够优雅,涉及使用手势检测器。在我的自定义HorizontalListView类中,我添加了以下代码:
构造
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
gestureDetector = new GestureDetector(context, new MyHorizontalScrollViewGestureDetector());
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return true;
}
});
// TODO Auto-generated constructor stub
}
MyHorizontalScrollViewGestureDetector内部类:
public class MyHorizontalScrollViewGestureDetector extends SimpleOnGestureListener
{
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
//Here code similar like that one in solution #1
//But the View is not scrolling, even without that code
super.onScroll(e1, e2, distanceX, distanceY);
return true;
}
}
但是,该列表不会滚动该解决方案。我可以添加onScroll方法:
ScrollBy((int)positionX, (int)positionY);
这会使列表滚动,但不是很好,广告有时会冻结。 我想知道为什么滚动不被超级调用。方法
我当前的解决方案#3(正常工作,但它是随处走动):
因为解决方案1和解决方案2都不起作用,所以我决定不再使用焦点了。 我现在所做的是,每当我点击它时每次更改Button Button时都会更改Button Drawable。我使用与用于聚焦按钮(Holo)相同的Drawable。在这种情况下,我不必担心在HorizontalScrollView中滚动。这个解决方案是一种循环,所以我期待任何评论,建议和编辑。
答案 0 :(得分:1)
以下解决方案是否适用(我从here获取了想法):
您可能想尝试创建自己的自定义类,扩展HorizontalScrollView
并覆盖onScrollChanged()
函数:
public class TestHorizontalScrollView extends HorizontalScrollView {
public TestHorizontalScrollView(Context context) {
super(context);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
// TODO Auto-generated method stub
Log.i("Scrolling", "X from ["+oldl+"] to ["+l+"]");
Button button = null;
for (; i < 11; i++)
{
button = (Button)((LinearLayout)getChildAt(0)).getChildAt(i);
if(button.isSelected())
break;
}
button.setSelected(true);
button.requestFocusFromTouch();
super.onScrollChanged(l, t, oldl, oldt);
}
}
现在您已检测到滚动(我们正在谈论其中一个HorizontalScrollView
)您可以再次设置相应按钮的选定状态。你可以试试这个解决方案,看看它是否有效。我对解决这个问题很感兴趣,因为这个问题也非常有趣。
无论如何,我设法找到了following article。他们在那里说:
想象一下一个简单的应用程序,例如ApiDemos,它显示了一个列表 文本项目。用户可以使用自由地浏览列表 轨迹球,他们也可以使用他们的滚动和推送列表 手指。此方案中的问题是选择。如果我选择一个 列表顶部的项目,然后将列表推向 底部,选择会发生什么?它应该保留在 项目并滚动屏幕?在这种情况下,如果我会发生什么 然后决定用轨迹球移动选择?或者更糟,如果我 按下轨迹球以对当前所选项目进行操作,即 屏幕上没有显示。仔细考虑后,我们决定了 完全删除选择。
在触控模式下,没有焦点也没有选择。任何选定的项目 一旦用户输入,就在网格列表中取消选择 触摸模式。同样,任何有焦点的小部件都会变得没有焦点 用户进入触摸模式。下图说明了什么时候会发生什么 用轨迹球选择项目后,用户触摸列表。
无论如何,那里的陈述并没有让我高兴,我进一步发现了这个:
android:focusable="true"
android:focusableInTouchMode="true"
同时设置android:clickable="true"
(您也可以设置android:focusable="true"
的{{1}}。
尝试将这些添加到按钮和包含它们的布局中。 尝试一切。
我会尽可能地支持你。
干杯
答案 1 :(得分:0)
我记得滚动视图存在问题,我认为这与您遇到的问题类似。
我提出的解决方案是覆盖onRequestFocusInDescendants
类中的HorizontalScrollView
方法。这需要您创建自己的HorizontalScrollView
扩展类,如果您还没有这样做。
就我而言,我总是从方法中返回true。这告诉来电者您已经处理了焦点变化,所以它不应该尝试进一步做任何事情。
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
根据您的要求,您可能会发现仅在某些条件下(例如滚动正在进行时)才返回true,否则将调用转发给超类。
答案 2 :(得分:0)
除了自定义方式之外,这个问题没有答案,因为你可能已经做过像改变drawable一样。原因是当你滑动时,焦点转到HorizontalScroll,你只能专注于一个项目,聚焦多个视图是没有意义的。因此要么实现一个drawable(你似乎已经完成了),要么扩展一个复选框并覆盖它的功能,所以当它被聚焦时,它会被检查并改变外观。
答案 3 :(得分:0)
我找到了解决问题的方法。您可以查看更新的问题以获取详细信息。基本上,我决定使用Drawable选择器而不是使用焦点,这更容易。