iT邦幫忙

0

Android studio 如何客製化手勢判定

  • 分享至 

  • xImage
  •  

記錄每天學習到的內容-參考書第29章:Neil Smyth - Android Studio Electric Eel Essentials - Java Edition_ Developing Android Apps Using Android Studio 2022.1.1 and Java-Payload Media
如有錯誤歡迎指證

The GestureOverlayView Class

Android SDK 提供了GestureOverlayView 的class ,這是一個透明的view用於提供手勢偵測。

偵測手勢

  • 註冊一個GesturePerformedListener 事件監聽器在GestureOverlayView class的實例上
  • 在外圍的class implements OnGesturePerformedListener interface 以及對應的onGesturePerfomed callback函數
    如果一個手勢監聽器偵測到,onGesturePerformed callback function會被Android runtime system 啟用。

建立自定義的手勢

  • 開發工具Gesture Builder Tool在模擬器google play下載,以建立自定義的手勢,
  • 模擬器檔案管理在View -> Tool Windows -> Device File Explorer
  • 手勢檔(gesture.txt)會在以下模擬器中的位置。
/storage/emulated/0/Android/data/migueldp.runeforge/files/gestures.txt
  • 將檔案複製到專案中的res/raw裡

使用者介面

在activity中建立GestureOverlayView 的layer
此範例中id設為gOverlay

<android.gesture.GestureOverlayView
android:id="@+id/gOverlay"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

讀取手勢檔案

.
.
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;

public class MainActivity extends AppCompatActivity
        implements OnGesturePerformedListener {
        
    private ActivityMainBinding binding;
    private GestureLibrary gLibrary;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        gestureSetup();
    }
    
    private void gestureSetup() {
        gLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
        if (!gLibrary.load()) {
            finish();
        }
    }
..
}

除了之前講到的 GestureOverlayView 以及OnGesturePerformedListener ,此程式建立了 GestureLibrary的實例gLibrary,用於載入位於res/raw裡的手勢檔案,並且implement OnGesturePerformedListener interface,因此還會再往後補寫onGesturePerformed callback function(因為是interface中的abstrack function)

註冊OnGesturePerformedListener

為了讓activity能收到使用者的手勢,需要註冊一個OnGesturePerformedListener到gLayout view 上,需增加以下程式碼到gestureSetup()裡面

GestureOverlayView gOverlay = findViewById(R.id.gOverlay);
gOverlay.addOnGesturePerformedListener(this);

補寫onGesturePerformed method

.
import android.gesture.Prediction;
import android.widget.Toast;
import android.gesture.Gesture;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements
OnGesturePerformedListener {
private GestureLibrary gLibrary;
.
.
    public void onGesturePerformed(GestureOverlayView overlay, Gesture
    gesture) {
        ArrayList<Prediction> predictions = gLibrary.recognize(gesture);
        if (predictions.size() > 0 && predictions.get(0).score > 1.0)
        {
            String action = predictions.get(0).name;
            Toast.makeText(this, action, Toast.LENGTH_SHORT).show();
        }
    }
.
.
.
}

多增加上述函式庫4個函式庫,當手勢再gOverlay view 上被偵測到onGesturePerformed method被呼叫,同時傳入一個GestureOverlayView 的物件以及被偵測到的手勢(type: Gesture),將偵測到的手勢參數丟進gLibrary實例中的recognize(),目的是為了比較真測到的手勢以及被從res/raw中讀取到的手勢檔案,recognize()會回傳一個ArrayList的物件包含一串Prediction物件,從最好排到最壞的預測,Prediction物件中包含了預測手勢的名稱以及預測分數。
在上述的程式碼中判斷手勢是否評分大於1 ,如果滿足條件,顯示一個Toast message(顯示彈跳通知)展示手勢的名稱

讓手勢變透明

在activity xml檔中的android.gesture.GestureOverlayView增加最下面兩行

<android.gesture.GestureOverlayView
android:id="@+id/gOverlay"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:gestureColor="#00000000"
android:uncertainGestureColor="#00000000" />

偵測pinch手勢(zoom in/ zoom out)

  • implements SimpleOnScaleGestureListener interface 需要複寫
    onScale(), onScaleBegin() and onScaleEnd() callback methods
  • 創造一個ScaleGestureDetector class的實例
  • 複寫onTouchEvent() callback method 在最外圍的activity
..
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    ScaleGestureDetector scaleGestureDetector;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
        scaleGestureDetector = new ScaleGestureDetector(this,
                                    new MyOnScaleGestureListener());
                                    
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        scaleGestureDetector.onTouchEvent(event);
        return true;
    }
    
    public class MyOnScaleGestureListener extends
    SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float scaleFactor = detector.getScaleFactor();
            if (scaleFactor > 1) {
                binding.myTextView.setText("Zooming Out");
            } 
            else {
                binding.myTextView.setText("Zooming In");
            }
            return true;
        }
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }
        
        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
        }
   }
.
.
.
}

參考書:Neil Smyth - Android Studio Electric Eel Essentials - Java Edition_ Developing Android Apps Using Android Studio 2022.1.1 and Java-Payload Media


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言