Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a226972 authored by cketti's avatar cketti
Browse files

Extracted functionality common to most activities to K9ActivityCommon

parent bbcc4988
Loading
Loading
Loading
Loading
+16 −209
Original line number Diff line number Diff line
package com.fsck.k9.activity;


import java.util.Locale;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;

import com.actionbarsherlock.app.SherlockActivity;
import com.fsck.k9.K9;
import com.fsck.k9.activity.K9ActivityCommon.K9ActivityMagic;
import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener;


public class K9Activity extends SherlockActivity {
    protected static final int BEZEL_SWIPE_THRESHOLD = 20;
public class K9Activity extends SherlockActivity implements K9ActivityMagic {

    protected GestureDetector mGestureDetector;
    private K9ActivityCommon mBase;

    @Override
    public void onCreate(Bundle icicle) {
        setLanguage(this, K9.getK9Language());
        setTheme(K9.getK9ThemeResourceId());
        super.onCreate(icicle);
        setupFormats();
    }

    public static void setLanguage(Context context, String language) {
        Locale locale;
        if (language == null || language.equals("")) {
            locale = Locale.getDefault();
        } else if (language.length() == 5 && language.charAt(2) == '_') {
            // language is in the form: en_US
            locale = new Locale(language.substring(0, 2), language.substring(3));
        } else {
            locale = new Locale(language);
        }
        Configuration config = new Configuration();
        config.locale = locale;
        context.getResources().updateConfiguration(config,
                context.getResources().getDisplayMetrics());
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mGestureDetector != null) {
            mGestureDetector.onTouchEvent(ev);
        }
        return super.dispatchTouchEvent(ev);
    public void onCreate(Bundle savedInstanceState) {
        mBase = K9ActivityCommon.newInstance(this);
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        setupFormats();
    }

    private java.text.DateFormat mTimeFormat;

    private void setupFormats() {
        mTimeFormat = android.text.format.DateFormat.getTimeFormat(this);   // 12/24 date format
    }

    public java.text.DateFormat getTimeFormat() {
        return mTimeFormat;
    }

    /**
     * Called when a swipe from right to left is handled by {@link MyGestureDetector}.  See
     * {@link android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)}
     * for more information on the {@link MotionEvent}s being passed.
     * @param e1 First down motion event that started the fling.
     * @param e2 The move motion event that triggered the current onFling.
     */
    protected void onSwipeRightToLeft(final MotionEvent e1, final MotionEvent e2) {
    }

    /**
     * Called when a swipe from left to right is handled by {@link MyGestureDetector}.  See
     * {@link android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)}
     * for more information on the {@link MotionEvent}s being passed.
     * @param e1 First down motion event that started the fling.
     * @param e2 The move motion event that triggered the current onFling.
     */
    protected void onSwipeLeftToRight(final MotionEvent e1, final MotionEvent e2) {
    }

    protected Animation inFromRightAnimation() {
        return slideAnimation(0.0f, +1.0f);
    }

    protected Animation outToLeftAnimation() {
        return slideAnimation(0.0f, -1.0f);
    }

    private Animation slideAnimation(float right, float left) {

        Animation slide = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT,  right, Animation.RELATIVE_TO_PARENT,  left,
            Animation.RELATIVE_TO_PARENT,  0.0f, Animation.RELATIVE_TO_PARENT,   0.0f
        );
        slide.setDuration(125);
        slide.setFillBefore(true);
        slide.setInterpolator(new AccelerateInterpolator());
        return slide;
    }

    class MyGestureDetector extends SimpleOnGestureListener {
        private boolean gesturesEnabled = false;

