Fork and kotlin port.

This commit is contained in:
aminecmi
2023-01-14 22:50:03 +01:00
commit c2907459cd
75 changed files with 3480 additions and 0 deletions

View File

@ -0,0 +1,24 @@
package bou.amine.apps.photoviewproject
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("bou.amine.apps.photoviewproject", appContext.packageName)
}
}

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".LauncherActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SimpleSampleActivity" />
<activity android:name=".ViewPagerActivity" />
<activity android:name=".RotationSampleActivity" />
<activity android:name=".PicassoSampleActivity" />
<activity android:name=".ActivityTransitionActivity" />
<activity android:name=".ActivityTransitionToActivity" />
<activity android:name=".ImmersiveActivity" />
</application>
</manifest>

View File

@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package bou.amine.apps.photoviewproject;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityOptionsCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class ActivityTransitionActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition);
RecyclerView list = findViewById(R.id.list);
list.setLayoutManager(new GridLayoutManager(this, 2));
ImageAdapter imageAdapter = new ImageAdapter(new ImageAdapter.Listener() {
@Override
public void onImageClicked(View view) {
transition(view);
}
});
list.setAdapter(imageAdapter);
}
private void transition(View view) {
if (Build.VERSION.SDK_INT < 21) {
Toast.makeText(ActivityTransitionActivity.this, "21+ only, keep out", Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent(ActivityTransitionActivity.this, ActivityTransitionToActivity.class);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(ActivityTransitionActivity.this, view, getString(R.string.transition_test));
startActivity(intent, options.toBundle());
}
}
}

View File

@ -0,0 +1,18 @@
package bou.amine.apps.photoviewproject;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
/**
* Activity that gets transitioned to
*/
public class ActivityTransitionToActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition_to);
}
}

View File

@ -0,0 +1,34 @@
package bou.amine.apps.photoviewproject;
import android.content.Context;
import android.view.MotionEvent;
import androidx.drawerlayout.widget.DrawerLayout;
/**
* Hacky fix for Issue #4 and
* http://code.google.com/p/android/issues/detail?id=18990
* <p/>
* ScaleGestureDetector seems to mess up the touch events, which means that
* ViewGroups which make use of onInterceptTouchEvent throw a lot of
* IllegalArgumentException: pointerIndex out of range.
* <p/>
* There's not much I can do in my code for now, but we can mask the result by
* just catching the problem and ignoring it.
*/
public class HackyDrawerLayout extends DrawerLayout {
public HackyDrawerLayout(Context context) {
super(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
}
}

View File

@ -0,0 +1,40 @@
package bou.amine.apps.photoviewproject;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
/**
* Hacky fix for Issue #4 and
* http://code.google.com/p/android/issues/detail?id=18990
* <p/>
* ScaleGestureDetector seems to mess up the touch events, which means that
* ViewGroups which make use of onInterceptTouchEvent throw a lot of
* IllegalArgumentException: pointerIndex out of range.
* <p/>
* There's not much I can do in my code for now, but we can mask the result by
* just catching the problem and ignoring it.
*
* @author Chris Banes
*/
public class HackyViewPager extends ViewPager {
public HackyViewPager(Context context) {
super(context);
}
public HackyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
return false;
}
}
}

View File

@ -0,0 +1,44 @@
package bou.amine.apps.photoviewproject;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
/**
* Image adapter
*/
public class ImageAdapter extends RecyclerView.Adapter<ImageViewHolder> {
Listener mListener;
public ImageAdapter(Listener listener) {
mListener = listener;
}
@Override
public ImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ImageViewHolder holder = ImageViewHolder.inflate(parent);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onImageClicked(view);
}
});
return holder;
}
@Override
public void onBindViewHolder(ImageViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 20;
}
public interface Listener {
void onImageClicked(View view);
}
}

View File

@ -0,0 +1,30 @@
package bou.amine.apps.photoviewproject;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
/**
* Image in recyclerview
*/
public class ImageViewHolder extends RecyclerView.ViewHolder {
public static ImageViewHolder inflate(ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_image, parent, false);
return new ImageViewHolder(view);
}
public TextView mTextTitle;
public ImageViewHolder(View view) {
super(view);
mTextTitle = view.findViewById(R.id.title);
}
private void bind(String title) {
mTextTitle.setText(title);
}
}

