GestureListener详解:
监听手势的关键是:GestureListener给我们提供了下述的回调方法:
- 按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
- 抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。
- 长按(onLongPress): 手指按在持续一段时间,并且没有松开。
- 滚动(onScroll): 手指在触摸屏上滑动。
- 按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。
- 抬起(onSingleTapUp):手指离开触摸屏的那一刹那。
知道了GestureListener的相关方法后,实现手势检测也很简单,步骤如下:
实现翻页效果的话,我们这边要用到的是:ViewFlipper(翻转视图)。还有动画效果,忘记了的话,可以去之前的博客: https://blog.youkuaiyun.com/lpcrazyboy/article/details/80754887
- Step 1: 创建GestureDetector对象,创建时需实现GestureListener传入
- Step 2: 将Activity或者特定组件上的TouchEvent的事件交给GestureDetector处理即可!我们写个简单的代码来验证这个流程,即重写对应的方法:
效果如下:
activity_main.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/practise_rLayoutRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_white"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/practise_tvNum"
android:layout_width="50dp"
android:layout_height="25dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginTop="10dp"
android:background="@drawable/text_shapestyle"
android:gravity="center"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:text="1/122"
android:textColor="@color/text_white"
android:textSize="@dimen/text_elementsize" />
<TextView
android:id="@+id/practise_tvQType"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/practise_tvNum"
android:gravity="center_vertical"
android:text="单选题"
android:textColor="@color/text_black"
android:textSize="@dimen/text_elementsize" />
<Button
android:id="@+id/practise_btnSetTextSize"
android:layout_width="60dp"
android:layout_height="25dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:paddingLeft="5dp"
android:layout_toRightOf="@+id/practise_tvQType"
android:background="@drawable/btn_shapestyle"
android:layout_centerVertical="true"
android:drawableLeft="@drawable/textsize_image"
android:text="字号"
android:textColor="@color/text_white"
android:textSize="@dimen/text_elementsize"/>
<TextView
android:id="@+id/practise_tvTestTime"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp"
android:layout_toLeftOf="@+id/practise_ivCollectYN"
android:gravity="center_vertical"
android:text="00:00:00"
android:textColor="@color/text_black"
android:textSize="@dimen/text_elementsize" />
<ImageView
android:id="@+id/practise_ivCollectYN"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:scaleType="fitCenter"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:src="@drawable/fav"
android:visibility="invisible"/>
</RelativeLayout>
<ViewFlipper
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewFlipper"/>
</LinearLayout>
<!-- 按钮功能模块 -->
<TableLayout
android:id="@+id/practise_tlfunction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
>
<!-- 分割线 -->
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#33000000" />
<TableRow
android:id="@+id/practise_trfunctionBtns"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/practise_btnSubmit"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:drawableTop="@drawable/lock"
android:background="@drawable/btnclick_bg_lightgray"
android:gravity="center"
android:text="交卷"
android:textSize="@dimen/text_elementsize"
android:textColor="@color/text_black"
android:paddingTop="4dp"
android:layout_weight="1"
/>
<Button
android:id="@+id/practise_btnPrevious"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:drawableTop="@drawable/previous"
android:background="@drawable/btnclick_bg_lightgray"
android:gravity="center"
android:text="上一题"
android:textSize="@dimen/text_elementsize"
android:textColor="@color/text_black"
android:paddingTop="4dp"
android:layout_weight="1"
/>
<Button
android:id="@+id/practise_btnNext"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:drawableTop="@drawable/next"
android:background="@drawable/btnclick_bg_lightgray"
android:text="下一题"
android:textSize="@dimen/text_elementsize"
android:textColor="@color/text_black"
android:gravity="center"
android:paddingTop="4dp"
android:layout_weight="1"
/>
<Button
android:id="@+id/practise_btnMark"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:drawableTop="@drawable/collect"
android:background="@drawable/btnclick_bg_lightgray"
android:text="标记"
android:textSize="@dimen/text_elementsize"
android:textColor="@color/text_black"
android:gravity="center"
android:paddingTop="4dp"
android:layout_weight="1"
/>
<Button
android:id="@+id/practise_btnNumMenu"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:drawableTop="@drawable/numbermenu"
android:background="@drawable/btnclick_bg_lightgray"
android:text="题卡"
android:gravity="center"
android:textSize="@dimen/text_elementsize"
android:paddingTop="4dp"
android:layout_weight="1"
/>
</TableRow>
</TableLayout>
</RelativeLayout >
每一个翻转视图的页面布局activity_chnihealthreport.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:fitsSystemWindows="true"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16dp"
android:paddingLeft="10dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:textColor="#646464"
android:text="您的皮肤在不知不觉中会出现青紫瘀斑、皮下出血吗?(指皮肤在没有外伤的情况下出现青一块紫一块的情况)"
android:id="@+id/tv_question" />
<ListView
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lv_question_answer"/>
</LinearLayout>
接下来,要写一个ListView的数据适配器:ChineseMedicineReportAdapter.java的代码如下:(选项内容)
package com.deepreality.gesturechangepagedemo;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ChineseMedicineReportAdapter extends BaseAdapter {
Context context;
Question quesions;
public ChineseMedicineReportAdapter(Context context, Question quesions) {
this.context = context;
this.quesions = quesions;
}
@Override
public int getCount() {
return quesions.getAnswer().size();
}
@Override
public Object getItem(int position) {
return quesions.getAnswer().get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(context, R.layout.item_answer_list, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Question.Answer answer = quesions.getAnswer().get(position);
holder.tvText.setText(answer.getAnswerMessage());
holder.tvText.setTextSize(16);
return convertView;
}
static class ViewHolder {
TextView tvText;
ViewHolder(View view) {
tvText = view.findViewById(R.id.tv_answer);
}
}
}
最后,在相应的Activity中调用并处理相关操作。
GestureFilpActivity.java的代码如下:
package com.deepreality.gesturechangepagedemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
import java.util.ArrayList;
import java.util.List;
public class GestureFilpActivity extends AppCompatActivity implements GestureDetector.OnGestureListener{
ViewFlipper mViewFlipper;
//1.定义手势检测器对象
GestureDetector mGestureDetector;
//2.定义一个动画数组,用于为ViewFilpper指定切换动画效果。
Animation[] animations = new Animation[4];
//3.定义手势两点之间的最小距离
private static int FLIP_DISTANCE = 100 ;
List<Question> mQuestion = new ArrayList<>();
ChineseMedicineReportAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewFlipper = findViewById(R.id.viewFlipper);
//1.构建手势检测器
mGestureDetector = new GestureDetector(GestureFilpActivity.this,this);
//2准备数据
List<Question> questions = initData();
mQuestion.addAll(questions);
//3.为ViewFilpper添加子控件。
for (int i = 0;i<mQuestion.size();i++){
Question question = mQuestion.get(i);
mViewFlipper.addView(addQuestionView(question));
}
//4.初始化Animation数组
animations[0] = AnimationUtils.loadAnimation(this,R.anim.left_in);
animations[1] = AnimationUtils.loadAnimation(this,R.anim.left_out);
animations[2] = AnimationUtils.loadAnimation(this,R.anim.right_in);
animations[3] = AnimationUtils.loadAnimation(this,R.anim.right_out);
}
private View addQuestionView(Question question){
View view = View.inflate(this, R.layout.activity_chnihealthreport, null);
TextView tes = (TextView) view.findViewById(R.id.tv_question);
ListView listview = (ListView) view.findViewById(R.id.lv_question_answer);
listview.addHeaderView(new View(this));
listview.addFooterView(new View(this));
adapter = new ChineseMedicineReportAdapter(this, question);
listview.setAdapter(adapter);
tes.setText(question.getQuestion());
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(GestureFilpActivity.this,position + "", Toast.LENGTH_SHORT).show();
if (mViewFlipper.getDisplayedChild() == mQuestion.size() - 1) {
Toast.makeText(GestureFilpActivity.this,"最后一个题", Toast.LENGTH_SHORT).show();
mViewFlipper.stopFlipping();
return;
}else {
mViewFlipper.setInAnimation(animations[0]);
mViewFlipper.setOutAnimation(animations[1]);
mViewFlipper.showNext();
}
}
});
return view;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Toast.makeText(GestureFilpActivity.this,"按下",Toast.LENGTH_SHORT).show();
}
//重点实现在这里切换
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (e1.getX() - e2.getX() < FLIP_DISTANCE){
if (mViewFlipper.getDisplayedChild() == 0) {
mViewFlipper.stopFlipping();
Toast.makeText(GestureFilpActivity.this,"第一个题",Toast.LENGTH_SHORT).show();
return false;
} else {
mViewFlipper.setInAnimation(animations[2]);
mViewFlipper.setOutAnimation(animations[3]);
mViewFlipper.showPrevious();
return true;
}
}else if (e1.getX() - e2.getX() > FLIP_DISTANCE){
if (mViewFlipper.getDisplayedChild() == mQuestion.size() - 1) {
Toast.makeText(GestureFilpActivity.this,"最后一个题",Toast.LENGTH_SHORT).show();
mViewFlipper.stopFlipping();
return false;
}else {
mViewFlipper.setInAnimation(animations[0]);
mViewFlipper.setOutAnimation(animations[1]);
mViewFlipper.showNext();
return true;
}
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//将Activity上的触发的事件交个GestureDetector处理
return mGestureDetector.onTouchEvent(event);
}
private List<Question> initData(){
List<Question> questions = new ArrayList<>();
Question q1 = new Question();
q1.setQuestion("1、\"红娘\"由来是出自下列哪部古典名剧:");
List<Question.Answer> mA = new ArrayList<>();
Question.Answer a1 = new Question.Answer();
a1.setAnswerMessage("A《琵琶记》");
Question.Answer a2 = new Question.Answer();
a2.setAnswerMessage("B《西厢记》");
Question.Answer a3 = new Question.Answer();
a3.setAnswerMessage("C《长生殿》");
Question.Answer a4 = new Question.Answer();
a4.setAnswerMessage("D《桃花扇》");
mA.add(a1);
mA.add(a2);
mA.add(a3);
mA.add(a4);
q1.setAnswer(mA);
questions.add(q1);
Question q2 = new Question();
q2.setQuestion("2.我国第一部有声影片是:");
List<Question.Answer> mB = new ArrayList<>();
Question.Answer b1 = new Question.Answer();
b1.setAnswerMessage("A《歌女红牡丹》");
Question.Answer b2 = new Question.Answer();
b2.setAnswerMessage("B《定军山》");
Question.Answer b3 = new Question.Answer();
b3.setAnswerMessage("C《林则徐》");
Question.Answer b4 = new Question.Answer();
b4.setAnswerMessage("D《玉人何处》");
mB.add(b1);
mB.add(b2);
mB.add(b3);
mB.add(b4);
q2.setAnswer(mB);
questions.add(q2);
Question q3= new Question();
q3.setQuestion("3.下列哪座山不属于我国四大佛山之一:( A)");
List<Question.Answer> mC = new ArrayList<>();
Question.Answer c1 = new Question.Answer();
c1.setAnswerMessage("A《歌女红牡丹》");
Question.Answer c2 = new Question.Answer();
c2.setAnswerMessage("B《定军山》");
Question.Answer c3 = new Question.Answer();
c3.setAnswerMessage("C《林则徐》");
Question.Answer c4 = new Question.Answer();
c4.setAnswerMessage("D《玉人何处》");
mC.add(c1);
mC.add(c2);
mC.add(c3);
mC.add(c4);
q3.setAnswer(mC);
questions.add(q3);
Question q4 = new Question();
q4.setQuestion("4.下面哪个是对“惊蛰”这个节气的正确描述?");
List<Question.Answer> mD = new ArrayList<>();
Question.Answer d1 = new Question.Answer();
d1.setAnswerMessage("A《歌女红牡丹》");
Question.Answer d2 = new Question.Answer();
d2.setAnswerMessage("B《定军山》");
Question.Answer d3 = new Question.Answer();
d3.setAnswerMessage("C《林则徐》");
Question.Answer d4 = new Question.Answer();
d4.setAnswerMessage("D《玉人何处》");
mD.add(d1);
mD.add(d2);
mD.add(d3);
mD.add(d4);
q4.setAnswer(mD);
questions.add(q4);
return questions;
}
}