From 9d8ca532f176e3ef565a6276e276370117630948 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Mon, 29 Jul 2019 17:54:13 +0200 Subject: [PATCH] Create option to synchronize text settings (global across all textfields) --- CHANGELOG.md | 9 +- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 39 +-- .../activity/MemeCreateActivity.java | 311 +++++++++--------- .../memetastic/data/MemeEditorElements.java | 8 + .../main/res/layout/memecreate__activity.xml | 1 + .../res/layout/memecreate__moar_controls.xml | 9 +- app/src/main/res/values/strings.xml | 1 + 8 files changed, 209 insertions(+), 173 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc13bef11..442730d6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ ![](https://test.gsantner.net/matomo/piwik.php?action_name=inapp_changelog&idsite=2&rec=1&urlref=https%3A%2F%2Fgithub.com%2Fgsantner%2Fmemetastic%2FCHANGELOG.md&_cvar=%7B%221%22%3A%5B%22source%22%2C%22changelog%22%5D%2C%222%22%3A%5B%22project%22%2C%22memetastic%22%5D%2C%223%22%3A%5B%22packageid%22%2C%22io.github.gsantner.memetastic%22%5D%2C%224%22%3A%5B%22referrer%22%2C%22https%3A%2F%2Fgithub.com%2Fgsantner%2Fmemetastic%2FCHANGELOG.md%22%5D%7D) -### v1.5.1 -- Add 'all' category -- Move 'other' category back to previous location +### v1.6 (in progress) +- Make app simpler to use +- Change primary color brown-black to improve readability +- Add caption option (in creator) to apply text appearance changes to all captions +- Works completly offline, no internet permission requested +- Remove tabbar from main view to see all images immediatly, less clutter ### v1.5.0 - Back to roots with small amount of templates inside projects diff --git a/app/build.gradle b/app/build.gradle index 62f1fc9c8..5ec4af515 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,8 +41,8 @@ android { resValue "string", "manifest_package_id", "io.github.gsantner.memetastic" applicationId "io.github.gsantner.memetastic" - versionName "1.5.3" - versionCode 53 + versionName "1.5.4" + versionCode 54 } flavorDimensions "default" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 989039fb1..885b94b4d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,14 +19,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . #########################################################*/ ---> +--> + - - + + + android:value="2.1" /> + android:resource="@xml/filepaths" /> @@ -58,8 +59,8 @@ android:theme="@style/AppTheme.NoActionBar"> - - + + @@ -73,13 +74,13 @@ android:windowSoftInputMode="adjustResize"> + android:value="net.gsantner.memetastic.activity.MainActivity" /> - - - - + + + + + android:value="net.gsantner.memetastic.activity.MainActivity" /> + android:value="net.gsantner.memetastic.activity.MainActivity" /> + android:value="net.gsantner.memetastic.activity.MainActivity" /> diff --git a/app/src/main/java/net/gsantner/memetastic/activity/MemeCreateActivity.java b/app/src/main/java/net/gsantner/memetastic/activity/MemeCreateActivity.java index 248e91fce..b9bbf5484 100644 --- a/app/src/main/java/net/gsantner/memetastic/activity/MemeCreateActivity.java +++ b/app/src/main/java/net/gsantner/memetastic/activity/MemeCreateActivity.java @@ -20,7 +20,6 @@ #########################################################*/ package net.gsantner.memetastic.activity; -import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -39,6 +38,7 @@ import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v4.content.LocalBroadcastManager; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.Layout; @@ -47,6 +47,7 @@ import android.text.TextUtils; import android.util.Base64; import android.util.Log; +import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -54,7 +55,7 @@ import android.view.WindowManager; import android.widget.AdapterView; import android.widget.Button; -import android.widget.CompoundButton; +import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; @@ -194,6 +195,7 @@ protected void onCreate(Bundle savedInstanceState) { View.VISIBLE : View.GONE); _create_caption.setText(savedInstanceState.getString("captionText")); } + _imageEditView.postDelayed(this::touchTopElement, 30); } private void initCaptionButtons() { @@ -350,94 +352,15 @@ private Bitmap extractBitmapFromIntent(final Intent intent) { return bitmap; } - @Override - public void onBackPressed() { - boolean hasTextInput = !_create_caption.getText().toString().isEmpty() || - !_memeEditorElements.getCaptionBottom().getText().isEmpty() || - !_memeEditorElements.getCaptionTop().getText().isEmpty(); - - // Close views above - if (_bottomContainerVisible) { - toggleMoarControls(true, false); - return; - } - - if (_editBar.getVisibility() != View.GONE) { - settingsDone(); - return; - } - - // Auto save if option checked - if (hasTextInput && _app.settings.isAutoSaveMeme()) { - if (saveMemeToFilesystem(false)) { - finish(); - return; - } - } - - // Close if no input - if (!hasTextInput) { - finish(); - return; - } - - // Else wait for double back-press - if (_doubleBackToExitPressedOnce) { - super.onBackPressed(); - return; - } - _doubleBackToExitPressedOnce = true; - Snackbar.make(findViewById(android.R.id.content), R.string.press_back_again_to_stop_editing__appspecific, Snackbar.LENGTH_SHORT).show(); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - _doubleBackToExitPressedOnce = false; - } - }, 2000); - } - - @OnTouch(R.id.memecreate__activity__image) - public boolean onImageTouched(View view, MotionEvent event) { - if (_editBar.getVisibility() == View.VISIBLE && !_create_caption.getText().toString().isEmpty()) { - onMemeEditorObjectChanged(); - } - if (event.getAction() == MotionEvent.ACTION_DOWN) { - float heightOfPic = view.getMeasuredHeight(); - float heightOfEvent = event.getY(); - - int position = (int) (heightOfEvent / heightOfPic * 100); - - _isBottom = position >= 50; - - _editBar.setVisibility(View.VISIBLE); - - String _areaCaption = _isBottom ? - _memeEditorElements.getCaptionBottom().getText() : - _memeEditorElements.getCaptionTop().getText(); - - _create_caption.setText(_areaCaption); - _create_caption.requestFocus(); - - ActivityUtils.get(this).showSoftKeyboard(); - - if (_bottomContainerVisible) { - toggleMoarControls(true, false); - } - return true; - } - return super.onTouchEvent(event); - } - + // Text settings dialog @OnClick(R.id.settings_caption) public void openSettingsDialog() { ActivityUtils.get(this).hideSoftKeyboard(); _dialogView = View.inflate(this, R.layout.ui__memecreate__text_settings, null); - initDialogViews(_dialogView); + initTextSettingsPopupDialog(_dialogView); - AlertDialog.Builder Builder = new AlertDialog.Builder(this); - - Builder.setTitle(R.string.settings) + AlertDialog dialog = new AlertDialog.Builder(this).setTitle(R.string.settings) //dialog _dialogView .setView(_dialogView) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @@ -448,14 +371,25 @@ public void onClick(DialogInterface dialogInterface, int i) { _create_caption.requestFocus(); } }) - .create().show(); - } + .setOnDismissListener((di) -> { + _toolbar.setVisibility(View.VISIBLE); + _imageEditView.setPadding(0, 0, 0, 0); - @OnClick(R.id.done_caption) - public void settingsDone() { - _editBar.setVisibility(View.GONE); - ActivityUtils.get(this).hideSoftKeyboard(); - onMemeEditorObjectChanged(); + }) + .create(); + + // Get some more space + try { + _toolbar.setVisibility(View.GONE); + WindowManager.LayoutParams wmlp = dialog.getWindow().getAttributes(); + wmlp.gravity = Gravity.TOP; + android.graphics.Point p = new android.graphics.Point(); + getWindowManager().getDefaultDisplay().getSize(p); + _imageEditView.setPadding(0, p.y / 2, 0, 0); + } catch (Exception ignored) { + + } + dialog.show(); } @Override @@ -579,17 +513,7 @@ public void toggleMoarControls(boolean forceVisibile, boolean visible) { container.setLayoutParams(lp); } - @OnClick(R.id.fab) - public void onFloatingButtonClicked(View view) { - toggleMoarControls(false, false); - ActivityUtils.get(this).hideSoftKeyboard(); - View focusedView = this.getCurrentFocus(); - if (focusedView != null) { - ActivityUtils.get(this).hideSoftKeyboard(); - } - } - - private void initDialogViews(View view) { + private void initTextSettingsPopupDialog(View view) { SeekBar textSize = view.findViewById(R.id.meme_dialog__seek_font_size); View textBackGroundColor = view.findViewById(R.id.meme_dialog__color_picker_for_text); View textBorderColor = view.findViewById(R.id.meme_dialog__color_picker_for_border); @@ -611,24 +535,21 @@ private void initDialogViews(View view) { //listeners - View.OnClickListener colorListeners = new View.OnClickListener() { - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.meme_dialog__color_picker_for_text: - if (_isBottom) { - showColorDialog(view.getId(), _memeEditorElements.getCaptionBottom().getTextColor()); - } else { - showColorDialog(view.getId(), _memeEditorElements.getCaptionTop().getTextColor()); - } - break; - case R.id.meme_dialog__color_picker_for_border: - if (_isBottom) { - showColorDialog(view.getId(), _memeEditorElements.getCaptionBottom().getBorderColor()); - } else { - showColorDialog(view.getId(), _memeEditorElements.getCaptionTop().getBorderColor()); - } - } + View.OnClickListener colorListeners = view1 -> { + switch (view1.getId()) { + case R.id.meme_dialog__color_picker_for_text: + if (_isBottom) { + showColorDialog(view1.getId(), _memeEditorElements.getCaptionBottom().getTextColor()); + } else { + showColorDialog(view1.getId(), _memeEditorElements.getCaptionTop().getTextColor()); + } + break; + case R.id.meme_dialog__color_picker_for_border: + if (_isBottom) { + showColorDialog(view1.getId(), _memeEditorElements.getCaptionBottom().getBorderColor()); + } else { + showColorDialog(view1.getId(), _memeEditorElements.getCaptionTop().getBorderColor()); + } } }; @@ -642,7 +563,8 @@ public void onItemSelected(AdapterView parent, View view, int position, long if (_isBottom) { _memeEditorElements.getCaptionBottom().setFont((MemeData.Font) parent.getSelectedItem()); - } else { + } + if (!_isBottom || _memeEditorElements.getImageMain().isTextSettingsGlobal()) { _memeEditorElements.getCaptionTop().setFont((MemeData.Font) parent.getSelectedItem()); } @@ -662,7 +584,9 @@ public void onNothingSelected(AdapterView parent) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (_isBottom) { _memeEditorElements.getCaptionBottom().setFontSize(progress + MemeLibConfig.FONT_SIZES.MIN); - } else { + } + + if (!_isBottom || _memeEditorElements.getImageMain().isTextSettingsGlobal()) { _memeEditorElements.getCaptionTop().setFontSize(progress + MemeLibConfig.FONT_SIZES.MIN); } onMemeEditorObjectChanged(); @@ -680,16 +604,14 @@ public void onStopTrackingTouch(SeekBar seekBar) { }); //switch - allCapsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) { - if (_isBottom) { - _memeEditorElements.getCaptionBottom().setAllCaps(isChecked); - } else { - _memeEditorElements.getCaptionTop().setAllCaps(isChecked); - } - onMemeEditorObjectChanged(); + allCapsSwitch.setOnCheckedChangeListener((compoundButton, isChecked) -> { + if (_isBottom) { + _memeEditorElements.getCaptionBottom().setAllCaps(isChecked); } + if (!_isBottom || _memeEditorElements.getImageMain().isTextSettingsGlobal()) { + _memeEditorElements.getCaptionTop().setAllCaps(isChecked); + } + onMemeEditorObjectChanged(); }); } @@ -697,22 +619,22 @@ private void initMoarControlsContainer() { final Button rotateButton = ButterKnife.findById(this, R.id.memecreate__moar_controls__rotate_plus_90deg); final SeekBar seekPaddingSize = ButterKnife.findById(this, R.id.memecreate__moar_controls__seek_padding_size); final ColorPanelView colorPickerPadding = ButterKnife.findById(this, R.id.memecreate__moar_controls__color_picker_for_padding); + final CheckBox globalTextSettingsCheckbox = findViewById(R.id.memecreate__moar_controls__global_text_settings); + // Apply existing settings _paddingColor.setColor(_memeEditorElements.getImageMain().getPaddingColor()); seekPaddingSize.setProgress(_memeEditorElements.getImageMain().getPadding()); + globalTextSettingsCheckbox.setChecked(_memeEditorElements.getImageMain().isTextSettingsGlobal()); // // Add bottom sheet listeners // - View.OnClickListener colorListener = new View.OnClickListener() { - public void onClick(View v) { - showColorDialog(R.id.memecreate__moar_controls__color_picker_for_padding, - _memeEditorElements.getImageMain().getPaddingColor()); - onMemeEditorObjectChanged(); - } + View.OnClickListener colorListener = v -> { + showColorDialog(R.id.memecreate__moar_controls__color_picker_for_padding, _memeEditorElements.getImageMain().getPaddingColor()); + onMemeEditorObjectChanged(); }; - + globalTextSettingsCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> _memeEditorElements.getImageMain().setTextSettingsGlobal(isChecked)); colorPickerPadding.setOnClickListener(colorListener); seekPaddingSize.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @@ -730,11 +652,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { onMemeEditorObjectChanged(); } }); - rotateButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - _memeEditorElements.getImageMain().setRotationDeg((_memeEditorElements.getImageMain().getRotationDeg() + 90) % 360); - onMemeEditorObjectChanged(); - } + rotateButton.setOnClickListener(v -> { + _memeEditorElements.getImageMain().setRotationDeg((_memeEditorElements.getImageMain().getRotationDeg() + 90) % 360); + onMemeEditorObjectChanged(); }); } @@ -757,7 +677,8 @@ public void onColorSelected(int id, @ColorInt int colorInt) { case R.id.meme_dialog__color_picker_for_border: {// border color if (_isBottom) { _memeEditorElements.getCaptionBottom().setBorderColor(colorInt); - } else { + } + if (!_isBottom || _memeEditorElements.getImageMain().isTextSettingsGlobal()) { _memeEditorElements.getCaptionTop().setBorderColor(colorInt); } View view = _dialogView.findViewById(R.id.meme_dialog__color_picker_for_border); @@ -767,7 +688,8 @@ public void onColorSelected(int id, @ColorInt int colorInt) { case R.id.meme_dialog__color_picker_for_text: {// text background color if (_isBottom) { _memeEditorElements.getCaptionBottom().setTextColor(colorInt); - } else { + } + if (!_isBottom || _memeEditorElements.getImageMain().isTextSettingsGlobal()) { _memeEditorElements.getCaptionTop().setTextColor(colorInt); } View view = _dialogView.findViewById(R.id.meme_dialog__color_picker_for_text); @@ -793,7 +715,7 @@ public void onColorSelected(int id, @ColorInt int colorInt) { public void onDialogDismissed(int id) { } - public Bitmap makeMemeImageFromElements(Context c, MemeEditorElements memeEditorElements) { + public Bitmap renderMemeImageFromElements(Context c, MemeEditorElements memeEditorElements) { // prepare canvas Bitmap bitmap = memeEditorElements.getImageMain().getDisplayImage(); @@ -897,9 +819,10 @@ public void onCaptionChanged(CharSequence text) { public void onMemeEditorObjectChanged() { _imageEditView.setImageBitmap(null); - if (_lastBitmap != null) + if (_lastBitmap != null) { _lastBitmap.recycle(); - Bitmap bmp = makeMemeImageFromElements(this, _memeEditorElements); + } + Bitmap bmp = renderMemeImageFromElements(this, _memeEditorElements); _imageEditView.setImageBitmap(bmp); _lastBitmap = bmp; } @@ -916,9 +839,101 @@ public void recreateImage(boolean createForSaving) { onMemeEditorObjectChanged(); } + ////////////////////////////////////////////////////////////// + //// + /// Visibility etc + // + @OnClick(R.id.done_caption) + public void settingsDone() { + _editBar.setVisibility(View.GONE); + ActivityUtils.get(this).hideSoftKeyboard(); + onMemeEditorObjectChanged(); + } + @OnClick(R.id.memecreate__moar_controls__layout) void onBottomContainerClicked() { toggleMoarControls(true, false); } + @Override + public void onBackPressed() { + boolean hasTextInput = !_create_caption.getText().toString().isEmpty() || + !_memeEditorElements.getCaptionBottom().getText().isEmpty() || + !_memeEditorElements.getCaptionTop().getText().isEmpty(); + + // Close views above + if (_bottomContainerVisible) { + toggleMoarControls(true, false); + return; + } + + if (_editBar.getVisibility() != View.GONE) { + settingsDone(); + return; + } + + // Auto save if option checked + if (hasTextInput && _app.settings.isAutoSaveMeme()) { + if (saveMemeToFilesystem(false)) { + finish(); + return; + } + } + + // Close if no input + if (!hasTextInput) { + finish(); + return; + } + + // Else wait for double back-press + if (_doubleBackToExitPressedOnce) { + super.onBackPressed(); + return; + } + _doubleBackToExitPressedOnce = true; + Snackbar.make(findViewById(android.R.id.content), R.string.press_back_again_to_stop_editing__appspecific, Snackbar.LENGTH_SHORT).show(); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + _doubleBackToExitPressedOnce = false; + } + }, 2000); + } + + public void touchTopElement() { + onImageTouched(_imageEditView, MotionEvent.obtain(1, 1, MotionEvent.ACTION_DOWN, 0, 0, 0)); + } + + @OnTouch(R.id.memecreate__activity__image) + public boolean onImageTouched(View view, MotionEvent event) { + if (_editBar.getVisibility() == View.VISIBLE && !_create_caption.getText().toString().isEmpty()) { + onMemeEditorObjectChanged(); + } + if (event.getAction() == MotionEvent.ACTION_DOWN) { + float heightOfPic = view.getMeasuredHeight(); + float heightOfEvent = event.getY(); + + int position = (int) (heightOfEvent / heightOfPic * 100); + + _isBottom = position >= 50; + + _editBar.setVisibility(View.VISIBLE); + + String _areaCaption = _isBottom ? + _memeEditorElements.getCaptionBottom().getText() : + _memeEditorElements.getCaptionTop().getText(); + + _create_caption.setText(_areaCaption); + _create_caption.requestFocus(); + + ActivityUtils.get(this).showSoftKeyboard(); + + if (_bottomContainerVisible) { + toggleMoarControls(true, false); + } + return true; + } + return super.onTouchEvent(event); + } } diff --git a/app/src/main/java/net/gsantner/memetastic/data/MemeEditorElements.java b/app/src/main/java/net/gsantner/memetastic/data/MemeEditorElements.java index 7884abacd..8e53b02bd 100644 --- a/app/src/main/java/net/gsantner/memetastic/data/MemeEditorElements.java +++ b/app/src/main/java/net/gsantner/memetastic/data/MemeEditorElements.java @@ -192,6 +192,7 @@ public void setImgText(MemeConfig.Caption captionConf) { public static class EditorImage implements Serializable { private Bitmap _image = null; private Bitmap _displayImage = null; + private boolean _isTextSettingsGlobal = true; private int _rotationDeg = 0; private int _padding = 0; private int _paddingColor = MemeLibConfig.MEME_COLORS.WHITE; @@ -224,6 +225,13 @@ public void setRotationDeg(int rotationDeg) { _rotationDeg = rotationDeg; } + public boolean isTextSettingsGlobal() { + return _isTextSettingsGlobal; + } + + public void setTextSettingsGlobal(boolean v) { + _isTextSettingsGlobal = v; + } public int getPadding() { return _padding; diff --git a/app/src/main/res/layout/memecreate__activity.xml b/app/src/main/res/layout/memecreate__activity.xml index 1a369d3c4..0683200ef 100644 --- a/app/src/main/res/layout/memecreate__activity.xml +++ b/app/src/main/res/layout/memecreate__activity.xml @@ -52,6 +52,7 @@ android:layout_margin="16dp" android:minHeight="32dp" android:src="@drawable/ic_color_lens_white_48dp" + android:visibility="gone" app:elevation="6dp" app:pressedTranslationZ="12dp" /> diff --git a/app/src/main/res/layout/memecreate__moar_controls.xml b/app/src/main/res/layout/memecreate__moar_controls.xml index 1f6e135e2..d653f6968 100644 --- a/app/src/main/res/layout/memecreate__moar_controls.xml +++ b/app/src/main/res/layout/memecreate__moar_controls.xml @@ -28,8 +28,8 @@ android:background="#eeeeee" android:fadeScrollbars="false" android:paddingLeft="@dimen/default_margin_2" - android:paddingRight="@dimen/default_margin_2" android:paddingTop="@dimen/default_margin_2" + android:paddingRight="@dimen/default_margin_2" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="net.gsantner.memetastic.activity.MemeCreateActivity"> @@ -100,5 +100,12 @@ android:minHeight="20dp" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 87a16fe94..09ec11555 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -152,5 +152,6 @@ work. If not, see . Close Do you like this project? Do you want that it gets improved and problems fixed?\n\nDeveloping apps and writing related blog posts costs a lot of time! If you want to help so that the project can go on, please consider a small donation!\n\nThis project is developed in leisure time, completely for free and without any advertisements! All + Global text settings