        /**
         * Creates a new {@link android.view.GestureDetector.OnGestureListener}.  Enabled/disabled based upon
         * {@link com.fsck.k9.K9#gesturesEnabled()}}.
         */
        public MyGestureDetector() {
            super();
    public boolean dispatchTouchEvent(MotionEvent event) {
        mBase.preDispatchTouchEvent(event);
        return super.dispatchTouchEvent(event);
    }

        /**
         * Create a new {@link android.view.GestureDetector.OnGestureListener}.
         * @param gesturesEnabled Setting to <code>true</code> will enable gesture detection,
         * regardless of the system-wide gesture setting.
         */
        public MyGestureDetector(final boolean gesturesEnabled) {
            super();
            this.gesturesEnabled = gesturesEnabled;
        }

        private static final float SWIPE_MAX_OFF_PATH_DIP = 250f;
        private static final float SWIPE_THRESHOLD_VELOCITY_DIP = 325f;


        protected MotionEvent mLastOnDownEvent = null;

    @Override
        public boolean onDown(MotionEvent e) {
            mLastOnDownEvent = e;
            return super.onDown(e);
    public int getThemeBackgroundColor() {
        return mBase.getThemeBackgroundColor();
    }

    @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            // Do fling-detection if gestures are force-enabled or we have system-wide gestures enabled.
            if (gesturesEnabled || K9.gesturesEnabled()) {

                // Apparently sometimes e1 is null
                // Found a workaround here: http://stackoverflow.com/questions/4151385/
                if (e1 == null) {
                    e1 = mLastOnDownEvent;
                }

                // Make sure we avoid NullPointerExceptions
                if (e1 == null || e2 == null) {
                    return false;
                }

                // Calculate the minimum distance required for this to count as a swipe.
                // Convert the constant dips to pixels.
                final float mGestureScale = getResources().getDisplayMetrics().density;
                final int minVelocity = (int)(SWIPE_THRESHOLD_VELOCITY_DIP * mGestureScale + 0.5f);
                final int maxOffPath = (int)(SWIPE_MAX_OFF_PATH_DIP * mGestureScale + 0.5f);

                // Calculate how much was actually swiped.
                final float deltaX = e2.getX() - e1.getX();
                final float deltaY = e2.getY() - e1.getY();

                // Calculate the minimum distance required for this to be considered a swipe.
                final int minDistance = (int)Math.abs(deltaY * 4);

                if(K9.DEBUG) {
                    final boolean movedAcross = (Math.abs(deltaX) > Math.abs(deltaY * 4));
                    final boolean steadyHand = (Math.abs(deltaX / deltaY) > 2);
                    Log.d(K9.LOG_TAG, String.format("Old swipe algorithm: movedAcross=%s steadyHand=%s result=%s", movedAcross, steadyHand, movedAcross && steadyHand));
                    Log.d(K9.LOG_TAG, String.format("New swipe algorithm: deltaX=%.2f deltaY=%.2f minDistance=%d velocity=%.2f (min=%d)", deltaX, deltaY, minDistance, velocityX, minVelocity));
    public void setupGestureDetector(OnSwipeGestureListener listener) {
        mBase.setupGestureDetector(listener);
    }

                try {
                    if (Math.abs(deltaY) > maxOffPath) {
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe too far off horizontal path.");
                        return false;
                    }
                    if(Math.abs(velocityX) < minVelocity) {
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe too slow.");
                        return false;
                    }
                    // right to left swipe
                    if (deltaX < (minDistance * -1)) {
                        onSwipeRightToLeft(e1, e2);
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Right to Left swipe OK.");
                    } else if (deltaX > minDistance) {
                        onSwipeLeftToRight(e1, e2);
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Left to Right swipe OK.");
                    } else {
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe did not meet minimum distance requirements.");
                        return false;
                    }

                    // successful fling, cancel the 2nd event to prevent any other action from happening
                    // see http://code.google.com/p/android/issues/detail?id=8497
                    e2.setAction(MotionEvent.ACTION_CANCEL);
                } catch (Exception e) {
                    // nothing
                }
            }
            return false;
        }
    }

    public int getThemeBackgroundColor() {
        TypedArray array = getTheme().obtainStyledAttributes(new int[] {
            android.R.attr.colorBackground,
        });
        int backgroundColor = array.getColor(0, 0xFF00FF);
        array.recycle();
        return backgroundColor;
    }

}
+115 −0
Original line number Diff line number Diff line
package com.fsck.k9.activity;

import java.util.Locale;

import com.fsck.k9.K9;
import com.fsck.k9.activity.misc.SwipeGestureDetector;
import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener;
import com.fsck.k9.helper.StringUtils;

import android.app.Activity;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.view.GestureDetector;
import android.view.MotionEvent;


/**
 * This class implements functionality common to most activities used in K-9 Mail.
 *
 * @see K9Activity
 * @see K9ListActivity
 * @see K9FragmentActivity
 */
public class K9ActivityCommon {
    /**
     * Creates a new instance of {@link K9ActivityCommon} bound to the specified activity.
     *
     * @param activity
     *         The {@link Activity} the returned {@code K9ActivityCommon} instance will be bound to.
     *
     * @return The {@link K9ActivityCommon} instance that will provide the base functionality of the
     *         "K9" activities.
     */
    public static K9ActivityCommon newInstance(Activity activity) {
        return new K9ActivityCommon(activity);
    }

