AndroidGUI23:水平方向和垂直方向同時滾動

在上一篇文章中,我們講到了使用 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 方式顯示。

 

運行結果:


結果表明可以同時在水平和垂直方向移動圖片。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章