ViewPager里面的ListView行prevents onItemClick被解雇 [英] ViewPager inside ListView row prevents onItemClick to be fired
问题描述
我有一个ListView的每一行内的ViewPager。它工作正常,它改变了看法里面,当用户使用滑动手势,但它prevents被称为ListView的onItemClick方法。我知道ViewPager是因为当我隐藏它,在onItemClick称为罪魁祸首,所以这是我想:
我创建了一个ViewGroup中要行(RowView)。这ViewGroup中有 onInterceptTouchEvent
重写,以避免ViewPager处理进一步触摸事件时,我发现一个点击。但onItemClick回调仍然没有被调用。而列表选择不上点击或者显示。我想这两个特点的工作。
这是如何从RowView的onInterceptTouchEvent如下:
@覆盖
公共布尔onInterceptTouchEvent(MotionEvent EV){
INT actionMasked = ev.getActionMasked();
开关(actionMasked){
案例MotionEvent.ACTION_DOWN:
Log.d(RowView,OnInterceptTouchEvent - 下);
tapDetector.onTouchEvent(EV);
返回false;
案例MotionEvent.ACTION_CANCEL:
Log.d(RowView,OnInterceptTouchEvent - 取消);
tapDetector.onTouchEvent(EV);
打破;
案例MotionEvent.ACTION_UP:
如果(tapDetector.onTouchEvent(EV)){
Log.d(RowView,OnInterceptTouchEvent - UP!);
返回true;
}
打破;
}
返回super.onInterceptTouchEvent(EV);
}
任何建议,以解决此问题?
修改:不工作的例子关于如何onItemClick在MainActivity不叫当ViewPager有效(棒棒堂列表选择不出现任何)
MainActivity
的ListView ListView的=(的ListView)findViewById(R.id.main_list);
listView.setAdapter(新MainListAdapter(这一点,30));
listView.setOnItemClickListener(新AdapterView.OnItemClickListener(){
@覆盖
公共无效onItemClick(适配器视图<>母公司视图中查看,INT位置,长的id){
Log.d(TAG,onItemClick:+位置);
}
});
列表项的XML:
< RelativeLayout的
的xmlns:机器人=http://schemas.android.com/apk/res/android
机器人:layout_width =match_parent
机器人:layout_height =80dp
机器人:descendantFocusability =blocksDescendants
>
<的TextView
机器人:ID =@ + ID / row_num
机器人:layout_width =WRAP_CONTENT
机器人:layout_height =WRAP_CONTENT
机器人:layout_alignParentBottom =真
机器人:layout_alignParentRight =真
机器人:layout_alignParentEnd =真
/>
< android.support.v4.view.ViewPager
机器人:ID =@ + ID / row_viewpager
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:能见度=看见
/>
< / RelativeLayout的>
清单适配器:
公共类MainListAdapter扩展了BaseAdapter {
私人上下文的背景下;
私人LayoutInflater充气;
私人诠释计数;
公共MainListAdapter(上下文的背景下,诠释计数){
this.context =背景;
this.inflater = LayoutInflater.from(上下文);
this.count =计数;
}
@覆盖
公众诠释getCount将(){
返回计数;
}
@覆盖
公共对象的getItem(INT位置){
返回的位置;
}
@覆盖
众长getItemId(INT位置){
返回的位置;
}
@覆盖
公共查看getView(INT位置,查看convertView,ViewGroup中父){
ViewHolder持有人;
如果(convertView == NULL){
持有人=新ViewHolder();
convertView = createRow(母公司持有);
} 其他 {
支架=(ViewHolder)convertView.getTag();
}
holder.textView.setText(Integer.toString(位置));
INT randomPages =(INT)(新的随机()nextDouble()* 5 + 2);
holder.viewPager.setAdapter(新NumAdapter(上下文,randomPages));
返回convertView;
}
私人查看createRow(ViewGroup中父,ViewHolder持有人){
查看查看= inflater.inflate(R.layout.row_main_listview,父母,假);
holder.textView =(TextView中)view.findViewById(R.id.row_num);
holder.viewPager =(ViewPager)view.findViewById(R.id.row_viewpager);
view.setTag(保持器);
返回查看;
}
私有静态类ViewHolder {
公众的TextView TextView的;
公共ViewPager viewPager;
}
}
ViewPager的适配器:
公共类NumAdapter扩展PagerAdapter {
私人LayoutInflater充气;
私人诠释计数;
公共NumAdapter(上下文的背景下,诠释计数){
this.inflater = LayoutInflater.from(上下文);
this.count =计数;
}
@覆盖
公共对象instantiateItem(ViewGroup中的容器,INT位置){
TextView中的TextView =(TextView中)inflater.inflate(R.layout.page_viewpager,集装箱,假);
textView.setText(页面+位置);
container.addView(TextView的);
返回的TextView;
}
@覆盖
公众诠释getCount将(){
返回计数;
}
@覆盖
公共布尔isViewFromObject(查看为arg0,对象ARG1){
返回将arg0 == ARG1;
}
@覆盖
公共无效destroyItem(ViewGroup中的容器,INT位置,Object对象){
container.removeView((查看)对象);
}
}
这是我做了什么终于来管理这虽然列表选择不工作。这可以改善,但是,就目前而言,这是我喜欢它是如何工作的唯一的解决方法。
公共类CustomListView扩展的ListView实现AbsListView.OnScrollListener {
/ *
*用于检测水龙头
* /
私人GestureDetector tapDetector;
/ *
*由于我们需要设置我们自己的OnScrollListener,这种存储一个
*使用外,如果有的话
* /
私人OnScrollListener onScrollListener;
私人布尔isScrolling = FALSE;
公共CustomListView(上下文的背景下){
超(上下文);
initView(上下文);
}
公共CustomListView(上下文的背景下,ATTRS的AttributeSet){
超(背景下,ATTRS);
initView(上下文);
}
公共CustomListView(上下文的背景下,ATTRS的AttributeSet,诠释defStyleAttr){
超(背景下,ATTRS,defStyleAttr);
initView(上下文);
}
@TargetApi(Build.VERSION_ codeS.LOLLIPOP)
公共CustomListView(上下文的背景下,ATTRS的AttributeSet,诠释defStyleAttr,诠释defStyleRes){
超(背景下,ATTRS,defStyleAttr,defStyleRes);
initView(上下文);
}
私人无效initView(上下文的背景下){
tapDetector =新GestureDetector(上下文,新TapListener());
super.setOnScrollListener(本);
}
@覆盖
公共无效setOnScrollListener(OnScrollListener onScrollListener){
this.onScrollListener = onScrollListener;
}
@覆盖
公共布尔dispatchTouchEvent(MotionEvent EV){
布尔isTap = tapDetector.onTouchEvent(EV);
如果(ev.getActionMasked()== MotionEvent.ACTION_UP){
//不要进行点击,如果ListView控件是滚动
//所以它能够停止滚动
如果(isTap&安培;&安培;!isScrolling&安培;&安培; hasOnItemClickListener()){
INT itemPosition = pointToPosition((int)的ev.getX(),(int)的ev.getY());
performItemClick(这一点,itemPosition,getItemIdAtPosition(itemPosition));
}
}
返回super.dispatchTouchEvent(EV);
}
公共布尔hasOnItemClickListener(){
返回getOnItemClickListener()!= NULL;
}
@覆盖
公共无效onScrollStateChanged(AbsListView观点,诠释scrollState){
isScrolling = scrollState = OnScrollListener.SCROLL_STATE_IDLE!;
如果(this.onScrollListener!= NULL){
onScrollListener.onScrollStateChanged(查看,scrollState);
}
}
@覆盖
公共无效onScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
如果(this.onScrollListener!= NULL){
onScrollListener.onScroll(查看,firstVisibleItem,visibleItemCount,totalItemCount);
}
}
I have a ViewPager inside every row of a ListView. It works fine, it changes the views inside it when the user use the swipe gesture, but it prevents the ListView's onItemClick method to be called. I know that the ViewPager is the culprit because when I hide it, the onItemClick is called, so this is what I am trying:
I have created a ViewGroup to be the row (RowView). This ViewGroup has onInterceptTouchEvent
overriden to avoid the ViewPager to handle further touch events when I detect a click. But the onItemClick callback is still not being called. And the list selector doesn't show either on click. I want this two features to work.
This is how the onInterceptTouchEvent from RowView looks like:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int actionMasked = ev.getActionMasked();
switch(actionMasked) {
case MotionEvent.ACTION_DOWN:
Log.d("RowView", "OnInterceptTouchEvent - Down");
tapDetector.onTouchEvent(ev);
return false;
case MotionEvent.ACTION_CANCEL:
Log.d("RowView", "OnInterceptTouchEvent - Cancel");
tapDetector.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
if(tapDetector.onTouchEvent(ev)) {
Log.d("RowView", "OnInterceptTouchEvent - UP!");
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
Any suggestions to solve this?
EDIT: Not working example about how the onItemClick in MainActivity is not called when the ViewPager is active (Lollipop list selector doesn't appear either)
MainActivity
ListView listView = (ListView) findViewById(R.id.main_list);
listView.setAdapter(new MainListAdapter(this, 30));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemClick: " + position);
}
});
List item XML:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:descendantFocusability="blocksDescendants"
>
<TextView
android:id="@+id/row_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
/>
<android.support.v4.view.ViewPager
android:id="@+id/row_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
/>
</RelativeLayout>
List adapter:
public class MainListAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private int count;
public MainListAdapter(Context context, int count) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.count = count;
}
@Override
public int getCount() {
return count;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null) {
holder = new ViewHolder();
convertView = createRow(parent, holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(Integer.toString(position));
int randomPages = (int) (new Random().nextDouble()*5+2);
holder.viewPager.setAdapter(new NumAdapter(context, randomPages));
return convertView;
}
private View createRow(ViewGroup parent, ViewHolder holder) {
View view = inflater.inflate(R.layout.row_main_listview, parent, false);
holder.textView = (TextView) view.findViewById(R.id.row_num);
holder.viewPager = (ViewPager) view.findViewById(R.id.row_viewpager);
view.setTag(holder);
return view;
}
private static class ViewHolder {
public TextView textView;
public ViewPager viewPager;
}
}
ViewPager's Adapter:
public class NumAdapter extends PagerAdapter {
private LayoutInflater inflater;
private int count;
public NumAdapter(Context context, int count) {
this.inflater = LayoutInflater.from(context);
this.count = count;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
TextView textView = (TextView) inflater.inflate(R.layout.page_viewpager, container, false);
textView.setText("Page " + position);
container.addView(textView);
return textView;
}
@Override
public int getCount() {
return count;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
}
This is what I've done finally to manage this although the list selector doesn't work. This could be improved, but, for now, it is the only workaround that I like how it works.
public class CustomListView extends ListView implements AbsListView.OnScrollListener {
/*
* Used for detect taps
*/
private GestureDetector tapDetector;
/*
* As we need to set our own OnScrollListener, this stores the one
* used outside, if any
*/
private OnScrollListener onScrollListener;
private boolean isScrolling = false;
public CustomListView(Context context) {
super(context);
initView(context);
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView(context);
}
private void initView(Context context) {
tapDetector = new GestureDetector(context, new TapListener());
super.setOnScrollListener(this);
}
@Override
public void setOnScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isTap = tapDetector.onTouchEvent(ev);
if(ev.getActionMasked() == MotionEvent.ACTION_UP) {
// Don't perform the click if the ListView is scrolling
// so it is able to stop the scroll
if(isTap && !isScrolling && hasOnItemClickListener()) {
int itemPosition = pointToPosition((int)ev.getX(), (int)ev.getY());
performItemClick(this, itemPosition, getItemIdAtPosition(itemPosition));
}
}
return super.dispatchTouchEvent(ev);
}
public boolean hasOnItemClickListener() {
return getOnItemClickListener() != null;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
isScrolling = scrollState != OnScrollListener.SCROLL_STATE_IDLE;
if(this.onScrollListener != null) {
onScrollListener.onScrollStateChanged(view, scrollState);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(this.onScrollListener != null) {
onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
这篇关于ViewPager里面的ListView行prevents onItemClick被解雇的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!