    public static void setLanguage(Activity activity, String language) {
        Locale locale;
        if (StringUtils.isNullOrEmpty(language)) {
            locale = Locale.getDefault();
        } else if (language.length() == 5 && language.charAt(2) == '_') {
            // language is in the form: en_US
            locale = new Locale(language.substring(0, 2), language.substring(3));
        } else {
            locale = new Locale(language);
        }

        Configuration config = new Configuration();
        config.locale = locale;
        Resources resources = activity.getResources();
        resources.updateConfiguration(config, resources.getDisplayMetrics());
    }


    /**
     * Base activities need to implement this interface.
     *
     * <p>The implementing class simply has to call through to the implementation of these methods
     * in {@link K9ActivityCommon}.</p>
     */
    public interface K9ActivityMagic {
        int getThemeBackgroundColor();
        void setupGestureDetector(OnSwipeGestureListener listener);
    }


    private Activity mActivity;
    private GestureDetector mGestureDetector;


    private K9ActivityCommon(Activity activity) {
        mActivity = activity;
        setLanguage(mActivity, K9.getK9Language());
        mActivity.setTheme(K9.getK9ThemeResourceId());
    }

    /**
     * Call this before calling {@code super.dispatchTouchEvent(MotionEvent)}.
     */
    public void preDispatchTouchEvent(MotionEvent event) {
        if (mGestureDetector != null) {
            mGestureDetector.onTouchEvent(event);
        }
    }

    /**
     * Get the background color of the theme used for this activity.
     *
     * @return The background color of the current theme.
     */
    public int getThemeBackgroundColor() {
        TypedArray array = mActivity.getTheme().obtainStyledAttributes(
                new int[] { android.R.attr.colorBackground });

        int backgroundColor = array.getColor(0, 0xFF00FF);

        array.recycle();

        return backgroundColor;
    }

    /**
     * Call this if you wish to use the swipe gesture detector.
     *
     * @param listener
     *         A listener that will be notified if a left to right or right to left swipe has been
     *         detected.
     */
    public void setupGestureDetector(OnSwipeGestureListener listener) {
        mGestureDetector = new GestureDetector(mActivity,
                new SwipeGestureDetector(mActivity, listener));
    }
}
+16 −209
Original line number Diff line number Diff line
package com.fsck.k9.activity;


import java.util.Locale;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.fsck.k9.K9;
import com.fsck.k9.activity.K9ActivityCommon.K9ActivityMagic;
import com.fsck.k9.activity.misc.SwipeGestureDetector.OnSwipeGestureListener;


public class K9FragmentActivity extends SherlockFragmentActivity {
    protected static final int BEZEL_SWIPE_THRESHOLD = 20;
public class K9FragmentActivity extends SherlockFragmentActivity implements K9ActivityMagic {

    protected GestureDetector mGestureDetector;
    private K9ActivityCommon mBase;

