【问题标题】:Impementing Vertical Scroll with horizontal swipe in Android在 Android 中使用水平滑动实现垂直滚动
【发布时间】:2014-01-18 06:23:49
【问题描述】:

我正在尝试使用 OnGestureListener 在 Android 中滑动。如果文本超出布局高度,我需要垂直滚动文本。我需要 Verical 滚动和水平滑动应该一起工作。

代码是:

package com.example.gestures;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Menu;
import android.view.MotionEvent;
import android.widget.TextView;
import android.widget.Toast;

public class Gestures extends Activity implements OnGestureListener {
GestureDetector gDetector;TextView tv;
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gestures);
        gDetector = new GestureDetector(this);
        tv=(TextView)findViewById(R.id.tv);

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.gestures, menu);
        return true;
    }

    @Override
    public boolean onDown(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onDown","In OnDown");
        return true;

    }

    public void rightToLeft() {

        //tv.setText("There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.");
    tv.setText("ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssALGIERS (Reuters) - Algerian President Abdelaziz Bouteflika, who suffered a stroke last year, has been in a Paris hospital since Monday for a long-planned check-up and he is making steady progress, the state news agency APS said on Tuesday.Algerians vote for a new president in April. Bouteflika, 76, has yet to announce whether he will run again after more than 10 years at the helm of the major North African oil producer.To complete his health assessment, started in Algiers, and under a routine medical control ... planned since June 2013, the President of the Republic Abdelaziz Bouteflika is staying at Val-de-Grace hospital, it said. The president's health is improving certainly and progressively.APS, citing a presidential statement, said Bouteflika would remain at the hospital until Friday.A veteran of Algeria's independence war against France, Bouteflika suffered a stroke in early 2013, forcing him to be rushed to hospital in France. He returned to Algeria in July to convalesce and has made only a few public appearances recently.");
    }
    public void lefttoRight() {
        tv.setText("leftToRight LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup Layout Attributes for a list of all child view attributes that this class supports. ");
        }

    @Override
    public boolean onFling(MotionEvent start, MotionEvent finish, float velocityX,
            float velocityY) {
        // TODO Auto-generated method stub
        //TextView t=(TextView)findViewById(R.id.tv);
        /*if(start.getRawX() < finish.getRawX())
        {
            Log.d("onFling","in inFling");
        }
        else if(start.getRawX()>finish.getRawX())
        {
            Log.d("onFLing","in onFling");
        }*/
        if (Math.abs(start.getY() - finish.getY()) > SWIPE_MAX_OFF_PATH)
            return false;
        // right to left swipe

        if(start.getX() - finish.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

        lefttoRight();

        }  
        else if (finish.getX() - start.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
     rightToLeft();
        }
        return true;
    }


    @Override
    public boolean onTouchEvent(MotionEvent me) {
    return gDetector.onTouchEvent(me);
    }

    @Override
    public void onLongPress(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onLongPress","in onlongpress");
    }



    @Override
    public void onShowPress(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onShowPress","in onShowPress");

    }

    @Override
    public boolean onSingleTapUp(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onSingleTapup","in onsingletapup");
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
            float arg3) {
        // TODO Auto-generated method stub
        return false;
    }

}

Xml 是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".Gestures" >



    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >


        <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
        </LinearLayout>

    </ScrollView>

</RelativeLayout>

问题是有时滚动工作和滑动工作不正常。请让我知道如何解决这个问题。提前致谢。 当我尝试 dispatchTouchEvent 时,它适用于 Activity 但是当我尝试将 TouchListener 添加到屏幕的一部分时,滚动不起作用。代码是:

package com.example.testswipe;





import java.util.Date;
import java.util.HashMap;





import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

public class TestSwipe extends Activity {
RelativeLayout rel;TextView tv;
int wwidth,topheight;ScrollView scrollView;
GestureDetector gestureDetector ;

private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
RelativeLayout relLayout,firstrel;LinearLayout linearLayout,linLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    setContentView(R.layout.sec);
        rel=(RelativeLayout)findViewById(R.id.rel);




        final LayoutInflater  inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LinearLayout ll=new LinearLayout(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        ll.setLayoutParams(params);
        relLayout=(RelativeLayout)inflater.inflate(R.layout.activity_one, null);
        firstrel=(RelativeLayout)inflater.inflate(R.layout.activity_test_swipe, null);
        tv=(TextView)relLayout.findViewById(R.id.textView1);
        // scrollView=(ScrollView)relLayout.findViewById(R.id.scrollView1);

        linLayout=(LinearLayout)findViewById(R.id.layout1);

        linearLayout=(LinearLayout)relLayout.findViewById(R.id.linlayouts);

            DisplayMetrics displaymetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
            System.out.println("Density is"+displaymetrics.densityDpi);
            Toast.makeText(getApplicationContext(), "Density is"+displaymetrics.densityDpi, Toast.LENGTH_LONG).show();
            int height = displaymetrics.heightPixels;
             wwidth= displaymetrics.widthPixels;
            System.out.println("Heightis"+height);
            System.out.println("Width is"+wwidth);
        //  int changedheight=(int) (0.1*height);
        //  int remainedheight=height-changedheight;
             topheight=(int) (0.2*height);
            int bottomheight=height-topheight;
        //LinearLayout rl=(LinearLayout)inflater.inflate

            linLayout.addView(firstrel,wwidth,topheight);

            linLayout.addView(relLayout, wwidth,bottomheight);
            OnSwipeTouchListener swp=new OnSwipeTouchListener();

        gestureDetector = new GestureDetector(swp.new GestureListener());


            linearLayout.setOnTouchListener(swp);



    }









    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        super.dispatchTouchEvent(ev);

