diff options
| author | Joe Robinson <joe@lc8n.com> | 2014-08-04 02:17:22 +0100 | 
|---|---|---|
| committer | Joe Robinson <joe@lc8n.com> | 2014-08-13 23:23:03 +0100 | 
| commit | 65c1db9dc23517ceff0e11e767585de330f70964 (patch) | |
| tree | c32f15920e56e81643bb81511a736c813740f05e /app | |
| parent | a5ca356e46df7e175c4c24a25b00c38c0954572f (diff) | |
Added partially working image viewer with paging
Diffstat (limited to 'app')
17 files changed, 728 insertions, 15 deletions
| diff --git a/app/app.iml b/app/app.iml index ad43377..1556047 100644 --- a/app/app.iml +++ b/app/app.iml @@ -59,11 +59,13 @@        <excludeFolder url="file://$MODULE_DIR$/build/intermediates" />        <excludeFolder url="file://$MODULE_DIR$/build/outputs" />      </content> -    <orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" /> +    <orderEntry type="jdk" jdkName="Android API 17 Platform" jdkType="Android SDK" />      <orderEntry type="sourceFolder" forTests="false" />      <orderEntry type="library" exported="" name="library-1.2.3" level="project" />      <orderEntry type="library" exported="" name="support-v4-19.1.0" level="project" /> +    <orderEntry type="library" exported="" name="disklrucache-2.0.2" level="project" />      <orderEntry type="library" exported="" name="otto-1.3.5" level="project" /> +    <orderEntry type="library" exported="" name="Android-BitmapCache-2.3" level="project" />    </component>  </module> diff --git a/app/build.gradle b/app/build.gradle index cf01a63..d099f61 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application'  android {      compileSdkVersion 19 -    buildToolsVersion "20.0.0" +    buildToolsVersion '20.0.0'      defaultConfig {          applicationId "uk.co.blatech.blaupload" @@ -25,5 +25,6 @@ dependencies {      compile 'com.android.support:support-v4:19.+'      compile 'com.squareup:otto:1.3.5'      compile 'com.github.chrisbanes.photoview:library:1.2.3' - +    compile 'com.jakewharton:disklrucache:2.0.2' +    compile files('libs/Android-BitmapCache-2.3.jar')  } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2700bb3..0b63b69 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,11 @@  <?xml version="1.0" encoding="utf-8"?>  <manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="uk.co.blatech.blaupload" > -    <uses-permission android:name="android.permission.INTERNET"/> + +    <uses-permission android:name="android.permission.INTERNET" /> +    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />      <application +        android:name=".BlauploadApplication"          android:allowBackup="true"          android:icon="@drawable/ic_launcher"          android:label="@string/app_name" @@ -14,11 +17,22 @@                  <action android:name="android.intent.action.MAIN" />                  <category android:name="android.intent.category.LAUNCHER" /> +                  <action android:name="android.intent.action.SEND_MULTIPLE" /> +                  <category android:name="android.intent.category.DEFAULT" /> +                  <data android:mimeType="image/*" />              </intent-filter>          </activity> +        <activity +            android:name=".ImageViewer" +            android:label="@string/title_activity_image_viewer" > +        </activity> +        <activity +            android:name=".ImagePager" +            android:label="@string/title_activity_image_pager" > +        </activity>      </application>  </manifest> diff --git a/app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java b/app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java new file mode 100644 index 0000000..518eff8 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java @@ -0,0 +1,50 @@ +package uk.co.blatech.blaupload; + +import android.app.Application; +import android.content.Context; +import android.os.Environment; +import android.util.Log; + +import java.io.File; + +import uk.co.senab.bitmapcache.BitmapLruCache; + +public class BlauploadApplication extends Application { + +    private BitmapLruCache mCache; + +    @Override +    public void onCreate() { +        super.onCreate(); + +        File cacheLocation; + +        // If we have external storage use it for the disk cache. Otherwise we use +        // the cache dir +        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { +            cacheLocation = new File( +                    Environment.getExternalStorageDirectory() + "/blaupload"); +        } else { +            cacheLocation = new File(getFilesDir() + "/blaupload"); +        } +        cacheLocation.mkdirs(); + +        BitmapLruCache.Builder builder = new BitmapLruCache.Builder(this); +        builder.setMemoryCacheEnabled(true).setMemoryCacheMaxSizeUsingHeapSize(); +        builder.setDiskCacheEnabled(true).setDiskCacheLocation(cacheLocation); + + +        mCache = builder.build(); + +        Log.d(BlauploadApplication.class.toString(), cacheLocation.toString()); +    } + +    public BitmapLruCache getBitmapCache() { +        return mCache; +    } + +    public static BlauploadApplication getApplication(Context context) { +        return (BlauploadApplication) context.getApplicationContext(); +    } + +}
\ No newline at end of file diff --git a/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java b/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java index 6e6369b..ee51908 100644 --- a/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java +++ b/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java @@ -1,6 +1,7 @@  package uk.co.blatech.blaupload;  import android.app.Activity; +import android.content.Intent;  import android.net.Uri;  import android.os.Bundle;  import android.app.Fragment; @@ -40,6 +41,8 @@ public  class HomeScreenFragment extends Fragment {      private ArrayList<ImageItem> thumbnails;      private GridViewAdapter gridAdapter;      private GridView gridView; +    private ArrayList<String> filenames; +    private JSONArray json;      /**       * Returns a new instance of this fragment       */ @@ -73,12 +76,17 @@ public  class HomeScreenFragment extends Fragment {                  new GridViewAdapter(getActivity(), R.layout.grid_item, thumbnails);          gridView.setAdapter(gridAdapter); -        //Display a message when an item is clicked -        //TODO: Make it display the full image +        filenames = new ArrayList<String>(); +        //Open the full image in a pager when clicked          gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {              public void onItemClick(AdapterView<?> parent, View v,                                      int position, long id) { -                Toast.makeText(getActivity(), "Clicked image #"+position, Toast.LENGTH_SHORT).show(); + +            Toast.makeText(getActivity(), "Clicked image #"+position, Toast.LENGTH_SHORT).show(); +            Intent mIntent = new Intent(getActivity(), ImagePager.class); +            mIntent.putExtra("json", json.toString()); +            mIntent.putExtra("position", position); +            startActivity(mIntent);              } @@ -90,7 +98,7 @@ public  class HomeScreenFragment extends Fragment {          super.onAttach(activity);          //Start loading the JSON file list in a thread as soon as we start -        new JSONLoader().execute("http://www.blaupload.co.uk/?format=json&last=9"); +        new JSONLoader().execute("http://www.blaupload.co.uk/?format=json&last=6");      } @@ -125,8 +133,7 @@ public  class HomeScreenFragment extends Fragment {      @Subscribe      public void onAsyncTaskResult(JSONLoaderResultEvent event) { -        JSONArray json = event.getResult(); -        ArrayList<String> filenames = new ArrayList<String>(); +        json = event.getResult();          if (json != null) { @@ -146,7 +153,7 @@ public  class HomeScreenFragment extends Fragment {              //Load the thumbnail for each item on a thread              int id = 0;              for (String filename : filenames) { -                new ImageLoader(getResources()).execute("http://www.lc8n.com/blathumbs/", filename, String.valueOf(id)); +                new ImageLoader(getResources()).execute("http://www.lc8n.com/blathumbs/", filename+".png", String.valueOf(id));                  id++;              } diff --git a/app/src/main/java/uk/co/blatech/blaupload/ImagePager.java b/app/src/main/java/uk/co/blatech/blaupload/ImagePager.java new file mode 100644 index 0000000..0191c52 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ImagePager.java @@ -0,0 +1,85 @@ +package uk.co.blatech.blaupload; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import com.squareup.otto.Subscribe; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import uk.co.blatech.blaupload.R; +import uk.co.blatech.blaupload.data.ImageItem; +import uk.co.blatech.blaupload.ui.ImagePagerAdapter; +import uk.co.blatech.blaupload.util.EventBus; +import uk.co.blatech.blaupload.util.ImageLoader; +import uk.co.blatech.blaupload.util.ImageLoaderResultEvent; + +public class ImagePager extends Activity { + + +    private ViewPager mViewPager; +    private JSONArray json; +    private ArrayList<String> urls; +    @Override +    protected void onCreate(Bundle savedInstanceState) { +        super.onCreate(savedInstanceState); +        mViewPager = new ViewPager(this); +        setContentView(mViewPager); +        EventBus.getInstance().register(this); +        urls = new ArrayList<String>(); +        String jsonText = getIntent().getStringExtra("json"); +        int id = getIntent().getIntExtra("position", 0); + +        try { +            json = new JSONArray(jsonText); +        } catch (JSONException e) { +            //TODO: Error handling if we got something other than JSON +            Log.e(ImagePager.class.toString(), "Failed to parse JSON"); +            e.printStackTrace(); +        } + +        for (int i = 0; i < json.length(); i++) { +            try { +                JSONObject item = json.getJSONObject(i); +                urls.add("http://www.blaupload.co.uk/"+item.getString("filename")); +            } catch (JSONException e) { +                e.printStackTrace(); +            } + +        } + +        ImagePagerAdapter adapter = new ImagePagerAdapter(ImagePager.this, urls); +        mViewPager.setAdapter(adapter); + +    } + + +    @Override +    public boolean onCreateOptionsMenu(Menu menu) { +        // Inflate the menu; this adds items to the action bar if it is present. +        getMenuInflater().inflate(R.menu.image_pager, menu); +        return true; +    } + +    @Override +    public boolean onOptionsItemSelected(MenuItem item) { +        // Handle action bar item clicks here. The action bar will +        // automatically handle clicks on the Home/Up button, so long +        // as you specify a parent activity in AndroidManifest.xml. +        int id = item.getItemId(); +        if (id == R.id.action_settings) { +            return true; +        } +        return super.onOptionsItemSelected(item); +    } + + +} diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java b/app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java new file mode 100644 index 0000000..d2a5af3 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java @@ -0,0 +1,41 @@ +package uk.co.blatech.blaupload.ui; + +import android.support.v4.view.ViewPager; +import android.view.View; + +public class DepthPageTransformer implements ViewPager.PageTransformer { +    private static final float MIN_SCALE = 0.75f; + +    public void transformPage(View view, float position) { +        int pageWidth = view.getWidth(); + +        if (position < -1) { // [-Infinity,-1) +            // This page is way off-screen to the left. +            view.setAlpha(0); + +        } else if (position <= 0) { // [-1,0] +            // Use the default slide transition when moving to the left page +            view.setAlpha(1); +            view.setTranslationX(0); +            view.setScaleX(1); +            view.setScaleY(1); + +        } else if (position <= 1) { // (0,1] +            // Fade the page out. +            view.setAlpha(1 - position); + +            // Counteract the default slide transition +            view.setTranslationX(pageWidth * -position); + +            // Scale the page down (between MIN_SCALE and 1) +            float scaleFactor = MIN_SCALE +                    + (1 - MIN_SCALE) * (1 - Math.abs(position)); +            view.setScaleX(scaleFactor); +            view.setScaleY(scaleFactor); + +        } else { // (1,+Infinity] +            // This page is way off-screen to the right. +            view.setAlpha(0); +        } +    } +}
\ No newline at end of file diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java b/app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java new file mode 100644 index 0000000..4f5dba0 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2013 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 uk.co.blatech.blaupload.ui; + +import android.content.Context; +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView.ScaleType; + +import java.util.ArrayList; + +public class ImagePagerAdapter extends PagerAdapter { + +    private final ArrayList<String> mUrls; + +    private final Context mContext; + +    public ImagePagerAdapter(Context context, ArrayList<String> urls) { +        mUrls = urls; +        mContext = context; +    } + +    @Override +    public int getCount() { +        return null != mUrls ? mUrls.size() : 0; +    } + +    @Override +    public View instantiateItem(ViewGroup container, int position) { +        NetworkCacheableImageView imageView = new NetworkCacheableImageView(mContext, null); + +        String url = mUrls.get(position); +        imageView.loadImage(url, true, null); + +        imageView.setScaleType(ScaleType.FIT_CENTER); +        container.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + +        return imageView; +    } + +    @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; +    } + +} diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java b/app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java new file mode 100644 index 0000000..043caae --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java @@ -0,0 +1,271 @@ +/******************************************************************************* + * Copyright (c) 2013 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 uk.co.blatech.blaupload.ui; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.drawable.BitmapDrawable; +import android.opengl.GLES10; +import android.os.AsyncTask; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.widget.ImageView; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.RejectedExecutionException; + +import javax.microedition.khronos.opengles.GL10; + +import uk.co.blatech.blaupload.BlauploadApplication; +import uk.co.blatech.blaupload.R; +import uk.co.blatech.blaupload.data.ImageItem; +import uk.co.senab.bitmapcache.BitmapLruCache; +import uk.co.senab.bitmapcache.CacheableBitmapDrawable; +import uk.co.senab.bitmapcache.CacheableImageView; + +/** + * Simple extension of CacheableImageView which allows downloading of Images of the Internet. + * + * This code isn't production quality, but works well enough for this sample.s + * + * @author Chris Banes + */ +public class NetworkCacheableImageView extends CacheableImageView { + +    public interface OnImageLoadedListener { +        void onImageLoaded(CacheableBitmapDrawable result); +    } + +    /** +     * This task simply fetches an Bitmap from the specified URL and wraps it in a wrapper. This +     * implementation is NOT 'best practice' or production ready code. +     */ +    private static class ImageUrlAsyncTask +            extends AsyncTask<String, Void, CacheableBitmapDrawable> { + +        private final BitmapLruCache mCache; + +        private final WeakReference<ImageView> mImageViewRef; +        private final OnImageLoadedListener mListener; + +        private final BitmapFactory.Options mDecodeOpts; + +        ImageUrlAsyncTask(ImageView imageView, BitmapLruCache cache, +                          BitmapFactory.Options decodeOpts, OnImageLoadedListener listener) { +            mCache = cache; +            mImageViewRef = new WeakReference<ImageView>(imageView); +            mListener = listener; +            mDecodeOpts = decodeOpts; +        } + +        @Override +        protected CacheableBitmapDrawable doInBackground(String... params) { + +                // Return early if the ImageView has disappeared. +                if (null == mImageViewRef.get()) { +                    return null; +                } + +                final String url = params[0]; + +                // Now we're not on the main thread we can check all caches +                CacheableBitmapDrawable result = mCache.get(url); + +                if (null == result) { +                    Log.d("ImageUrlAsyncTask", "Downloading: " + url); + +//                    // The bitmap isn't cached so download from the web +//                    HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); +//                    InputStream is = new BufferedInputStream(conn.getInputStream()); +                    Bitmap bmp = downloadImage(url); +                    // Add to cache +                    if (bmp != null) { +                        result = mCache.put(url, bmp); +                    } +                } else { +                    Log.d("ImageUrlAsyncTask", "Got from Cache: " + url); +                } + +                return result; + + +        } + +        @Override +        protected void onPostExecute(CacheableBitmapDrawable result) { +            super.onPostExecute(result); + +            ImageView iv = mImageViewRef.get(); +            if (null != iv) { +                iv.setImageDrawable(result); +            } + +            if (null != mListener) { +                mListener.onImageLoaded(result); +            } +        } + +        private Bitmap downloadImage(String url) { + + +            DefaultHttpClient client = new DefaultHttpClient(); +            HttpGet httpGet = new HttpGet(url); +            Bitmap bmp = null; + + +            int[] maxTextureSize = new int[1]; +            maxTextureSize[0] = 4096; +            GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); +            //TODO: Fix out of memory errors +            try { +                HttpResponse response = client.execute(httpGet); +                StatusLine statusLine = response.getStatusLine(); +                int statusCode = statusLine.getStatusCode(); +                String[] parts = url.split("\\."); +                String extension = parts[parts.length-1]; +                //Create the Bitmap if the file exists +                if (statusCode == 200 && isImageExtension(extension)) { +                    // If the thumbnail wasn't found, show a placeholder +                    HttpEntity entity = response.getEntity(); +                    byte[] bytes = EntityUtils.toByteArray(entity); +                    try { +                        bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); +                    } catch (Exception e) { +                        Log.e(NetworkCacheableImageView.class.toString(), "Failed decoding " + url); +                        e.printStackTrace(); +                        return bmp; +                    } +                    int bmpHeight = bmp.getHeight(); +                    int bmpWidth = bmp.getWidth(); +                    if (bmpWidth > maxTextureSize[0]) { + +                        float ratio = (float)maxTextureSize[0]/(float)bmpWidth; +                        Matrix matrix = new Matrix(); +                        bmpWidth = maxTextureSize[0]; +                        bmpHeight = Math.round(bmpHeight * ratio); +                        matrix.postScale(ratio, ratio); +                        bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); +                    } else if (bmpHeight > maxTextureSize[0]) { +                        float ratio = (float)maxTextureSize[0]/(float)bmpHeight; +                        bmpHeight = maxTextureSize[0]; +                        bmpWidth = Math.round(bmpWidth * ratio); +                        Matrix matrix = new Matrix(); +                        matrix.postScale(ratio, ratio); +                        bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); +                    } +                } else { +                    //If the file doesn't exist, use the placeholder instead +//                    bmp = BitmapFactory.decodeResource(res, R.drawable.x); +                    return bmp; +                } + +                //TODO: Error handling (Not sure how we get here) +            } catch (ClientProtocolException e) { +                e.printStackTrace(); +            } catch (IOException e) { +                e.printStackTrace(); +            } + +            return bmp; +        } + +        private boolean isImageExtension(String extension) { +            if (extension.equalsIgnoreCase("jpeg") || extension.equalsIgnoreCase("jpg") || +                    extension.equalsIgnoreCase("gif") || extension.equalsIgnoreCase("png")) { +                return true; +            } else { +                return false; +            } +        } +    } + +    private final BitmapLruCache mCache; + +    private ImageUrlAsyncTask mCurrentTask; + +    public NetworkCacheableImageView(Context context, AttributeSet attrs) { +        super(context, attrs); +        mCache = BlauploadApplication.getApplication(context).getBitmapCache(); +    } + +    /** +     * Loads the Bitmap. +     * +     * @param url      - URL of image +     * @param fullSize - Whether the image should be kept at the original size +     * @return true if the bitmap was found in the cache +     */ +    public boolean loadImage(String url, final boolean fullSize, OnImageLoadedListener listener) { +        // First check whether there's already a task running, if so cancel it +        if (null != mCurrentTask) { +            mCurrentTask.cancel(true); +        } + +        // Check to see if the memory cache already has the bitmap. We can +        // safely do +        // this on the main thread. +        BitmapDrawable wrapper = mCache.getFromMemoryCache(url); + +        if (null != wrapper) { +            // The cache has it, so just display it +            setImageDrawable(wrapper); +            return true; +        } else { +            // Memory Cache doesn't have the URL, do threaded request... +            setImageDrawable(null); + +            BitmapFactory.Options decodeOpts = null; + +            if (!fullSize) { +                //decodeOpts = new BitmapFactory.Options(); +                //decodeOpts.inSampleSize = 2; +            } + +            mCurrentTask = new ImageUrlAsyncTask(this, mCache, decodeOpts, listener); + +            try { +                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { +                    mCurrentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); +                } else { +                    mCurrentTask.execute(url); +                } +            } catch (RejectedExecutionException e) { +                // This shouldn't happen, but might. +            } + +            return false; +        } +    } + +} diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java b/app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java new file mode 100644 index 0000000..e0b837e --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java @@ -0,0 +1,75 @@ +package uk.co.blatech.blaupload.ui; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * Found at http://stackoverflow.com/questions/7814017/is-it-possible-to-disable-scrolling-on-a-viewpager. + * Convenient way to temporarily disable ViewPager navigation while interacting with ImageView. + * + * Julia Zudikova + */ + +/** + * 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 ZoomViewPager extends ViewPager { + +    private boolean isLocked; + +    public ZoomViewPager(Context context) { +        super(context); +        isLocked = false; +    } + +    public ZoomViewPager(Context context, AttributeSet attrs) { +        super(context, attrs); +        isLocked = false; +    } + +    @Override +    public boolean onInterceptTouchEvent(MotionEvent ev) { +        if (!isLocked) { +            try { +                return super.onInterceptTouchEvent(ev); +            } catch (IllegalArgumentException e) { +                e.printStackTrace(); +                return false; +            } +        } +        return false; +    } + +    @Override +    public boolean onTouchEvent(MotionEvent event) { +        if (!isLocked) { +            return super.onTouchEvent(event); +        } +        return false; +    } + +    public void toggleLock() { +        isLocked = !isLocked; +    } + +    public void setLocked(boolean isLocked) { +        this.isLocked = isLocked; +    } + +    public boolean isLocked() { +        return isLocked; +    } + +}
\ No newline at end of file diff --git a/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java b/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java index 9af9a26..4a2dbc5 100644 --- a/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java +++ b/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java @@ -1,9 +1,14 @@  package uk.co.blatech.blaupload.util; +import android.annotation.TargetApi;  import android.content.res.Resources;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.opengl.GLES10;  import android.os.AsyncTask; +import android.os.Build; +import android.util.Log;  import org.apache.http.HttpEntity;  import org.apache.http.HttpResponse; @@ -15,6 +20,8 @@ import org.apache.http.util.EntityUtils;  import java.io.IOException; +import javax.microedition.khronos.opengles.GL10; +  import uk.co.blatech.blaupload.R;  import uk.co.blatech.blaupload.data.ImageItem; @@ -50,9 +57,12 @@ public class ImageLoader extends AsyncTask<String, Void, ImageItem> {          String host = args[0];          String filename = args[1];          int id = Integer.parseInt(args[2]); +        int[] maxTextureSize = new int[1]; +        maxTextureSize[0] = 4096; +        GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);          //Add an extra .png on the end to match the current thumbnail filenames -        String url = host + filename + ".png"; +        String url = host + filename;          DefaultHttpClient client = new DefaultHttpClient();          HttpGet httpGet = new HttpGet(url); @@ -62,13 +72,40 @@ public class ImageLoader extends AsyncTask<String, Void, ImageItem> {              HttpResponse response = client.execute(httpGet);              StatusLine statusLine = response.getStatusLine();              int statusCode = statusLine.getStatusCode(); - +            String[] parts = filename.split("\\."); +            String extension = parts[parts.length-1];              //Create the Bitmap if the file exists -            if (statusCode == 200) { +            if (statusCode == 200 && isImageExtension(extension)) {                  // If the thumbnail wasn't found, show a placeholder                  HttpEntity entity = response.getEntity();                  byte[] bytes = EntityUtils.toByteArray(entity); -                bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); +                try { +                    bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); +                } catch (Exception e) { +                    Log.e(ImageLoader.class.toString(), "Failed decoding " + filename); +                    e.printStackTrace(); +                    bmp = BitmapFactory.decodeResource(res, R.drawable.x); +                    ImageItem image = new ImageItem(id, bmp, filename); +                    return image; +                } +                int bmpHeight = bmp.getHeight(); +                int bmpWidth = bmp.getWidth(); +                if (bmpWidth > maxTextureSize[0]) { + +                    float ratio = (float)maxTextureSize[0]/(float)bmpWidth; +                    Matrix matrix = new Matrix(); +                    bmpWidth = maxTextureSize[0]; +                    bmpHeight = Math.round(bmpHeight * ratio); +                    matrix.postScale(ratio, ratio); +                    bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); +                } else if (bmpHeight > maxTextureSize[0]) { +                    float ratio = (float)maxTextureSize[0]/(float)bmpHeight; +                    bmpHeight = maxTextureSize[0]; +                    bmpWidth = Math.round(bmpWidth * ratio); +                    Matrix matrix = new Matrix(); +                    matrix.postScale(ratio, ratio); +                    bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); +                }              } else {                  //If the file doesn't exist, use the placeholder instead                  bmp = BitmapFactory.decodeResource(res, R.drawable.x); @@ -92,4 +129,13 @@ public class ImageLoader extends AsyncTask<String, Void, ImageItem> {      } +    private boolean isImageExtension(String extension) { +        if (extension.equalsIgnoreCase("jpeg") || extension.equalsIgnoreCase("jpg") || +                extension.equalsIgnoreCase("gif") || extension.equalsIgnoreCase("png")) { +            return true; +        } else { +            return false; +        } +    } +  } diff --git a/app/src/main/res/layout/activity_image_pager.xml b/app/src/main/res/layout/activity_image_pager.xml new file mode 100644 index 0000000..74181fa --- /dev/null +++ b/app/src/main/res/layout/activity_image_pager.xml @@ -0,0 +1,16 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:tools="http://schemas.android.com/tools" +    android:layout_width="match_parent" +    android:layout_height="match_parent" +    android:paddingLeft="@dimen/activity_horizontal_margin" +    android:paddingRight="@dimen/activity_horizontal_margin" +    android:paddingTop="@dimen/activity_vertical_margin" +    android:paddingBottom="@dimen/activity_vertical_margin" +    tools:context="uk.co.blatech.blaupload.ImagePager"> + +    <TextView +        android:text="@string/hello_world" +        android:layout_width="wrap_content" +        android:layout_height="wrap_content" /> + +</RelativeLayout> diff --git a/app/src/main/res/layout/activity_image_viewer.xml b/app/src/main/res/layout/activity_image_viewer.xml new file mode 100644 index 0000000..9eef971 --- /dev/null +++ b/app/src/main/res/layout/activity_image_viewer.xml @@ -0,0 +1,7 @@ +<uk.co.blatech.blaupload.ui.ZoomViewPager +    xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:tools="http://schemas.android.com/tools" +    android:id="@+id/pager" +    android:layout_width="match_parent" +    android:layout_height="match_parent" +    tools:context="uk.co.blatech.blaupload.ImageViewer"/>
\ No newline at end of file diff --git a/app/src/main/res/layout/fragment_image_viewer.xml b/app/src/main/res/layout/fragment_image_viewer.xml new file mode 100644 index 0000000..d9f75fa --- /dev/null +++ b/app/src/main/res/layout/fragment_image_viewer.xml @@ -0,0 +1,13 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:tools="http://schemas.android.com/tools" +    android:layout_width="match_parent" +    android:layout_height="match_parent" +    tools:context="uk.co.blatech.blaupload.ImageViewer$PlaceholderFragment"> + +    <ImageView +        android:layout_width="wrap_content" +        android:layout_height="wrap_content" +        android:id="@+id/imageView" +        android:layout_centerVertical="true" +        android:layout_centerHorizontal="true" /> +</RelativeLayout> diff --git a/app/src/main/res/menu/image_pager.xml b/app/src/main/res/menu/image_pager.xml new file mode 100644 index 0000000..67ae247 --- /dev/null +++ b/app/src/main/res/menu/image_pager.xml @@ -0,0 +1,8 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:tools="http://schemas.android.com/tools" +    tools:context="uk.co.blatech.blaupload.ImagePager" > +    <item android:id="@+id/action_settings" +        android:title="@string/action_settings" +        android:orderInCategory="100" +        android:showAsAction="never" /> +</menu> diff --git a/app/src/main/res/menu/image_viewer.xml b/app/src/main/res/menu/image_viewer.xml new file mode 100644 index 0000000..bed19e0 --- /dev/null +++ b/app/src/main/res/menu/image_viewer.xml @@ -0,0 +1,8 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:tools="http://schemas.android.com/tools" +    tools:context="uk.co.blatech.blaupload.ImageViewer" > +    <item android:id="@+id/action_settings" +        android:title="@string/action_settings" +        android:orderInCategory="100" +        android:showAsAction="never" /> +</menu> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 25d7732..ba06821 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,5 +10,8 @@      <string name="action_example">Example action</string>      <string name="action_settings">Settings</string>      <string name="hello_blank_fragment">Hello blank fragment</string> +    <string name="title_activity_image_viewer">ImageViewer</string> +    <string name="hello_world">Hello world!</string> +    <string name="title_activity_image_pager">ImagePager</string>  </resources> | 