    @Override
    public void onCreate(Bundle icicle) {
        setLanguage(this, K9.getK9Language());
        setTheme(K9.getK9ThemeResourceId());
        super.onCreate(icicle);
        setupFormats();
    }

    public static void setLanguage(Context context, String language) {
        Locale locale;
        if (language == null || language.equals("")) {
            locale = Locale.getDefault();
        } else if (language.length() == 5 && language.charAt(2) == '_') {
            // language is in the form: en_US
            locale = new Locale(language.substring(0, 2), language.substring(3));
        } else {
            locale = new Locale(language);
        }
        Configuration config = new Configuration();
        config.locale = locale;
        context.getResources().updateConfiguration(config,
                context.getResources().getDisplayMetrics());
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mGestureDetector != null) {
            mGestureDetector.onTouchEvent(ev);
        }
        return super.dispatchTouchEvent(ev);
    public void onCreate(Bundle savedInstanceState) {
        mBase = K9ActivityCommon.newInstance(this);
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        setupFormats();
    }

    private java.text.DateFormat mTimeFormat;

    private void setupFormats() {
        mTimeFormat = android.text.format.DateFormat.getTimeFormat(this);   // 12/24 date format
    }

    public java.text.DateFormat getTimeFormat() {
        return mTimeFormat;
    }

    /**
     * Called when a swipe from right to left is handled by {@link MyGestureDetector}.  See
     * {@link android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)}
     * for more information on the {@link MotionEvent}s being passed.
     * @param e1 First down motion event that started the fling.
     * @param e2 The move motion event that triggered the current onFling.
     */
    protected void onSwipeRightToLeft(final MotionEvent e1, final MotionEvent e2) {
    }

    /**
     * Called when a swipe from left to right is handled by {@link MyGestureDetector}.  See
     * {@link android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent, android.view.MotionEvent, float, float)}
     * for more information on the {@link MotionEvent}s being passed.
     * @param e1 First down motion event that started the fling.
     * @param e2 The move motion event that triggered the current onFling.
     */
    protected void onSwipeLeftToRight(final MotionEvent e1, final MotionEvent e2) {
    }

    protected Animation inFromRightAnimation() {
        return slideAnimation(0.0f, +1.0f);
    }

    protected Animation outToLeftAnimation() {
        return slideAnimation(0.0f, -1.0f);
    }

    private Animation slideAnimation(float right, float left) {

        Animation slide = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT,  right, Animation.RELATIVE_TO_PARENT,  left,
            Animation.RELATIVE_TO_PARENT,  0.0f, Animation.RELATIVE_TO_PARENT,   0.0f
        );
        slide.setDuration(125);
        slide.setFillBefore(true);
        slide.setInterpolator(new AccelerateInterpolator());
        return slide;
    }

    class MyGestureDetector extends SimpleOnGestureListener {
        private boolean gesturesEnabled = false;

