文档章节

Android-解决ViewFlipper与ScrollView滑动响应事件拦截的问题【转】

球球
 球球
发布于 2016/05/20 21:15
字数 965
阅读 14
收藏 0
点赞 2
评论 0

最近在做一个简单的展示界面时,遇到了一个比较棘手的问题。由于要展示多项内容,所以使用ViewFlipper作为水平滑动容器;而每项内容中由于许多文本较长,因此需要使用ScrollView作为垂直滑动容器。基本的界面布局大致如下:

外部文件common_list_view.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/geyan_query_view_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="@drawable/mid_bg">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="43dip"
android:orientation="vertical"
android:gravity="top"
android:layout_gravity="top">
<Gallery
android:id="@+id/gallery_data"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="top"
android:layout_gravity="top"
android:spacing="60dip"
android:paddingLeft="6dip"
android:paddingRight="6dip"
>
</Gallery>
</LinearLayout>
<ImageView
android:id="@+id/main_background"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<include layout="@layout/common_title_view"
android:id="@+id/title"/>
</RelativeLayout>

内部文件common_info_view.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/linear">
<TextView
android:id="@+id/text_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dip"
android:layout_marginTop="5dip"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#181712"
/>
<ScrollView
android:id="@+id/scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="5dip"
android:fadeScrollbars="true"
>
<TextView
android:id="@+id/text_detail"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.3"
android:textSize="18sp"
android:textColor="#181712"
android:singleLine="false"
/>
</ScrollView>
</LinearLayout>

由于ViewFlipper在外,ScrollView在内,因此一般的做法是定义一个手势响应类来处理响应事件,并将响应事件的处理交给内层的ScrollView。大致代码如下:

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
 
public class Test1 extends Activity {
 
	private ViewFlipper viewFlipper;
 
	private String[] descriptionsArray;
	private String[] titleArray;
 
	private int selectedPosition;
 
	private TextView textViewTitle;
	private TextView textViewContent;
	private FriendlyScrollView scroll;
 
	private LayoutInflater mInflater;
 
	private GestureDetector gestureDetector;
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
 
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.common_info_list_view);
 
		InitUI();
 
		super.onCreate(savedInstanceState);
 
		Toast.makeText(this, R.string.hello, Toast.LENGTH_SHORT).show();
	}
 
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
        super.onCreateOptionsMenu(menu);
        return false;
	}
 
	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		finish();
	}
 
	private void InitUI(){
 
		viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper_data);
 
		mInflater = LayoutInflater.from(this);
 
		fillDate();
 
		viewFlipper.addView(getContentView());
	}
 
	private void fillDate(){
		selectedPosition = 0;
 
		titleArray = getResources().getStringArray(R.array.title_array);
		descriptionsArray = getResources().getStringArray(R.array.description_array);
 
		gestureDetector = new GestureDetector(new CommonGestureListener());
	}
 
	private View getContentView() {
		View contentView = new View(this);
		contentView = mInflater.inflate(R.layout.common_info_item_view, null);
 
		textViewTitle = (TextView) contentView.findViewById(R.id.text_title);
		textViewContent = (TextView) contentView.findViewById(R.id.text_detail);
 
		textViewTitle.setText(titleArray[selectedPosition]);
		textViewTitle.setPadding(10, 0, 10, 0);
		textViewContent.setText(descriptionsArray[selectedPosition]);
		textViewContent.setPadding(10, 5, 10, 5);
 
		scroll = (FriendlyScrollView) contentView.findViewById(R.id.scroll);
		scroll.setOnTouchListener(onTouchListener);
		scroll.setGestureDetector(gestureDetector);
 
		return contentView;
	}
 
	private View.OnTouchListener onTouchListener = new View.OnTouchListener() {
 
		public boolean onTouch(View v, MotionEvent event) {
			// TODO Auto-generated method stub
			return gestureDetector.onTouchEvent(event);
		}
	};
 
	public class CommonGestureListener extends SimpleOnGestureListener {
 
		@Override
		public boolean onDown(MotionEvent e) {
			// TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "====> Jieqi: do onDown...");
			return false;
		}
 
		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "====> Jieqi: do onShowPress...");
			super.onShowPress(e);
		}
 
		@Override
	    public void onLongPress(MotionEvent e) {
	        // TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "----> Jieqi: do onLongPress...");
	    }
 
		@Override
		public boolean onSingleTapConfirmed(MotionEvent e) {
			// TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "====> Jieqi: do onSingleTapConfirmed...");
			return false;
		}
 
		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "====> Jieqi: do onSingleTapUp...");
			return false;
		}
 
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY){
			// TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "====> Jieqi: do onFling...");
			if (e1.getX() - e2.getX() > 100 && Math.abs(velocityX) > 50) {
				//向左
				selectedPosition = selectedPosition + 1 < titleArray.length ? (selectedPosition + 1) : 0;
				viewFlipper.addView(getContentView());
				viewFlipper.setInAnimation(AnimationControl.inFromRightAnimation());
                viewFlipper.setOutAnimation(AnimationControl.outToLeftAnimation());
                viewFlipper.showNext();
                viewFlipper.removeViewAt(0);
			} else if (e2.getX() - e1.getX() > 100 && Math.abs(velocityX) > 50) {
				//向右
				selectedPosition = selectedPosition > 0 ? (selectedPosition - 1) : (titleArray.length - 1);
				viewFlipper.addView(getContentView());
				viewFlipper.setInAnimation(AnimationControl.inFromLeftAnimation());
                viewFlipper.setOutAnimation(AnimationControl.outToRightAnimation());
				viewFlipper.showNext();
				viewFlipper.removeViewAt(0);
			}
			return true;
		}
 
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			// TODO Auto-generated method stub
			Log.d("QueryViewFlipper", "====> Jieqi: do onScroll...");
			return super.onScroll(e1, e2, distanceX, distanceY);
		}
 
    }
}