View File

@ -0,0 +1,88 @@
package bou.amine.apps.photoviewproject;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import bou.amine.apps.photoview.OnPhotoTapListener;
import bou.amine.apps.photoview.PhotoView;
import com.squareup.picasso.Picasso;
import static android.R.attr.uiOptions;
/**
* Shows immersive image viewer
*/
public class ImmersiveActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_immersive);
PhotoView photoView = findViewById(R.id.photo_view);
Picasso.with(this)
.load("http://pbs.twimg.com/media/Bist9mvIYAAeAyQ.jpg")
.into(photoView);
photoView.setOnPhotoTapListener(new OnPhotoTapListener() {
@Override
public void onPhotoTap(ImageView view, float x, float y) {
//fullScreen();
}
});
fullScreen();
}
public void fullScreen() {
// BEGIN_INCLUDE (get_current_ui_flags)
// The UI options currently enabled are represented by a bitfield.
// getSystemUiVisibility() gives us that bitfield.
int uiOptions = getWindow().getDecorView().getSystemUiVisibility();
int newUiOptions = uiOptions;
// END_INCLUDE (get_current_ui_flags)
// BEGIN_INCLUDE (toggle_ui_flags)
boolean isImmersiveModeEnabled = isImmersiveModeEnabled();
if (isImmersiveModeEnabled) {
Log.i("TEST", "Turning immersive mode mode off. ");
} else {
Log.i("TEST", "Turning immersive mode mode on.");
}
// Navigation bar hiding: Backwards compatible to ICS.
if (Build.VERSION.SDK_INT >= 14) {
newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
// Status bar hiding: Backwards compatible to Jellybean
if (Build.VERSION.SDK_INT >= 16) {
newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN;
}
// Immersive mode: Backward compatible to KitKat.
// Note that this flag doesn't do anything by itself, it only augments the behavior
// of HIDE_NAVIGATION and FLAG_FULLSCREEN. For the purposes of this sample
// all three flags are being toggled together.
// Note that there are two immersive mode UI flags, one of which is referred to as "sticky".
// Sticky immersive mode differs in that it makes the navigation and status bars
// semi-transparent, and the UI flag does not get cleared when the user interacts with
// the screen.
if (Build.VERSION.SDK_INT >= 18) {
newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
//END_INCLUDE (set_ui_flags)
}
private boolean isImmersiveModeEnabled() {
return ((uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) == uiOptions);
}
}

View File

@ -0,0 +1,127 @@
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package bou.amine.apps.photoviewproject;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class LauncherActivity extends AppCompatActivity {
public static final String[] options = {
"Simple Sample",
"ViewPager Sample",
"Rotation Sample",
"Picasso Sample",
"Activity Transition Sample",
"Immersive Sample"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launcher);
Toolbar toolbar = findViewById(R.id.toolbar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setTitle(R.string.app_name);
}
RecyclerView recyclerView = findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new ItemAdapter());
}
private static class ItemAdapter extends RecyclerView.Adapter<ItemViewHolder> {
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ItemViewHolder holder = ItemViewHolder.newInstance(parent);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Class clazz;
switch (holder.getAdapterPosition()) {
default:
case 0:
clazz = SimpleSampleActivity.class;
break;
case 1:
clazz = ViewPagerActivity.class;
break;
case 2:
clazz = RotationSampleActivity.class;
break;
case 3:
clazz = PicassoSampleActivity.class;
break;
case 4:
clazz = ActivityTransitionActivity.class;
break;
case 5:
clazz = ImmersiveActivity.class;
}
Context context = holder.itemView.getContext();
context.startActivity(new Intent(context, clazz));
}
});
return holder;
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
holder.bind(options[position]);
}
@Override
public int getItemCount() {
return options.length;
}
}
private static class ItemViewHolder extends RecyclerView.ViewHolder {
public static ItemViewHolder newInstance(ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_sample, parent, false);
return new ItemViewHolder(view);
}
public TextView mTextTitle;
public ItemViewHolder(View view) {
super(view);
mTextTitle = view.findViewById(R.id.title);
}
private void bind(String title) {
mTextTitle.setText(title);
}
}
}