        return gestureDetector.onTouchEvent(ev);
    }









    public class OnSwipeTouchListener implements OnTouchListener {


    //  GestureDetector gestureDetector = new GestureDetector(new GestureListener());

        public boolean onTouch(final View v, final MotionEvent event) {
          return gestureDetector.onTouchEvent(event);

        }
        private final class GestureListener extends SimpleOnGestureListener {

            private static final int SWIPE_THRESHOLD = 100;
            private static final int SWIPE_VELOCITY_THRESHOLD = 100;


            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                onTouch(e);
                return true;
            }



            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;}



            public void rightToLeft() {

                //tv.setText("There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.");
            tv.setText("ALGIERS (Reuters) - Algerian President Abdelaziz Bouteflika, who suffered a stroke last year, has been in a Paris hospital since Monday for a long-planned check-up and he is making steady progress, the state news agency APS said on Tuesday.Algerians vote for a new president in April. Bouteflika, 76, has yet to announce whether he will run again after more than 10 years at the helm of the major North African oil producer.To complete his health assessment, started in Algiers, and under a routine medical control ... planned since June 2013, the President of the Republic Abdelaziz Bouteflika is staying at Val-de-Grace hospital, it said. The president's health is improving certainly and progressively.APS, citing a presidential statement, said Bouteflika would remain at the hospital until Friday.A veteran of Algeria's independence war against France, Bouteflika suffered a stroke in early 2013, forcing him to be rushed to hospital in France. He returned to Algeria in July to convalesce and has made only a few public appearances recently.");
            }
            public void lefttoRight() {
                tv.setText("leftToRight LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup Layout Attributes for a list of all child view attributes that this class supports. ");
                }

            @Override
            public boolean onFling(MotionEvent start, MotionEvent finish, float velocityX, float velocityY) {


            System.out.println("in onswipetouch nFling()");
            if (Math.abs(start.getY() - finish.getY()) > SWIPE_MAX_OFF_PATH)
                 return false;
             // right to left swipe

             if(start.getX() - finish.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

                lefttoRight();

             }  
             else if (finish.getX() - start.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
          rightToLeft();
                }

            return true;
        }


        }
        public boolean onTouch(MotionEvent e) {
            return true;
        }

        }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.test_swipe, menu);
        return true;
    }

}

而xml文件是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/relLayout"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="@android:color/darker_gray"
    tools:context=".TestSwipe" >


     <ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >



        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:id="@+id/linlayouts" >

<TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:text="@string/hello_world"
         />


   </LinearLayout>
</ScrollView>














</RelativeLayout>

在这个滚动不工作。请帮助我。

【问题讨论】:

  • 你要水平滑动到什么地方?
  • 当我水平滑动时,TextView 中的文本应该会发生变化,如果超过布局高度,那么它应该是可滚动的。

标签: android vertical-scrolling swipe-gesture


【解决方案1】:

您需要将以下代码添加到您的活动中。使用此代码,ActivityGestureDetector 有机会看到触摸事件。

@Override
public boolean dispatchTouchEvent(MotionEvent ev){
    super.dispatchTouchEvent(ev);
    return gDetector.onTouchEvent(ev);
}

编辑:你说你想要一个使用 LinearLayout 的例子。