这个时候问题出现了,通过Log显示,当ScrollView中内容太短的时候,ScrollView不会触发OnScroll和OnFling事件,导致ViewFlipper左右滑动不响应。(当然后来的另一个测试表明这个问题在ListView上不存在)
为了解决这一个问题,我重新自定义了一个FriendlyScrollView类,来重写ScrollView的onTouchEvent和dispatchTouchEvent方法,具体如下:

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ScrollView;
 
public class FriendlyScrollView extends ScrollView {
 
	GestureDetector gestureDetector;
 
    public FriendlyScrollView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
 
	public FriendlyScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
 
	public FriendlyScrollView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}
 
	public void setGestureDetector(GestureDetector gestureDetector) {
		this.gestureDetector = gestureDetector;
	}
 
	@Override
	public boolean onTouchEvent(MotionEvent event) {
	    super.onTouchEvent(event);
	    return gestureDetector.onTouchEvent(event);
	}
 
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev){
	    gestureDetector.onTouchEvent(ev);
	    super.dispatchTouchEvent(ev);
	    return true;
	} 
 
}

然后将common_info_view.xml和程序中的ScrollView改成FriendlyScrollView,终于解决了这个问题。

 

 

 

© 著作权归作者所有

共有 人打赏支持
球球
粉丝 3
博文 111
码字总数 50993
作品 0
石景山
程序员
ViewPager,ScrollView 嵌套ViewPager滑动冲突解决

ViewPager,ScrollView 嵌套ViewPager滑动冲突解决 这篇博客主要讲解一下几个问题 粗略地介绍一下View的事件分发机制 解决事件滑动冲突的思路及方法 ScrollView 里面嵌套ViewPager导致的滑动...

丁佳辉 ⋅ 01/12 ⋅ 0

Android ScrollView滑动事件和子控件点击事件冲突

问题描述: 父控件是一个ScrollView,然后上面排满了按钮,类似于支付宝 这样,按钮都有onclick事件,这样滑动的时候如果接触点在按钮上,ScrollView就滑不动了。 解决方案是重写ScrollView ...

暖冰 ⋅ 2016/12/25 ⋅ 0

【Android】打造下拉放大效果

前言 在其他App上看到了这样的一个效果,感觉有点意思,于是决定实现一个类似的效果。 (其实是iOS的同学在是现功能的时候秀了一波操作) 效果大概是这样子的: UI看完后 “这个效果不错啊”...

带心情去旅行 ⋅ 今天 ⋅ 0

Android两条并排RecyclerView实时联动滑动增强

Android两条并排RecyclerView实时联动滑动增强 在附录1中,我初步实现了两条垂直摆放的RecyclerView的实时联动滚动,但是附录文章1的实现存在一定问题,比如当用户的手指同时在屏幕的两条Rec...

zhangphil ⋅ 04/24 ⋅ 0

ScrollView嵌套ScrollView的滑动冲突

结论: 在自定义控件中如下重写就告诉所有父View:不要拦截事件,让我消费!! 这是一个从源码角度分析滑动冲突的原因 以及在源码中理解为何能解决滑动冲突 这是MainActivity主界面的布局内容...

William_Huang ⋅ 03/16 ⋅ 0

安卓自定义View进阶-事件分发机制原理

