11c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu/* 21c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * Copyright (C) 2013 The Android Open Source Project 31c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * 41c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * Licensed under the Apache License, Version 2.0 (the "License"); 51c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * you may not use this file except in compliance with the License. 61c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * You may obtain a copy of the License at 71c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * 81c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * http://www.apache.org/licenses/LICENSE-2.0 91c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * 101c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * Unless required by applicable law or agreed to in writing, software 111c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * distributed under the License is distributed on an "AS IS" BASIS, 121c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * See the License for the specific language governing permissions and 141c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu * limitations under the License. 151c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu */ 161c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 171c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liupackage com.android.camera.ui; 181c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 199eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liuimport android.app.Activity; 201c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liuimport android.content.Context; 219eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liuimport android.content.Intent; 229eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liuimport android.provider.MediaStore; 231c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liuimport android.util.AttributeSet; 241c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liuimport android.view.MotionEvent; 25f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liuimport android.view.View; 269eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liuimport android.view.ViewConfiguration; 271c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liuimport android.widget.FrameLayout; 281c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 2928a2950939614a0c1c83787960ce1a218fb69a5eDoris Liuimport com.android.camera.app.CameraAppUI; 305596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 31344320c90639f823451ddac42e8f39b74727787cDoris Liuimport com.android.camera.util.CameraUtil; 329eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liuimport com.android.camera.widget.FilmstripLayout; 339eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liuimport com.android.camera2.R; 34772951602f9cfccd097283e3b78d188838c82138Erin Dahlgren 35f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liupublic class MainActivityLayout extends FrameLayout { 361c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 375596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private final Log.Tag TAG = new Log.Tag("MainActivityLayout"); 389eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu // Only check for intercepting touch events within first 500ms 399eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private static final int SWIPE_TIME_OUT = 500; 409eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu 419eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private ModeListView mModeList; 429eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private FilmstripLayout mFilmstripLayout; 439eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private boolean mCheckToIntercept; 449eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private MotionEvent mDown; 459eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private final int mSlop; 46f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu private boolean mRequestToInterceptTouchEvents = false; 47f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu private View mTouchReceiver = null; 489eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private final boolean mIsCaptureIntent; 4928a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu private CameraAppUI.NonDecorWindowSizeChangedListener mNonDecorWindowSizeChangedListener = null; 509eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu 519eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu // TODO: This can be removed once we come up with a new design for b/13751653. 529eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu @Deprecated 539eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu private boolean mSwipeEnabled = true; 541c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 551c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu public MainActivityLayout(Context context, AttributeSet attrs) { 561c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu super(context, attrs); 579eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 589eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu 599eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu Activity activity = (Activity) context; 609eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu Intent intent = activity.getIntent(); 619eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu String action = intent.getAction(); 629eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mIsCaptureIntent = (MediaStore.ACTION_IMAGE_CAPTURE.equals(action) 639eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(action) 649eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu || MediaStore.ACTION_VIDEO_CAPTURE.equals(action)); 659eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 669eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu 679eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu /** 689eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu * Enables or disables the swipe for modules not supporting the new swipe 699eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu * logic yet. 709eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu */ 719eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu @Deprecated 729eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu public void setSwipeEnabled(boolean enabled) { 739eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mSwipeEnabled = enabled; 748793eff1b85bda89047316fed36cdc1161a8b811Sascha Haeberling } 758793eff1b85bda89047316fed36cdc1161a8b811Sascha Haeberling 761c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu @Override 771c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu public boolean onInterceptTouchEvent(MotionEvent ev) { 781c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { 799eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mCheckToIntercept = true; 801c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu mDown = MotionEvent.obtain(ev); 81f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu mTouchReceiver = null; 82f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu mRequestToInterceptTouchEvents = false; 831c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu return false; 84f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu } else if (mRequestToInterceptTouchEvents) { 85f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu mRequestToInterceptTouchEvents = false; 86f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu onTouchEvent(mDown); 87f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu return true; 881c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { 891c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu // Do not intercept touch once child is in zoom mode 909eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mCheckToIntercept = false; 911c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu return false; 929eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } else { 939eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu // TODO: This can be removed once we come up with a new design for b/13751653. 949eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu if (!mCheckToIntercept) { 959eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu return false; 969eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 979eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu if (ev.getEventTime() - ev.getDownTime() > SWIPE_TIME_OUT) { 989eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu return false; 999eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 1009eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu if (mIsCaptureIntent || !mSwipeEnabled) { 1019eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu return false; 1029eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 1039eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu int deltaX = (int) (ev.getX() - mDown.getX()); 1049eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu int deltaY = (int) (ev.getY() - mDown.getY()); 1059eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu if (ev.getActionMasked() == MotionEvent.ACTION_MOVE 1069eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu && Math.abs(deltaX) > mSlop) { 1079eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu // Intercept right swipe 1089eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu if (deltaX >= Math.abs(deltaY) * 2) { 1099eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mTouchReceiver = mModeList; 1109eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu onTouchEvent(mDown); 1119eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu return true; 1129eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 1139eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu // Intercept left swipe 1149eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu else if (deltaX < -Math.abs(deltaY) * 2) { 1159eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mTouchReceiver = mFilmstripLayout; 1169eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu onTouchEvent(mDown); 1179eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu return true; 1189eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 1199eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 1201c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu } 1211c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu return false; 1221c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu } 1231c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 1241c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu @Override 1251c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu public boolean onTouchEvent(MotionEvent ev) { 126f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu if (mTouchReceiver != null) { 127f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu mTouchReceiver.setVisibility(VISIBLE); 128166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong return mTouchReceiver.dispatchTouchEvent(ev); 129f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu } 130f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu return false; 1311c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu } 1321c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu 1339eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu @Override 1349eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu public void onFinishInflate() { 1359eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mModeList = (ModeListView) findViewById(R.id.mode_list_layout); 1369eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu mFilmstripLayout = (FilmstripLayout) findViewById(R.id.filmstrip_layout); 1379eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu } 1389eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu 139f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu public void redirectTouchEventsTo(View touchReceiver) { 140f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu if (touchReceiver == null) { 141f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu Log.e(TAG, "Cannot redirect touch to a null receiver."); 142f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu return; 143f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu } 144f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu mTouchReceiver = touchReceiver; 145f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu mRequestToInterceptTouchEvents = true; 146f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu } 14728a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu 14828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu @Override 14928a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 15028a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu if (mNonDecorWindowSizeChangedListener != null) { 15128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu mNonDecorWindowSizeChangedListener.onNonDecorWindowSizeChanged( 152344320c90639f823451ddac42e8f39b74727787cDoris Liu MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec), 1538be316c7a8caf962cf3fcf5e49d332fb2718319fPaul Rohde CameraUtil.getDisplayRotation()); 15428a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu } 15528a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu super.onMeasure(widthMeasureSpec, heightMeasureSpec); 15628a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu } 15728a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu 15828a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu /** 15928a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu * Sets a listener that gets notified when the layout size is changed. This 16028a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu * size is the size of main activity layout. It is also the size of the window 16128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu * excluding the system decor such as status bar and nav bar. 16228a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu */ 16328a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu public void setNonDecorWindowSizeChangedListener( 16428a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu CameraAppUI.NonDecorWindowSizeChangedListener listener) { 16528a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu mNonDecorWindowSizeChangedListener = listener; 16628a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu if (mNonDecorWindowSizeChangedListener != null) { 16728a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu mNonDecorWindowSizeChangedListener.onNonDecorWindowSizeChanged( 168344320c90639f823451ddac42e8f39b74727787cDoris Liu getMeasuredWidth(), getMeasuredHeight(), 1698be316c7a8caf962cf3fcf5e49d332fb2718319fPaul Rohde CameraUtil.getDisplayRotation()); 17028a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu } 17128a2950939614a0c1c83787960ce1a218fb69a5eDoris Liu } 1729eb517f4c4bcf00fbe435a56f89d3abcaaa4d881Doris Liu}