View File

@ -0,0 +1,23 @@
package bou.amine.apps.photoviewproject;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import bou.amine.apps.photoview.PhotoView;
import com.squareup.picasso.Picasso;
public class PicassoSampleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
final PhotoView photoView = findViewById(R.id.iv_photo);
Picasso.with(this)
.load("http://pbs.twimg.com/media/Bist9mvIYAAeAyQ.jpg")
.into(photoView);
}
}

View File

@ -0,0 +1,102 @@
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package bou.amine.apps.photoviewproject;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import bou.amine.apps.photoview.PhotoView;
public class RotationSampleActivity extends AppCompatActivity {
private PhotoView photo;
private final Handler handler = new Handler();
private boolean rotating = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rotation_sample);
Toolbar toolbar = findViewById(R.id.toolbar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.inflateMenu(R.menu.rotation);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_rotate_10_right:
photo.setRotationBy(10);
return true;
case R.id.action_rotate_10_left:
photo.setRotationBy(-10);
return true;
case R.id.action_toggle_automatic_rotation:
toggleRotation();
return true;
case R.id.action_reset_to_0:
photo.setRotationTo(0);
return true;
case R.id.action_reset_to_90:
photo.setRotationTo(90);
return true;
case R.id.action_reset_to_180:
photo.setRotationTo(180);
return true;
case R.id.action_reset_to_270:
photo.setRotationTo(270);
return true;
}
return false;
}
});
}
photo = findViewById(R.id.iv_photo);
photo.setImageResource(R.drawable.wallpaper);
}
@Override
protected void onPause() {
super.onPause();
handler.removeCallbacksAndMessages(null);
}
private void toggleRotation() {
if (rotating) {
handler.removeCallbacksAndMessages(null);
} else {
rotateLoop();
}
rotating = !rotating;
}
private void rotateLoop() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
photo.setRotationBy(1);
rotateLoop();
}
}, 15);
}
}

View File

