/* * Copyright 2015. Appsi Mobile * * 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 com.appsimobile.appsii; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.os.AsyncTask; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.RelativeLayout; import com.appsimobile.appsii.dagger.AppInjector; import java.lang.ref.WeakReference; import javax.inject.Inject; /** * Created by Nick Martens on 6/20/13. */ public class PatternRelativeLayout extends RelativeLayout implements SharedPreferences.OnSharedPreferenceChangeListener { // watch the properties: // pref_sidebar_background_image // pref_sidebar_size // pref_sidebar_background_horizontal_repeat // pref_sidebar_background_vertical_repeat int mAlpha; float mXposition; float mYposition; AsyncTask<Void, Void, Bitmap> mBackgroundLoader; int mOldWidth; int mOldHeight; boolean mShouldMeasureChildren = true; //private ViewPager mViewPager; boolean mShouldLayoutChildren = true; boolean mBlockLayouts; Configuration mOldConfiguration; Bitmap mActivePattern; @Inject SharedPreferences mSharedPreferences; private BitmapDrawable mBitmapDrawable; private boolean mTileX; private boolean mTileY; { AppInjector.inject(this); } public PatternRelativeLayout(Context context) { super(context); } public PatternRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public PatternRelativeLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /* @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mBlockLayouts && !mShouldMeasureChildren) { int w = MeasureSpec.getSize(widthMeasureSpec); int h = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(w, h); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mShouldMeasureChildren = false; } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (mBlockLayouts && !mShouldLayoutChildren) { mViewPager.layout(mViewPager.getLeft(), mViewPager.getTop(), mViewPager.getRight(), mViewPager.getBottom()); return; } mShouldLayoutChildren = false; super.onLayout(changed, l, t, r, b); } */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mBlockLayouts) { setBlockLayouts(false); } mShouldLayoutChildren = true; mShouldMeasureChildren = true; return super.onInterceptTouchEvent(ev); } public void setBlockLayouts(boolean blockLayouts) { if (blockLayouts != mBlockLayouts) { mBlockLayouts = blockLayouts; if (blockLayouts) { requestLayout(); invalidate(); } } } @Override protected void dispatchDraw(Canvas canvas) { try { super.dispatchDraw(canvas); } catch (NullPointerException e) { Log.e("PatternRelativeLayout", "prevented framework level crash, this may cause flickering", e); } } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { try { return super.drawChild(canvas, child, drawingTime); } catch (Exception e) { Log.e("PatternRelativeLayout", "prevented framework level crash, this may cause flickering", e); } return false; } @TargetApi(Build.VERSION_CODES.FROYO) @Override protected void onConfigurationChanged(Configuration newConfig) { boolean needsUpdate = mOldConfiguration == null; if (!needsUpdate) { needsUpdate = newConfig.orientation != mOldConfiguration.orientation; } if (needsUpdate) { updateBitmap(); } super.onConfigurationChanged(newConfig); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (oldw == 0) { oldw = mOldWidth; } if (oldh == 0) { oldh = mOldHeight; } mOldWidth = w; mOldHeight = h; super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { onDrawImpl(canvas); // <-- NOTE THIS CALL, WHEN REMOVING TO THIS PROPERLY!!! super.onDraw(canvas); } //Paint mPaint; protected void onDrawImpl(Canvas canvas) { if (mBitmapDrawable != null) { //mActivePattern = BitmapFactory.decodeResource(getResources(), // R.drawable.colorful_bubbles); int xOffset = 0; int yOffset = 0; int totalWidth = getWidth() - getPaddingLeft() - getPaddingRight(); int totalHeight = getHeight() - getPaddingTop() - getPaddingBottom(); int patternWidth = mActivePattern.getWidth(); int patternHeight = mActivePattern.getHeight(); int w = mTileX ? totalWidth : Math.min(totalWidth, patternWidth); int h = mTileY ? totalHeight : Math.min(totalHeight, patternHeight); if (!mTileX) { int spaceLeft = totalWidth; spaceLeft -= patternWidth; if (spaceLeft > 0) { xOffset = (int) ((spaceLeft / 100f) * mXposition); } } if (!mTileY) { int spaceLeft = totalHeight; spaceLeft -= patternHeight; if (spaceLeft > 0) { yOffset = (int) ((spaceLeft / 100f) * mYposition); } } canvas.translate(xOffset, yOffset); mBitmapDrawable.setBounds(getPaddingLeft(), getPaddingTop(), w + getPaddingLeft(), h); mBitmapDrawable.setAlpha(mAlpha); mBitmapDrawable.draw(canvas); canvas.translate(-xOffset, -yOffset); /* Paint p = new Paint(); p.setColor(Color.WHITE); canvas.drawRect(0, 0, totalWidth - 1, totalHeight - 1, p); p.setColor(Color.GREEN); canvas.drawRect(0, 0, w - 1, h - 1, p); */ //canvas.drawRect(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), // getHeight() - getPaddingBottom(), mPaint); } } @Override protected void onFinishInflate() { super.onFinishInflate(); setWillNotDraw(false); if (!isInEditMode()) { updateBitmap(); SharedPreferences preferences = mSharedPreferences; preferences.registerOnSharedPreferenceChangeListener(this); mAlpha = getAlpha(preferences.getInt("pref_sidebar_background_transparency", 0)); mXposition = preferences.getInt("pref_sidebar_background_x_pos", 0); mYposition = preferences.getInt("pref_sidebar_background_y_pos", 0); } //mViewPager = (ViewPager) findViewById(R.id.sidebar_pager); } private void updateBitmap() { SharedPreferences preferences = mSharedPreferences; int height = getContext().getResources().getDisplayMetrics().heightPixels; int widthTmp = getContext().getResources().getDisplayMetrics().widthPixels; int width = Math.min(height, widthTmp); height = Math.max(height, widthTmp); float sidebarPercentage = preferences.getInt("pref_sidebar_size", 80); width = (int) ((width * sidebarPercentage) / 100f); loadBackground(getContext(), width, height); } int getAlpha(int preferenceValue) { preferenceValue = 100 - Math.min(preferenceValue, 100); return (preferenceValue * 255) / 100; } // preventing the system for crashing on 4.0.3 / 4.0.4 devices with hw accelleration enabled void loadBackground(final Context context, final int width, final int height) { if (mBackgroundLoader != null) { mBackgroundLoader.cancel(true); } final WeakReference<Context> contextReference = new WeakReference<Context>(context); mBackgroundLoader = new AsyncTask<Void, Void, Bitmap>() { @Override protected Bitmap doInBackground(Void... params) { Context context = contextReference.get(); if (context == null) return null; SharedPreferences preferences = mSharedPreferences; return ThemingUtils.getSidebarWallpaper(context, preferences, width, height); } @Override protected void onPostExecute(Bitmap bitmap) { mActivePattern = bitmap; updatePaint(); } }; mBackgroundLoader.execute(); } void updatePaint() { if (mActivePattern == null) { //mPaint = null; mBitmapDrawable = null; return; } mBitmapDrawable = new BitmapDrawable(getResources(), mActivePattern); //mPaint = new Paint(); SharedPreferences preferences = mSharedPreferences; String hType = preferences.getString("pref_sidebar_background_horizontal_repeat", "none"); String vType = preferences.getString("pref_sidebar_background_vertical_repeat", "none"); Shader.TileMode vertical = getTileMode(vType); Shader.TileMode horizontal = getTileMode(hType); if (horizontal != null) { mBitmapDrawable.setTileModeX(horizontal); mTileX = true; } else { mTileX = false; } if (vertical != null) { mBitmapDrawable.setTileModeY(vertical); mTileY = true; } else { mTileY = false; } } Shader.TileMode getTileMode(String prefValue) { if (prefValue.equals("repeat")) { return Shader.TileMode.REPEAT; } else if (prefValue.equals("mirror")) { return Shader.TileMode.MIRROR; } else if (prefValue.equals("repeat_edges")) { return Shader.TileMode.CLAMP; } return null; } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals("pref_sidebar_custom_background") || key.equals("pref_sidebar_background_image") || key.equals("pref_sidebar_size")) { updateBitmap(); } else if (key.equals("pref_sidebar_background_horizontal_repeat") || key.equals("pref_sidebar_background_vertical_repeat")) { updatePaint(); } else if (key.equals("pref_sidebar_background_transparency")) { mAlpha = getAlpha(sharedPreferences.getInt(key, 100)); invalidate(); } else if (key.equals("pref_sidebar_background_x_pos") || key.equals("pref_sidebar_background_y_pos")) { mXposition = sharedPreferences.getInt("pref_sidebar_background_x_pos", 0); mYposition = sharedPreferences.getInt("pref_sidebar_background_y_pos", 0); invalidate(); } } }