Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.ui;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.provider.MediaStore;
     23 import android.util.AttributeSet;
     24 import android.view.MotionEvent;
     25 import android.view.View;
     26 import android.view.ViewConfiguration;
     27 import android.widget.FrameLayout;
     28 
     29 import com.android.camera.app.CameraAppUI;
     30 import com.android.camera.debug.Log;
     31 import com.android.camera.util.CameraUtil;
     32 import com.android.camera.widget.FilmstripLayout;
     33 import com.android.camera2.R;
     34 
     35 public class MainActivityLayout extends FrameLayout {
     36 
     37     private final Log.Tag TAG = new Log.Tag("MainActivityLayout");
     38     // Only check for intercepting touch events within first 500ms
     39     private static final int SWIPE_TIME_OUT = 500;
     40 
     41     private ModeListView mModeList;
     42     private FilmstripLayout mFilmstripLayout;
     43     private boolean mCheckToIntercept;
     44     private MotionEvent mDown;
     45     private final int mSlop;
     46     private boolean mRequestToInterceptTouchEvents = false;
     47     private View mTouchReceiver = null;
     48     private final boolean mIsCaptureIntent;
     49     private CameraAppUI.NonDecorWindowSizeChangedListener mNonDecorWindowSizeChangedListener = null;
     50 
     51     // TODO: This can be removed once we come up with a new design for b/13751653.
     52     @Deprecated
     53     private boolean mSwipeEnabled = true;
     54 
     55     public MainActivityLayout(Context context, AttributeSet attrs) {
     56         super(context, attrs);
     57         mSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     58 
     59         Activity activity = (Activity) context;
     60         Intent intent = activity.getIntent();
     61         String action = intent.getAction();
     62         mIsCaptureIntent = (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
     63                 || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(action)
     64                 || MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
     65     }
     66 
     67     /**
     68      * Enables or disables the swipe for modules not supporting the new swipe
     69      * logic yet.
     70      */
     71     @Deprecated
     72     public void setSwipeEnabled(boolean enabled) {
     73         mSwipeEnabled = enabled;
     74     }
     75 
     76     @Override
     77     public boolean onInterceptTouchEvent(MotionEvent ev) {
     78         if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
     79             mCheckToIntercept = true;
     80             mDown = MotionEvent.obtain(ev);
     81             mTouchReceiver = null;
     82             mRequestToInterceptTouchEvents = false;
     83             return false;
     84         } else if (mRequestToInterceptTouchEvents) {
     85             mRequestToInterceptTouchEvents = false;
     86             onTouchEvent(mDown);
     87             return true;
     88         } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
     89             // Do not intercept touch once child is in zoom mode
     90             mCheckToIntercept = false;
     91             return false;
     92         } else {
     93             // TODO: This can be removed once we come up with a new design for b/13751653.
     94             if (!mCheckToIntercept) {
     95                 return false;
     96             }
     97             if (ev.getEventTime() - ev.getDownTime() > SWIPE_TIME_OUT) {
     98                 return false;
     99             }
    100             if (mIsCaptureIntent || !mSwipeEnabled) {
    101                 return false;
    102             }
    103             int deltaX = (int) (ev.getX() - mDown.getX());
    104             int deltaY = (int) (ev.getY() - mDown.getY());
    105             if (ev.getActionMasked() == MotionEvent.ACTION_MOVE
    106                     && Math.abs(deltaX) > mSlop) {
    107                 // Intercept right swipe
    108                 if (deltaX >= Math.abs(deltaY) * 2) {
    109                     mTouchReceiver = mModeList;
    110                     onTouchEvent(mDown);
    111                     return true;
    112                 }
    113                 // Intercept left swipe
    114                 else if (deltaX < -Math.abs(deltaY) * 2) {
    115                     mTouchReceiver = mFilmstripLayout;
    116                     onTouchEvent(mDown);
    117                     return true;
    118                 }
    119             }
    120         }
    121         return false;
    122     }
    123 
    124     @Override
    125     public boolean onTouchEvent(MotionEvent ev) {
    126         if (mTouchReceiver != null) {
    127             mTouchReceiver.setVisibility(VISIBLE);
    128             return mTouchReceiver.dispatchTouchEvent(ev);
    129         }
    130         return false;
    131     }
    132 
    133     @Override
    134     public void onFinishInflate() {
    135         mModeList = (ModeListView) findViewById(R.id.mode_list_layout);
    136         mFilmstripLayout = (FilmstripLayout) findViewById(R.id.filmstrip_layout);
    137     }
    138 
    139     public void redirectTouchEventsTo(View touchReceiver) {
    140         if (touchReceiver == null) {
    141             Log.e(TAG, "Cannot redirect touch to a null receiver.");
    142             return;
    143         }
    144         mTouchReceiver = touchReceiver;
    145         mRequestToInterceptTouchEvents = true;
    146     }
    147 
    148     @Override
    149     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    150         if (mNonDecorWindowSizeChangedListener != null) {
    151             mNonDecorWindowSizeChangedListener.onNonDecorWindowSizeChanged(
    152                     MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec),
    153                     CameraUtil.getDisplayRotation());
    154         }
    155         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    156     }
    157 
    158     /**
    159      * Sets a listener that gets notified when the layout size is changed. This
    160      * size is the size of main activity layout. It is also the size of the window
    161      * excluding the system decor such as status bar and nav bar.
    162      */
    163     public void setNonDecorWindowSizeChangedListener(
    164             CameraAppUI.NonDecorWindowSizeChangedListener listener) {
    165         mNonDecorWindowSizeChangedListener = listener;
    166         if (mNonDecorWindowSizeChangedListener != null) {
    167             mNonDecorWindowSizeChangedListener.onNonDecorWindowSizeChanged(
    168                     getMeasuredWidth(), getMeasuredHeight(),
    169                     CameraUtil.getDisplayRotation());
    170         }
    171     }
    172 }