package com.brianattwell.app;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Menu;
import android.view.MotionEvent;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnGestureListener {
    GestureDetector gDetector;TextView tv;
    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 200;
    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gDetector = new GestureDetector(this);
        tv=(TextView)findViewById(R.id.tv);

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev){
        super.dispatchTouchEvent(ev);
        return gDetector.onTouchEvent(ev);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        //getMenuInflater().inflate(R.menu., menu);
        return true;
    }

    @Override
    public boolean onDown(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onDown","In OnDown");
        return true;

    }

    public void rightToLeft() {

        //tv.setText("There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.");
        tv.setText("ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssALGIERS (Reuters) - Algerian President Abdelaziz Bouteflika, who suffered a stroke last year, has been in a Paris hospital since Monday for a long-planned check-up and he is making steady progress, the state news agency APS said on Tuesday.Algerians vote for a new president in April. Bouteflika, 76, has yet to announce whether he will run again after more than 10 years at the helm of the major North African oil producer.To complete his health assessment, started in Algiers, and under a routine medical control ... planned since June 2013, the President of the Republic Abdelaziz Bouteflika is staying at Val-de-Grace hospital, it said. The president's health is improving certainly and progressively.APS, citing a presidential statement, said Bouteflika would remain at the hospital until Friday.A veteran of Algeria's independence war against France, Bouteflika suffered a stroke in early 2013, forcing him to be rushed to hospital in France. He returned to Algeria in July to convalesce and has made only a few public appearances recentlsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssALGIERS (Reuters) - Algerian President Abdelaziz Bouteflika, who suffered a stroke last year, has been in a Paris hospital since Monday for a long-planned check-up and he is making steady progress, the state news agency APS said on Tuesday.Algerians vote for a new president in April. Bouteflika, 76, has yet to announce whether he will run again after more than 10 years at the helm of the major North African oil producer.To complete his health assessment, started in Algiers, and under a routine medical control ... planned since June 2013, the President of the Republic Abdelaziz Bouteflika is staying at Val-de-Grace hospital, it said. The president's health is improving certainly and progressively.APS, citing a presidential statement, said Bouteflika would remain at the hospital until Friday.A veteran of Algeria's independence war against France, Bouteflika suffered a stroke in early 2013, forcing him to be rushed to hospital in France. He returned to Algeria in July to convalesce and has made only a few public appearances recentlsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssALGIERS (Reuters) - Algerian President Abdelaziz Bouteflika, who suffered a stroke last year, has been in a Paris hospital since Monday for a long-planned check-up and he is making steady progress, the state news agency APS said on Tuesday.Algerians vote for a new president in April. Bouteflika, 76, has yet to announce whether he will run again after more than 10 years at the helm of the major North African oil producer.To complete his health assessment, started in Algiers, and under a routine medical control ... planned since June 2013, the President of the Republic Abdelaziz Bouteflika is staying at Val-de-Grace hospital, it said. The president's health is improving certainly and progressively.APS, citing a presidential statement, said Bouteflika would remain at the hospital until Friday.A veteran of Algeria's independence war against France, Bouteflika suffered a stroke in early 2013, forcing him to be rushed to hospital in France. He returned to Algeria in July to convalesce and has made only a few public appearances recently.");
    }
    public void lefttoRight() {
        tv.setText("leftToRight LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup Layout Attributes for a list of all child view attributes that this class supportsght LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup Layout Attributes for a list of all child view attributes that this class supportsght LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup Layout Attributes for a list of all child view attributes that this class supports. ");
    }

    @Override
    public boolean onFling(MotionEvent start, MotionEvent finish, float velocityX,
                           float velocityY) {
        // TODO Auto-generated method stub
        //TextView t=(TextView)findViewById(R.id.tv);
        /*if(start.getRawX() < finish.getRawX())
        {
            Log.d("onFling","in inFling");
        }
        else if(start.getRawX()>finish.getRawX())
        {
            Log.d("onFLing","in onFling");
        }*/
        if (Math.abs(start.getY() - finish.getY()) > SWIPE_MAX_OFF_PATH)
            return false;
        // right to left swipe

        if(start.getX() - finish.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

            lefttoRight();

        }
        else if (finish.getX() - start.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
            rightToLeft();
        }
        return true;
    }


    @Override
    public boolean onTouchEvent(MotionEvent me) {
        return gDetector.onTouchEvent(me);
    }

    @Override
    public void onLongPress(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onLongPress","in onlongpress");
    }



    @Override
    public void onShowPress(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onShowPress","in onShowPress");

    }

    @Override
    public boolean onSingleTapUp(MotionEvent arg0) {
        // TODO Auto-generated method stub
        Log.d("onSingleTapup","in onsingletapup");
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
                            float arg3) {
        // TODO Auto-generated method stub
        return false;
    }

}

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Gestures" >



    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

            <TextView
                android:id="@+id/tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />

    </ScrollView>

</LinearLayout>

【讨论】:

  • 谢谢它对 Activity 有效,但我尝试将 TouchListener 添加到 linearlayout 滚动不起作用。请帮助我。
  • 对不起,我误读了您的评论。我不认为它应该有所作为。让我检查一下。
  • 谢谢它为 Activity 工作,但我在一个类中实现了 TouchListener(OnSwipeTouchListener)。我试图将 TouchListener 添加到线性布局(OnSwipeTouchListener swp=new OnSwipeTouchListener();gestureDetector = new GestureDetector(swp.new GestureListener ());linearLayout.setOnTouchListener(swp); 滚动不起作用。请帮帮我。
  • 我刚刚粘贴了对您的代码的修改,它使用 LinearLayout。
  • 滑动应该适用于部分屏幕,所以我在 ScrollView 中使用了一个线性布局并将 TouchListener 添加到线性布局中。请您提供您的邮件 ID。我将发布代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-01
相关资源
最近更新 更多