        /**
         * Creates a new {@link android.view.GestureDetector.OnGestureListener}.  Enabled/disabled based upon
         * {@link com.fsck.k9.K9#gesturesEnabled()}}.
         */
        public MyGestureDetector() {
            super();
    public boolean dispatchTouchEvent(MotionEvent event) {
        mBase.preDispatchTouchEvent(event);
        return super.dispatchTouchEvent(event);
    }

        /**
         * Create a new {@link android.view.GestureDetector.OnGestureListener}.
         * @param gesturesEnabled Setting to <code>true</code> will enable gesture detection,
         * regardless of the system-wide gesture setting.
         */
        public MyGestureDetector(final boolean gesturesEnabled) {
            super();
            this.gesturesEnabled = gesturesEnabled;
        }

        private static final float SWIPE_MAX_OFF_PATH_DIP = 250f;
        private static final float SWIPE_THRESHOLD_VELOCITY_DIP = 325f;


        protected MotionEvent mLastOnDownEvent = null;

    @Override
        public boolean onDown(MotionEvent e) {
            mLastOnDownEvent = e;
            return super.onDown(e);
    public int getThemeBackgroundColor() {
        return mBase.getThemeBackgroundColor();
    }

    @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            // Do fling-detection if gestures are force-enabled or we have system-wide gestures enabled.
            if (gesturesEnabled || K9.gesturesEnabled()) {

                // Apparently sometimes e1 is null
                // Found a workaround here: http://stackoverflow.com/questions/4151385/
                if (e1 == null) {
                    e1 = mLastOnDownEvent;
                }

                // Make sure we avoid NullPointerExceptions
                if (e1 == null || e2 == null) {
                    return false;
                }

                // Calculate the minimum distance required for this to count as a swipe.
                // Convert the constant dips to pixels.
                final float mGestureScale = getResources().getDisplayMetrics().density;
                final int minVelocity = (int)(SWIPE_THRESHOLD_VELOCITY_DIP * mGestureScale + 0.5f);
                final int maxOffPath = (int)(SWIPE_MAX_OFF_PATH_DIP * mGestureScale + 0.5f);

                // Calculate how much was actually swiped.
                final float deltaX = e2.getX() - e1.getX();
                final float deltaY = e2.getY() - e1.getY();

                // Calculate the minimum distance required for this to be considered a swipe.
                final int minDistance = (int)Math.abs(deltaY * 4);

                if(K9.DEBUG) {
                    final boolean movedAcross = (Math.abs(deltaX) > Math.abs(deltaY * 4));
                    final boolean steadyHand = (Math.abs(deltaX / deltaY) > 2);
                    Log.d(K9.LOG_TAG, String.format("Old swipe algorithm: movedAcross=%s steadyHand=%s result=%s", movedAcross, steadyHand, movedAcross && steadyHand));
                    Log.d(K9.LOG_TAG, String.format("New swipe algorithm: deltaX=%.2f deltaY=%.2f minDistance=%d velocity=%.2f (min=%d)", deltaX, deltaY, minDistance, velocityX, minVelocity));
    public void setupGestureDetector(OnSwipeGestureListener listener) {
        mBase.setupGestureDetector(listener);
    }

                try {
                    if (Math.abs(deltaY) > maxOffPath) {
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe too far off horizontal path.");
                        return false;
                    }
                    if(Math.abs(velocityX) < minVelocity) {
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe too slow.");
                        return false;
                    }
                    // right to left swipe
                    if (deltaX < (minDistance * -1)) {
                        onSwipeRightToLeft(e1, e2);
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Right to Left swipe OK.");
                    } else if (deltaX > minDistance) {
                        onSwipeLeftToRight(e1, e2);
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Left to Right swipe OK.");
                    } else {
                        if(K9.DEBUG)
                            Log.d(K9.LOG_TAG, "New swipe algorithm: Swipe did not meet minimum distance requirements.");
                        return false;
                    }

                    // successful fling, cancel the 2nd event to prevent any other action from happening
                    // see http://code.google.com/p/android/issues/detail?id=8497
                    e2.setAction(MotionEvent.ACTION_CANCEL);
                } catch (Exception e) {
                    // nothing
                }
            }
            return false;
        }
    }

    public int getThemeBackgroundColor() {
        TypedArray array = getTheme().obtainStyledAttributes(new int[] {
            android.R.attr.colorBackground,
        });
        int backgroundColor = array.getColor(0, 0xFF00FF);
        array.recycle();
        return backgroundColor;
    }

}
+56 −54

File changed.

Preview size limit exceeded, changes collapsed.

+1 −2
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ import android.preference.Preference;
public class K9PreferenceActivity extends SherlockPreferenceActivity {
    @Override
    public void onCreate(Bundle icicle) {
        K9Activity.setLanguage(this, K9.getK9Language());
        K9ActivityCommon.setLanguage(this, K9.getK9Language());

        if (Build.VERSION.SDK_INT >= 6 && Build.VERSION.SDK_INT < 14) {
            // There's a display bug in all supported Android versions before 4.0 (SDK 14) which
@@ -88,5 +88,4 @@ public class K9PreferenceActivity extends SherlockPreferenceActivity {
            return false;
        }
    }

}
Loading