@ -0,0 +1,193 @@
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package bou.amine.apps.photoviewproject;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import bou.amine.apps.photoview.OnMatrixChangedListener;
import bou.amine.apps.photoview.OnPhotoTapListener;
import bou.amine.apps.photoview.OnSingleFlingListener;
import bou.amine.apps.photoview.PhotoView;
import java.util.Random;
public class SimpleSampleActivity extends AppCompatActivity {
static final String PHOTO_TAP_TOAST_STRING = "Photo Tap! X: %.2f %% Y:%.2f %% ID: %d";
static final String SCALE_TOAST_STRING = "Scaled to: %.2ff";
static final String FLING_LOG_STRING = "Fling velocityX: %.2f, velocityY: %.2f";
private PhotoView mPhotoView;
private TextView mCurrMatrixTv;
private Toast mCurrentToast;
private Matrix mCurrentDisplayMatrix = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple_sample);
Toolbar toolbar = findViewById(R.id.toolbar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setTitle("Simple Sample");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.inflateMenu(R.menu.main_menu);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_zoom_toggle:
mPhotoView.setZoomable(!mPhotoView.isZoomEnabled());
item.setTitle(mPhotoView.isZoomEnabled() ? R.string.menu_zoom_disable : R.string.menu_zoom_enable);
return true;
case R.id.menu_scale_fit_center:
mPhotoView.setScaleType(ImageView.ScaleType.CENTER);
return true;
case R.id.menu_scale_fit_start:
mPhotoView.setScaleType(ImageView.ScaleType.FIT_START);
return true;
case R.id.menu_scale_fit_end:
mPhotoView.setScaleType(ImageView.ScaleType.FIT_END);
return true;
case R.id.menu_scale_fit_xy:
mPhotoView.setScaleType(ImageView.ScaleType.FIT_XY);
return true;
case R.id.menu_scale_scale_center:
mPhotoView.setScaleType(ImageView.ScaleType.CENTER);
return true;
case R.id.menu_scale_scale_center_crop:
mPhotoView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return true;
case R.id.menu_scale_scale_center_inside:
mPhotoView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
return true;
case R.id.menu_scale_random_animate:
case R.id.menu_scale_random:
Random r = new Random();
float minScale = mPhotoView.getMinimumScale();
float maxScale = mPhotoView.getMaximumScale();
float randomScale = minScale + (r.nextFloat() * (maxScale - minScale));
mPhotoView.setScale(randomScale, item.getItemId() == R.id.menu_scale_random_animate);
showToast(String.format(SCALE_TOAST_STRING, randomScale));
return true;
case R.id.menu_matrix_restore:
if (mCurrentDisplayMatrix == null)
showToast("You need to capture display matrix first");
else
mPhotoView.setDisplayMatrix(mCurrentDisplayMatrix);
return true;
case R.id.menu_matrix_capture:
mCurrentDisplayMatrix = new Matrix();
mPhotoView.getDisplayMatrix(mCurrentDisplayMatrix);
return true;
}
return false;
}
});
}
mPhotoView = findViewById(R.id.iv_photo);
mCurrMatrixTv = findViewById(R.id.tv_current_matrix);
Drawable bitmap = ContextCompat.getDrawable(this, R.drawable.wallpaper);
mPhotoView.setImageDrawable(bitmap);
// Lets attach some listeners, not required though!
mPhotoView.setOnMatrixChangeListener(new MatrixChangeListener());
mPhotoView.setOnPhotoTapListener(new PhotoTapListener());
mPhotoView.setOnSingleFlingListener(new SingleFlingListener());
}
private class PhotoTapListener implements OnPhotoTapListener {
@Override
public void onPhotoTap(ImageView view, float x, float y) {
float xPercentage = x * 100f;
float yPercentage = y * 100f;
showToast(String.format(PHOTO_TAP_TOAST_STRING, xPercentage, yPercentage, view == null ? 0 : view.getId()));
}
}
private void showToast(CharSequence text) {
if (mCurrentToast != null) {
mCurrentToast.cancel();
}
mCurrentToast = Toast.makeText(SimpleSampleActivity.this, text, Toast.LENGTH_SHORT);
mCurrentToast.show();
}
private class MatrixChangeListener implements OnMatrixChangedListener {
@Override
public void onMatrixChanged(RectF rect) {
mCurrMatrixTv.setText(rect.toString());
}
}
private class SingleFlingListener implements OnSingleFlingListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d("PhotoView", String.format(FLING_LOG_STRING, velocityX, velocityY));
return true;
}
}
}

View File