安卓自定义View进阶-事件分发机制原理 之前讲解了很多与View绘图相关的知识,你可以在 安卓自定义View教程目录 中查看到这些文章,如果你理解了这些文章,那么至少2D绘图部分不是难题了,大部...

猴亮屏 ⋅ 05/22 ⋅ 0

Android取消RecyclerView、ListView、ScrollView、HorizontalScrollView滑动到边缘闪现灰白色水波纹动画

Android取消RecyclerView、ListView、ScrollView、HorizontalScrollView滑动到边缘闪现灰白色水波纹动画 标准的Android RecyclerView、ListView、ScrollView、HorizontalScrollView滑动到边缘...

zhangphil ⋅ 05/04 ⋅ 0

第七章 View的滑动冲突

1. 概述   在进行Android开发的时候,都可能会碰到滑动冲突。有时候,下载了一个Demo运行的好好的,但是出现滑动冲突,这样导致Demo运行崩溃。然后,整个人都炸了。下面来分析下滑动冲突是...

忆念成风 ⋅ 2017/11/14 ⋅ 0

Android滑动冲突处理

在我们平时项目开发的过程中,是不是会遇到滑动View之间的相互嵌套,比如外部的Scrollview或SwipeRefreshLayout嵌套内部的Viewpager或横向Recyclerview,如外部Viewpager嵌套内部Viewpager。...

翻滚吧李博 ⋅ 2017/12/14 ⋅ 0

2018届应届生android面试总结

写在前面 四月份结束了拥抱变化后的大规模面试后,2018届android校招面试总结:百度,大疆,乐视,知乎在五月份里,自己进行了最后俩次面试。算是对自己的大学生涯的一个交代。 面试过程 这俩...

MDove ⋅ 05/23 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

内核线程、轻量级进程、用户线程

线程与进程概念 在现代操作系统中,进程支持多线程。 进程是资源管理的最小单元; 线程是程序执行的最小单元。 即线程作为调度和分配的基本单位,进程作为资源分配的基本单位 一个进程的组成...

117 ⋅ 26分钟前 ⋅ 0

elasticsearch2.4.6升级为elasticsearch-5.5.0的经历

将elasticsearch-5.5.0 中的配置 path.data 指向原来的数据路径 即 path.data: /usr/local/src/elasticsearch-2.4.6/data 注意: elasticsearch-5.5.0 需要将jdk版本升级到1.8...

晨猫 ⋅ 27分钟前 ⋅ 1

lvm讲解 磁盘故障小案例

1

oschina130111 ⋅ 31分钟前 ⋅ 0

那些提升开发人员工作效率的在线工具

本文转载自公众号 Hollis 作为一个Java开发人员,经常要和各种各样的工具打交道,除了我们常用的IDE工具以外,其实还有很多工具是我们在日常开发及学习过程中要经常使用到的。 Hollis偏爱使用...

时刻在奔跑 ⋅ 44分钟前 ⋅ 0

restful风格 实现DELETE PUT请求 的web.xml的配置

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframe......

泉天下 ⋅ 49分钟前 ⋅ 0

Shell数组

Shell数组 Shell在编程方面比Windows批处理强大很多,无论是在循环、运算。 bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数...

蜗牛奔跑 ⋅ 58分钟前 ⋅ 0

nmap为了开发方便 可以做简单的修改

因为nmap扫描是默认使用的是nse脚本,但是在开发的过程中需要修改后缀(主要是因为后缀为lua才能显示高亮,所以这里用一个取巧的办法) nse_main.lua文件中我们找到如下代码 local t, path = cn...

超级大黑猫 ⋅ 今天 ⋅ 0

springmvc获取axios数据为null情况

场景:前端用了vue没有用ajax与后台通信,用了axios,但是在代码运行过程中发现axios传递到后台的值接受到数据为null。 问题原因:此处的问题在与axios返回给后台的数据为json类型的,后台接...

王子城 ⋅ 今天 ⋅ 0

hadoop技术入门学习之发行版选择

经常会看到这样的问题:零基础学习hadoop难不难?有的人回答说:零基础学习hadoop,没有想象的那么难,也没有想象的那么容易。看到这样的答案不免觉得有些尴尬,这个问题算是白问了,因为这个...

左手的倒影 ⋅ 今天 ⋅ 0

806. Number of Lines To Write String - LeetCode

Question 806. Number of Lines To Write String Solution 思路:注意一点,如果a长度为4,当前行已经用了98个单元,要另起一行。 Java实现: public int[] numberOfLines(int[] widths, Str...

yysue ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部