Android开发:水平方向和垂直方向同时滚动


在这篇()文章中,我们讲到了使用 ScrollView HorizontalScrollView ,可以在同一时刻让屏幕要么在水平方向滚动,要么在垂直方向滚动。但却不能同时在水平和垂直两个方向滚动。这篇文章的目的就是为了解决同时在两个方向滚动的问题。  

1.     创建一个 Android Project ,将 desktop.png( 大小为 1280 x 900) ,拷贝到 res/drawable-mdpi 文件夹下。

2.     修改 Activity 所对应的 Java 代码,使之如下:

package com.pat.gui;

 

import android.app.Activity;

import android.content.Context;

import android.content.res.Configuration;

import android.content.res.Resources;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.os.Bundle;

import android.util.DisplayMetrics;

import android.view.GestureDetector;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.Window;

import android.view.WindowManager;

import android.view.GestureDetector.OnGestureListener;

import android.widget.Toast;

 

public class ScrollPicture extends Activity

implements

OnGestureListener

{

         private int X = 0;

         private int Y = 0;

        

         private static int scrollX = 0;

         private static int scrollY = 0;

        

         PictureView main;

         Bitmap bmp;

         Bitmap adapt;

         Resources res;

         Paint paint;

         GestureDetector gestureDetector;

         DisplayMetrics dm;

        

    @Override

    public void onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

        gestureDetector = new GestureDetector(this);

        paint = new Paint();

        // 获取图像

        res = getResources();

        bmp = BitmapFactory.decodeResource(res, R.drawable.desktop);

        // 获取图像的宽度和高度

        X = bmp.getWidth();

        Y = bmp.getHeight();

       

        // adapt bmp 显示在屏幕上的那部分图像,见 PictureView 中的 handleScroll 方法

        adapt = Bitmap.createBitmap(bmp);

        main = new PictureView(this);

       

        // 去掉标题栏

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // 全屏显示

        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                                                            WindowManager.LayoutParams.FLAG_FULLSCREEN);

       

        //setContentView(R.layout.main);

        setContentView(main, new ViewGroup.LayoutParams(X, Y));

       

        // landscape 方式显示

        this.setRequestedOrientation(Configuration.ORIENTATION_LANDSCAPE);

       

        // 获取屏幕尺寸

        dm = new DisplayMetrics();

        getWindowManager().getDefaultDisplay().getMetrics(dm);

     }

 

    // 屏幕翻转时,要重新获取 dm 。要使 onConfigurationChanged 可以被触发,必须做到:

    // 1. AndroidManifest.xml Activity 标签中,增加属性 android:configChanges="orientation"

    // 2. AndroidManifest.xml ,须增加权限:

    //    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"/>

    // 当屏幕显示有 landscape 变成 portrait ,或者有 portrait 变成 landscape 是,都会触发 onConfigurationChanged

         @Override

         public void onConfigurationChanged(Configuration newConfig)

         {

                   if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)

                   {

                            // 获取屏幕尺寸

                            dm = new DisplayMetrics();

                    getWindowManager().getDefaultDisplay().getMetrics(dm);

                    // 重新计算 adapt 。显示 desktop.png 的左上角开始,占整个屏幕尺寸大小的那部分

                    adapt = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);

                    // scrollX scrollY 分别为在水平或者垂直方向上,滚动的像素值

                    scrollX = 0;

                    scrollY = 0;

                    // 重画

                            main.invalidate();

                    Toast.makeText(this, "(" + dm.widthPixels + ", " + dm.heightPixels + ")", Toast.LENGTH_SHORT).show();

                   }

                  

                   if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)

                   {

                            dm = new DisplayMetrics();

                    getWindowManager().getDefaultDisplay().getMetrics(dm);

                    adapt = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);

                    scrollX = 0;

                    scrollY = 0;

                            main.invalidate();

                    Toast.makeText(this, "(" + dm.widthPixels + ", " + dm.heightPixels + ")", Toast.LENGTH_SHORT).show();

                   }

                   // 下面这句必须存在,否则会出现异常

                   super.onConfigurationChanged(newConfig);

         }

 

         public boolean onTouchEvent(MotionEvent me)

         {

                   return gestureDetector.onTouchEvent(me);

         }

 

         public boolean onDown(MotionEvent me)

         {

                   return true;

         }

 

         public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY)

         {

                   return true;

         }

 

         public void onLongPress(MotionEvent me)

         {

 

         }

 

         public boolean onScroll(MotionEvent me1, MotionEvent me2, float distanceX, float distanceY)

         {

                   // distanceX distanceY ,分别为叫上次位置的滚动量,可以为正,也可能为负

                  main.handleScroll(distanceX, distanceY);

                   return true;

         }

 

         public void onShowPress(MotionEvent me)

         {

 

         }

 

         public boolean onSingleTapUp(MotionEvent me)

         {

                   return true;

         }

        

    class PictureView extends View

    {

                   public PictureView(Context ctx)

                   {

                            super(ctx);

                   }

 

                   // 调用 invalidate 方法时,会触发 onDraw 这个方法

                   protected void onDraw(Canvas canvas)

                   {

                            canvas.drawBitmap(adapt, 0, 0, paint);

                   }

                  

                   public void handleScroll(float distanceX, float distanceY)

                   {

                            // 修正每次滚动后的 scrollX scrollY 的值

                            scrollX += distanceX;

                            scrollY += distanceY;

 

                            if(scrollX < 0)

                            {

                                     scrollX = 0;

                            }

                           

                            if(scrollX > (X - dm.widthPixels))

                            {

                                     scrollX = X - dm.widthPixels;

                            }

                           

                            if(scrollY < 0)

                            {

                                     scrollY = 0;

                            }

                           

                            if(scrollY > (Y - dm.heightPixels))

                            {

                                     scrollY = Y - dm.heightPixels;

                            }

                            // 重新获取 adapt

                            adapt = Bitmap.createBitmap(bmp, scrollX, scrollY, dm.widthPixels, dm.heightPixels);

                            // 重画

                            invalidate();

                   }

    }

}

 

3.     修改 AndroidManifest.xml ,使之如下:

<? xml version = "1.0" encoding = "utf-8" ?>

< manifest xmlns:android = "http://schemas.android.com/apk/res/android"

      package = "com.pat.gui"

      android:versionCode = "1"

      android:versionName = "1.0" >

    < application android:icon = "@drawable/icon" android:label = "@string/app_name" >

        < activity android:name = ".ScrollPicture"

                  android:label = "@string/app_name"

                  android:screenOrientation = "sensor"

                  android:configChanges = "orientation" >

            < intent-filter >

                < action android:name = "android.intent.action.MAIN" />

                < category android:name = "android.intent.category.LAUNCHER" />

            </ intent-filter >

        </ activity >

 

    </ application >

    < uses-sdk android:minSdkVersion = "7" />

    < uses-permission android:name = "android.permission.CHANGE_CONFIGURATION" />

</ manifest >

注意 AndroidManifest.xml 文件中, 3 行粗体字。其中的 android:screenOrientation="sensor" 表示,由手机的重力感应器来决定屏幕是以 landscape 或者 portrait 方式显示。  

运行结果:


结果表明可以同时在水平和垂直方向移动图片。

相关内容