@ -0,0 +1,73 @@
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package bou.amine.apps.photoviewproject;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import bou.amine.apps.photoview.PhotoView;
public class ViewPagerActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new SamplePagerAdapter());
}
static class SamplePagerAdapter extends PagerAdapter {
private static final int[] sDrawables = { R.drawable.wallpaper, R.drawable.wallpaper, R.drawable.wallpaper,
R.drawable.wallpaper, R.drawable.wallpaper, R.drawable.wallpaper };
@Override
public int getCount() {
return sDrawables.length;
}
@Override
public View instantiateItem(ViewGroup container, int position) {
PhotoView photoView = new PhotoView(container.getContext());
photoView.setImageResource(sDrawables[position]);
// Now just add PhotoView to ViewPager and return it
container.addView(photoView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
return photoView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<bou.amine.apps.photoview.PhotoView
android:id="@+id/photo_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -0,0 +1,25 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
</com.google.android.material.appbar.AppBarLayout>
<bou.amine.apps.photoview.PhotoView
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/wallpaper"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,5 @@
<bou.amine.apps.photoview.PhotoView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@ -0,0 +1,33 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
</com.google.android.material.appbar.AppBarLayout>
<bou.amine.apps.photoview.PhotoView
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/tv_current_matrix"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="#60000000"
android:gravity="center"
android:textColor="@android:color/white"/>
</FrameLayout>

View File

@ -0,0 +1,5 @@
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@ -0,0 +1,7 @@
<bou.amine.apps.photoview.PhotoView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:src="@drawable/wallpaper"
android:transitionName="@string/transition_test" />

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<bou.amine.apps.photoviewproject.HackyViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/wallpaper"/>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeight"
android:background="?attr/selectableItemBackground">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/white"/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="20sp"
android:layout_margin="16dp"
tools:text="Hello there"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:background="@android:color/white"/>
</FrameLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="UnusedAttribute">
<item
android:id="@+id/menu_zoom_toggle"
android:title="@string/menu_zoom_disable"/>
<item
android:id="@+id/menu_scale_fit_center"
android:title="@string/menu_scale_fit_center"/>
<item
android:id="@+id/menu_scale_fit_start"
android:title="@string/menu_scale_fit_start"/>
<item
android:id="@+id/menu_scale_fit_end"
android:title="@string/menu_scale_fit_end"/>
<item
android:id="@+id/menu_scale_fit_xy"
android:title="@string/menu_scale_fit_xy"/>
<item
android:id="@+id/menu_scale_scale_center"
android:title="@string/menu_scale_center"/>
<item
android:id="@+id/menu_scale_scale_center_crop"
android:title="@string/menu_scale_center_crop"/>
<item
android:id="@+id/menu_scale_scale_center_inside"
android:title="@string/menu_scale_center_inside"/>
<item
android:id="@+id/menu_scale_random_animate"
android:title="@string/menu_zoom_random_animate"/>
<item
android:id="@+id/menu_scale_random"
android:title="@string/menu_zoom_random"/>
<item
android:id="@+id/menu_matrix_restore"
android:title="@string/menu_matrix_restore"/>
<item
android:id="@+id/menu_matrix_capture"
android:title="@string/menu_matrix_capture"/>
</menu>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_rotate_10_right"
android:title="Rotate 10° Right"/>
<item
android:id="@+id/action_rotate_10_left"
android:title="Rotate 10° Left"/>
<item
android:id="@+id/action_toggle_automatic_rotation"
android:title="Toggle Automatic Rotation"/>
<item
android:id="@+id/action_reset_to_0"
android:title="Reset to 0"/>
<item
android:id="@+id/action_reset_to_90"
android:title="Reset to 90"/>
<item
android:id="@+id/action_reset_to_180"
android:title="Reset to 180"/>
<item
android:id="@+id/action_reset_to_270"
android:title="Reset to 270"/>
</menu>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="green">#AACE30</color>
<color name="blue">#142D3E</color>
<color name="blue_dark">#001425</color>
</resources>

View File

@ -0,0 +1,19 @@
<resources>
<string name="app_name">PhotoView Sample</string>
<string name="menu_zoom_enable">Enable Zoom</string>
<string name="menu_zoom_disable">Disable Zoom</string>
<string name="menu_scale_fit_center">Change to FIT_CENTER</string>
<string name="menu_scale_fit_start">Change to FIT_START</string>
<string name="menu_scale_fit_end">Change to FIT_END</string>
<string name="menu_scale_fit_xy">Change to FIT_XY</string>
<string name="menu_scale_center">Change to CENTER</string>
<string name="menu_scale_center_inside">Change to CENTER_INSIDE</string>
<string name="menu_scale_center_crop">Change to CENTER_CROP</string>
<string name="menu_zoom_random_animate">Animate scale to random value</string>
<string name="menu_zoom_random">Set scale to random value</string>
<string name="menu_matrix_restore">Restore Display Matrix</string>
<string name="menu_matrix_capture">Capture Display Matrix</string>
<string name="extract_visible_bitmap">Extract visible bitmap</string>
</resources>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/blue</item>
<item name="colorPrimaryDark">@color/blue_dark</item>
<item name="colorAccent">@color/green</item>
<!-- enable window content transitions -->
<item name="android:windowActivityTransitions" tools:targetApi="lollipop">true</item>
</style>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="transition_test">test</string>
</resources>

View File

@ -0,0 +1,17 @@
package bou.amine.apps.photoviewproject
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}