From 9522387646848b32ec943d3f355678ccfdf05924 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 1 May 2020 21:37:45 +0200 Subject: #762 Branding --- .../notes/android/activity/AboutActivity.java | 10 +- .../notes/android/activity/EditNoteActivity.java | 5 + .../notes/android/activity/LockedActivity.java | 4 +- .../NoteListWidgetConfigurationActivity.java | 4 + .../android/activity/NotesListViewActivity.java | 14 +++ .../android/activity/PreferencesActivity.java | 4 + .../fragment/AccountChooserDialogFragment.java | 4 +- .../android/fragment/CategoryDialogFragment.java | 17 ++- .../owncloud/notes/branding/Branded.java | 9 ++ .../owncloud/notes/branding/BrandedActivity.java | 137 +++++++++++++++++++++ .../notes/branding/BrandedAlertDialogBuilder.java | 48 ++++++++ .../branding/BrandedDeleteAlertDialogBuilder.java | 26 ++++ .../notes/branding/BrandedDialogFragment.java | 24 ++++ .../owncloud/notes/branding/BrandedFragment.java | 22 ++++ .../notes/branding/BrandedPreferenceCategory.java | 46 +++++++ .../notes/branding/BrandedSwitchPreference.java | 112 +++++++++++++++++ .../owncloud/notes/branding/BrandingUtil.java | 88 +++++++++++++ .../owncloud/notes/model/ItemAdapter.java | 30 +++-- app/src/main/res/layout/drawer_layout.xml | 1 + app/src/main/res/values/attrs.xml | 5 + app/src/main/res/values/styles.xml | 5 + 21 files changed, 598 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java create mode 100644 app/src/main/res/values/attrs.xml (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java index 0334ba64..6c091c65 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java @@ -15,11 +15,13 @@ import it.niedermann.owncloud.notes.databinding.ActivityAboutBinding; public class AboutActivity extends LockedActivity { + private ActivityAboutBinding binding; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ActivityAboutBinding binding = ActivityAboutBinding.inflate(getLayoutInflater()); + binding = ActivityAboutBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); @@ -27,6 +29,12 @@ public class AboutActivity extends LockedActivity { binding.tabs.setupWithViewPager(binding.pager); } + @Override + public void applyBrand(int mainColor, int textColor) { + + applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar); + } + private class TabsPagerAdapter extends FragmentPagerAdapter { TabsPagerAdapter(FragmentManager fragmentManager) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java index 2e651cdc..c93a14fb 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java @@ -269,4 +269,9 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment public void onAccountChosen(LocalAccount account) { fragment.moveNote(account); } + + @Override + public void applyBrand(int mainColor, int textColor) { + applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar); + } } \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java index 0b0ca7c1..07a544df 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java @@ -8,13 +8,13 @@ import android.os.Bundle; import android.util.Log; import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; import it.niedermann.owncloud.notes.ExceptionHandler; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.BrandedActivity; import it.niedermann.owncloud.notes.util.Notes; -public abstract class LockedActivity extends AppCompatActivity { +public abstract class LockedActivity extends BrandedActivity { private static final String TAG = LockedActivity.class.getSimpleName(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java index 2f50999b..b633e3bf 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java @@ -129,6 +129,10 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + @Override + public void applyBrand(int mainColor, int textColor) { + } + private class LoadCategoryListTask extends AsyncTask> { @Override protected List doInBackground(Void... voids) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index 25c14b8c..8d6507a0 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -50,6 +50,8 @@ import it.niedermann.owncloud.notes.android.MultiSelectedActionModeCallback; import it.niedermann.owncloud.notes.android.NotesListViewItemTouchHelper; import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.AccountChooserListener; import it.niedermann.owncloud.notes.android.fragment.ExceptionDialogFragment; +import it.niedermann.owncloud.notes.branding.BrandingUtil; +import it.niedermann.owncloud.notes.databinding.ActivityNotesListViewBinding; import it.niedermann.owncloud.notes.databinding.DrawerLayoutBinding; import it.niedermann.owncloud.notes.model.Capabilities; import it.niedermann.owncloud.notes.model.Category; @@ -99,6 +101,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter private LocalAccount localAccount; protected DrawerLayoutBinding binding; + protected ActivityNotesListViewBinding activityBinding; private CoordinatorLayout coordinatorLayout; private SwipeRefreshLayout swipeRefreshLayout; @@ -133,6 +136,8 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter CapabilitiesWorker.update(this); binding = DrawerLayoutBinding.inflate(getLayoutInflater()); + activityBinding = ActivityNotesListViewBinding.bind(binding.activityNotesListView.getRoot()); + setContentView(binding.getRoot()); this.coordinatorLayout = binding.activityNotesListView.activityNotesListView; this.swipeRefreshLayout = binding.activityNotesListView.swiperefreshlayout; @@ -218,6 +223,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter localAccount = db.getLocalAccountByAccountName(accountName); if (localAccount != null) { try { + BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor()); ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext()); new NotesListViewItemTouchHelper(ssoAccount, this, db, adapter, syncCallBack, this::refreshLists, swipeRefreshLayout, this).attachToRecyclerView(listView); synchronize(); @@ -422,6 +428,14 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter return this.coordinatorLayout; } + @Override + public void applyBrand(int mainColor, int textColor) { + applyBrandToPrimaryToolbar(mainColor, textColor, activityBinding.notesListActivityActionBar); + applyBrandToFAB(mainColor, textColor, activityBinding.fabCreate); + binding.headerViewBackground.setBackgroundColor(mainColor); + adapter.applyBrand(mainColor, textColor); + } + private class LoadCategoryListTask extends AsyncTask> { @Override protected List doInBackground(Void... voids) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java index 3efc1ad5..15681b2f 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java @@ -27,4 +27,8 @@ public class PreferencesActivity extends LockedActivity { .replace(R.id.fragment_container_view, new PreferencesFragment()) .commit(); } + + @Override + public void applyBrand(int mainColor, int textColor) { + } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java index 880eafb6..af90855d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java @@ -10,7 +10,6 @@ import android.view.WindowManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDialogFragment; import androidx.recyclerview.widget.RecyclerView; @@ -19,6 +18,7 @@ import java.util.Objects; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.AccountChooserListener; +import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder; import it.niedermann.owncloud.notes.databinding.DialogChooseAccountBinding; import it.niedermann.owncloud.notes.model.LocalAccount; import it.niedermann.owncloud.notes.persistence.NotesDatabase; @@ -54,7 +54,7 @@ public class AccountChooserDialogFragment extends AppCompatDialogFragment implem RecyclerView.Adapter adapter = new AccountChooserAdapter(accountsList, this, requireActivity()); binding.accountsList.setAdapter(adapter); - return new AlertDialog.Builder(requireActivity()) + return new BrandedAlertDialogBuilder(requireActivity()) .setView(binding.getRoot()) .setTitle(R.string.simple_move) .setNegativeButton(android.R.string.cancel, null) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java index 74f538ff..8a8ed237 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java @@ -1,6 +1,5 @@ package it.niedermann.owncloud.notes.android.fragment; -import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.Context; @@ -14,12 +13,14 @@ import android.view.WindowManager; import android.widget.EditText; import androidx.annotation.NonNull; -import androidx.appcompat.app.AppCompatDialogFragment; import androidx.fragment.app.Fragment; import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.BrandedActivity; +import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder; +import it.niedermann.owncloud.notes.branding.BrandedDialogFragment; import it.niedermann.owncloud.notes.databinding.DialogChangeCategoryBinding; import it.niedermann.owncloud.notes.model.NavigationAdapter; import it.niedermann.owncloud.notes.persistence.NotesDatabase; @@ -29,16 +30,22 @@ import it.niedermann.owncloud.notes.persistence.NotesDatabase; * It targetFragment is set it must implement the interface {@link CategoryDialogListener}. * The calling Activity must implement the interface {@link CategoryDialogListener}. */ -public class CategoryDialogFragment extends AppCompatDialogFragment { +public class CategoryDialogFragment extends BrandedDialogFragment { private static final String TAG = CategoryDialogFragment.class.getSimpleName(); private static final String STATE_CATEGORY = "category"; + private DialogChangeCategoryBinding binding; private NotesDatabase db; private CategoryDialogListener listener; private EditText editCategory; + @Override + public void applyBrand(int mainColor, int textColor) { + BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.search); + } + /** * Interface that must be implemented by the calling Activity. */ @@ -81,7 +88,7 @@ public class CategoryDialogFragment extends AppCompatDialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { View dialogView = View.inflate(getContext(), R.layout.dialog_change_category, null); - DialogChangeCategoryBinding binding = DialogChangeCategoryBinding.bind(dialogView); + binding = DialogChangeCategoryBinding.bind(dialogView); this.editCategory = binding.search; if (savedInstanceState == null) { @@ -131,7 +138,7 @@ public class CategoryDialogFragment extends AppCompatDialogFragment { } }); - return new AlertDialog.Builder(getActivity()) + return new BrandedAlertDialogBuilder(getActivity()) .setTitle(R.string.change_category_title) .setView(dialogView) .setCancelable(true) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java new file mode 100644 index 00000000..7ef9138d --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java @@ -0,0 +1,9 @@ +package it.niedermann.owncloud.notes.branding; + +import androidx.annotation.ColorInt; +import androidx.annotation.UiThread; + +public interface Branded { + @UiThread + void applyBrand(@ColorInt int mainColor, @ColorInt int textColor); +} \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java new file mode 100644 index 00000000..e2110729 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java @@ -0,0 +1,137 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.res.ColorStateList; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.Menu; +import android.view.View; +import android.view.Window; +import android.widget.EditText; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.graphics.drawable.DrawableCompat; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.tabs.TabLayout; + +import it.niedermann.owncloud.notes.R; + +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES.LOLLIPOP; +import static android.os.Build.VERSION_CODES.M; +import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; +import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark; + +public abstract class BrandedActivity extends AppCompatActivity implements Branded { + + private static final String TAG = BrandedActivity.class.getSimpleName(); + + public static void applyBrandToStatusbar(@NonNull Window window, @ColorInt int mainColor, @ColorInt int textColor) { + if (SDK_INT >= LOLLIPOP) { // Set status bar color + window.setStatusBarColor(mainColor); + if (SDK_INT >= M) { // Set icon and text color of status bar + final View decorView = window.getDecorView(); + if (isColorDark(mainColor)) { + int flags = decorView.getSystemUiVisibility(); + flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + decorView.setSystemUiVisibility(flags); + } else { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + } + } + } + + public static void applyBrandToPrimaryToolbar(@ColorInt int mainColor, @ColorInt int textColor, @NonNull Toolbar toolbar) { + toolbar.setBackgroundColor(mainColor); + toolbar.setTitleTextColor(textColor); + final Drawable overflowDrawable = toolbar.getOverflowIcon(); + if (overflowDrawable != null) { + overflowDrawable.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP); + toolbar.setOverflowIcon(overflowDrawable); + } + + final Drawable navigationDrawable = toolbar.getNavigationIcon(); + if (navigationDrawable != null) { + navigationDrawable.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP); + toolbar.setNavigationIcon(navigationDrawable); + } + } + + public static void applyBrandToFAB(@ColorInt int mainColor, @ColorInt int textColor, @NonNull FloatingActionButton fab) { + fab.setSupportBackgroundTintList(ColorStateList.valueOf(mainColor)); + fab.setColorFilter(textColor); + } + + public static void applyBrandToEditText(@ColorInt int mainColor, @ColorInt int textColor, @NonNull EditText editText) { + @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(editText.getContext(), mainColor); + DrawableCompat.setTintList(editText.getBackground(), new ColorStateList( + new int[][]{ + new int[]{android.R.attr.state_active}, + new int[]{android.R.attr.state_activated}, + new int[]{android.R.attr.state_focused}, + new int[]{android.R.attr.state_pressed}, + new int[]{} + }, + new int[]{ + finalMainColor, + finalMainColor, + finalMainColor, + finalMainColor, + editText.getContext().getResources().getColor(R.color.fg_default) + } + )); + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (BrandingUtil.isBrandingEnabled(this)) { + @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(this); + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(this); + setTheme(isColorDark(textColor) ? R.style.AppThemeLightBrand : R.style.AppTheme); + applyBrandToStatusbar(getWindow(), mainColor, textColor); + } else { + setTheme(R.style.AppTheme); + } + } + + @Override + protected void onStart() { + super.onStart(); + + if (BrandingUtil.isBrandingEnabled(this)) { + @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(this); + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(this); + applyBrand(mainColor, textColor); + } + } + + // TODO maybe this can be handled in R.style.AppThemLightBrand + @Override + public boolean onCreateOptionsMenu(Menu menu) { + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(this); + for (int i = 0; i < menu.size(); i++) { + Drawable drawable = menu.getItem(i).getIcon(); + if (drawable != null) { + drawable = DrawableCompat.wrap(drawable); + DrawableCompat.setTint(drawable, textColor); + menu.getItem(i).setIcon(drawable); + } + } + return super.onCreateOptionsMenu(menu); + } + + protected void applyBrandToPrimaryTabLayout(@ColorInt int mainColor, @ColorInt int textColor, @NonNull TabLayout tabLayout) { + tabLayout.setBackgroundColor(mainColor); + tabLayout.setTabTextColors(textColor, textColor); + tabLayout.setTabIconTint(ColorStateList.valueOf(textColor)); + tabLayout.setSelectedTabIndicatorColor(textColor); + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java new file mode 100644 index 00000000..940d978d --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java @@ -0,0 +1,48 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; +import android.content.DialogInterface; +import android.widget.Button; + +import androidx.annotation.CallSuper; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; + +import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; + +public class BrandedAlertDialogBuilder extends AlertDialog.Builder implements Branded { + + protected AlertDialog dialog; + + public BrandedAlertDialogBuilder(Context context) { + super(context); + } + + @NonNull + @Override + public AlertDialog create() { + this.dialog = super.create(); + + @NonNull Context context = getContext(); + @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context); + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context); + applyBrand(mainColor, textColor); + dialog.setOnShowListener(dialog -> applyBrand(mainColor, textColor)); + return dialog; + } + + @CallSuper + @Override + public void applyBrand(int mainColor, int textColor) { + final Button[] buttons = new Button[3]; + buttons[0] = dialog.getButton(DialogInterface.BUTTON_POSITIVE); + buttons[1] = dialog.getButton(DialogInterface.BUTTON_NEGATIVE); + buttons[2] = dialog.getButton(DialogInterface.BUTTON_NEUTRAL); + for (Button button : buttons) { + if (button != null) { + button.setTextColor(getSecondaryForegroundColorDependingOnTheme(button.getContext(), mainColor)); + } + } + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java new file mode 100644 index 00000000..113acf49 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java @@ -0,0 +1,26 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; +import android.content.DialogInterface; +import android.widget.Button; + +import androidx.annotation.CallSuper; + +import it.niedermann.owncloud.notes.R; + +public class BrandedDeleteAlertDialogBuilder extends BrandedAlertDialogBuilder { + + public BrandedDeleteAlertDialogBuilder(Context context) { + super(context); + } + + @CallSuper + @Override + public void applyBrand(int mainColor, int textColor) { + super.applyBrand(mainColor, textColor); + final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (positiveButton != null) { + positiveButton.setTextColor(getContext().getResources().getColor(R.color.bg_attention)); + } + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java new file mode 100644 index 00000000..63eb2a69 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java @@ -0,0 +1,24 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; + +public abstract class BrandedDialogFragment extends DialogFragment implements Branded { + + @Override + public void onStart() { + super.onStart(); + + @Nullable Context context = getContext(); + if (context != null) { + if (BrandingUtil.isBrandingEnabled(context)) { + @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context); + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context); + applyBrand(mainColor, textColor); + } + } + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java new file mode 100644 index 00000000..63576fda --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java @@ -0,0 +1,22 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +public abstract class BrandedFragment extends Fragment implements Branded { + + @Override + public void onStart() { + super.onStart(); + + @Nullable Context context = getContext(); + if (context != null && BrandingUtil.isBrandingEnabled(context)) { + @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context); + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context); + applyBrand(mainColor, textColor); + } + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java new file mode 100644 index 00000000..d2bcd274 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java @@ -0,0 +1,46 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceViewHolder; + +import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; + +public class BrandedPreferenceCategory extends PreferenceCategory { + + public BrandedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public BrandedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BrandedPreferenceCategory(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BrandedPreferenceCategory(Context context) { + super(context); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + if (BrandingUtil.isBrandingEnabled(getContext())) { + final View v = holder.itemView.findViewById(android.R.id.title); + @Nullable final Context context = getContext(); + if (context != null && v instanceof TextView) { + @ColorInt final int mainColor = getSecondaryForegroundColorDependingOnTheme(context, BrandingUtil.readBrandMainColor(context)); + ((TextView) v).setTextColor(mainColor); + } + } + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java new file mode 100644 index 00000000..b284d31f --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java @@ -0,0 +1,112 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Switch; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.DrawableCompat; +import androidx.preference.PreferenceViewHolder; +import androidx.preference.SwitchPreference; + +import it.niedermann.owncloud.notes.R; + +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES.JELLY_BEAN; +import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; + +public class BrandedSwitchPreference extends SwitchPreference implements Branded { + + @ColorInt + private Integer mainColor = null; + + @ColorInt + private Integer textColor = null; + + @Nullable + private Switch switchView; + + public BrandedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public BrandedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BrandedSwitchPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BrandedSwitchPreference(Context context) { + super(context); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + if (BrandingUtil.isBrandingEnabled(getContext()) && holder.itemView instanceof ViewGroup) { + switchView = findSwitchWidget(holder.itemView); + if (mainColor != null && textColor != null) { + applyBrand(); + } + } + } + + @Override + public void applyBrand(@ColorInt int mainColor, @ColorInt int textColor) { + this.mainColor = mainColor; + this.textColor = textColor; + // onBindViewHolder is called after applyBrand, therefore we have to store the given values and apply them later. + if (BrandingUtil.isBrandingEnabled(getContext())) { + applyBrand(); + } + } + + private void applyBrand() { + if (switchView != null && SDK_INT >= JELLY_BEAN) { + final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(getContext(), mainColor); + // int trackColor = Color.argb(77, Color.red(finalMainColor), Color.green(finalMainColor), Color.blue(finalMainColor)); + DrawableCompat.setTintList(switchView.getThumbDrawable(), new ColorStateList( + new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}}, + new int[]{finalMainColor, getContext().getResources().getColor(R.color.fg_default)} + )); + DrawableCompat.setTintList(switchView.getTrackDrawable(), new ColorStateList( + new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}}, + new int[]{finalMainColor, getContext().getResources().getColor(R.color.fg_default)} + )); + } + } + + /** + * Recursively go through view tree until we find an android.widget.Switch + * + * @param view Root view to start searching + * @return A Switch class or null + * @see Source + */ + private Switch findSwitchWidget(View view) { + if (view instanceof Switch) { + return (Switch) view; + } + if (view instanceof ViewGroup) { + ViewGroup viewGroup = (ViewGroup) view; + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View child = viewGroup.getChildAt(i); + if (child instanceof ViewGroup) { + Switch result = findSwitchWidget(child); + if (result != null) return result; + } + if (child instanceof Switch) { + return (Switch) child; + } + } + } + return null; + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java new file mode 100644 index 00000000..214fbd83 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -0,0 +1,88 @@ +package it.niedermann.owncloud.notes.branding; + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.util.Log; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.preference.PreferenceManager; + +import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.android.DarkModeSetting; +import it.niedermann.owncloud.notes.util.Notes; + +import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient; + +public class BrandingUtil { + + private static final String TAG = BrandingUtil.class.getSimpleName(); + private static final String pref_key_branding = "branding"; + private static final String pref_key_branding_main = "branding_main"; + private static final String pref_key_branding_text = "branding_text"; + + private BrandingUtil() { + + } + + + public static boolean isBrandingEnabled(@NonNull Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getBoolean(pref_key_branding, true); + } + + @ColorInt + public static int readBrandMainColor(@NonNull Context context) { + if (BrandingUtil.isBrandingEnabled(context)) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); + Log.v(TAG, "--- Read: shared_preference_theme_main"); + return sharedPreferences.getInt(pref_key_branding_main, context.getApplicationContext().getResources().getColor(R.color.primary)); + } else { + return context.getResources().getColor(R.color.primary); + } + } + + @ColorInt + public static int readBrandTextColor(@NonNull Context context) { + if (isBrandingEnabled(context)) { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); + Log.v(TAG, "--- Read: shared_preference_theme_text"); + return sharedPreferences.getInt(pref_key_branding_text, context.getApplicationContext().getResources().getColor(android.R.color.white)); + } else { + return Color.WHITE; + } + } + + public static void saveBrandColors(@NonNull Context context, @ColorInt int mainColor, @ColorInt int textColor) { + if (isBrandingEnabled(context) && context instanceof BrandedActivity) { + final BrandedActivity activity = (BrandedActivity) context; + activity.applyBrand(mainColor, textColor); + BrandedActivity.applyBrandToStatusbar(activity.getWindow(), mainColor, textColor); + } + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit(); + Log.v(TAG, "--- Write: shared_preference_theme_main" + " | " + mainColor); + Log.v(TAG, "--- Write: shared_preference_theme_text" + " | " + textColor); + editor.putInt(pref_key_branding_main, mainColor); + editor.putInt(pref_key_branding_text, textColor); + editor.apply(); + } + + /** + * Since we may collide with dark theme in this area, we have to make sure that the color is visible depending on the background + */ + @ColorInt + public static int + getSecondaryForegroundColorDependingOnTheme(@NonNull Context context, @ColorInt int mainColor) { + final boolean isDarkTheme = Notes.getAppTheme(context) == DarkModeSetting.DARK; + if (isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.BLACK)) { + Log.v(TAG, "Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and dark theme is too low. Falling back to WHITE as brand color."); + return Color.WHITE; + } else if (!isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.WHITE)) { + Log.v(TAG, "Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and light theme is too low. Falling back to BLACK as brand color."); + return Color.BLACK; + } else { + return mainColor; + } + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java index c2f2cc4b..e1fa32ec 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java @@ -1,5 +1,6 @@ package it.niedermann.owncloud.notes.model; +import android.content.Context; import android.text.Html; import android.util.Log; import android.view.LayoutInflater; @@ -8,33 +9,41 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.Branded; +import it.niedermann.owncloud.notes.branding.BrandingUtil; import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemBinding; import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding; import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; -public class ItemAdapter extends RecyclerView.Adapter { +public class ItemAdapter extends RecyclerView.Adapter implements Branded { private static final String TAG = ItemAdapter.class.getSimpleName(); private static final int section_type = 0; private static final int note_type = 1; private final NoteClickListener noteClickListener; - private List itemList; + private List itemList = new ArrayList<>(); private boolean showCategory = true; - private final List selected; + @NonNull + private Context context; + private final List selected = new ArrayList<>(); + @ColorInt + private int mainColor; - public ItemAdapter(@NonNull NoteClickListener noteClickListener) { - this.itemList = new ArrayList<>(); - this.selected = new ArrayList<>(); - this.noteClickListener = noteClickListener; + public ItemAdapter(@NonNull T context) { + this.context = context; + this.noteClickListener = context; + this.mainColor = context.getResources().getColor(R.color.primary); } /** @@ -97,6 +106,7 @@ public class ItemAdapter extends RecyclerView.Adapter { nvHolder.noteTitle.setText(Html.fromHtml(note.getTitle())); nvHolder.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE); nvHolder.noteCategory.setText(Html.fromHtml(note.getCategory())); + DrawableCompat.setTint(nvHolder.noteCategory.getBackground(), mainColor); nvHolder.noteExcerpt.setText(Html.fromHtml(note.getExcerpt())); nvHolder.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); nvHolder.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp); @@ -159,6 +169,12 @@ public class ItemAdapter extends RecyclerView.Adapter { return getItem(position).isSection() ? section_type : note_type; } + @Override + public void applyBrand(int mainColor, int textColor) { + this.mainColor = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor); + notifyDataSetChanged(); + } + public interface NoteClickListener { void onNoteClick(int position, View v); diff --git a/app/src/main/res/layout/drawer_layout.xml b/app/src/main/res/layout/drawer_layout.xml index 74419fd9..cf1f0d7b 100644 --- a/app/src/main/res/layout/drawer_layout.xml +++ b/app/src/main/res/layout/drawer_layout.xml @@ -38,6 +38,7 @@ android:theme="@style/ThemeOverlay.AppCompat.Dark"> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index edf7acee..25deffbb 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -9,6 +9,11 @@ @color/bg_normal + + + -- cgit v1.2.3 From 22b226fab96615031f6429ccf5dc820b07d0590f Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 1 May 2020 21:47:02 +0200 Subject: #762 Branding Preferences --- .../android/activity/PreferencesActivity.java | 5 ++- .../android/fragment/PreferencesFragment.java | 36 +++++++++++++++++++--- .../owncloud/notes/model/ItemAdapter.java | 3 +- app/src/main/res/xml/preferences.xml | 6 ++-- 4 files changed, 40 insertions(+), 10 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java index 15681b2f..8e6c0bd5 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java @@ -14,11 +14,13 @@ import it.niedermann.owncloud.notes.databinding.ActivityPreferencesBinding; public class PreferencesActivity extends LockedActivity { + private ActivityPreferencesBinding binding; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ActivityPreferencesBinding binding = ActivityPreferencesBinding.inflate(getLayoutInflater()); + binding = ActivityPreferencesBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); @@ -30,5 +32,6 @@ public class PreferencesActivity extends LockedActivity { @Override public void applyBrand(int mainColor, int textColor) { + applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java index 27ce4fc7..ec1dda15 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java @@ -1,24 +1,32 @@ package it.niedermann.owncloud.notes.android.fragment; import android.app.Activity; +import android.content.Context; import android.os.Bundle; import android.util.Log; +import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import androidx.preference.ListPreference; import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.SwitchPreference; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.android.DarkModeSetting; +import it.niedermann.owncloud.notes.branding.Branded; +import it.niedermann.owncloud.notes.branding.BrandedSwitchPreference; +import it.niedermann.owncloud.notes.branding.BrandingUtil; import it.niedermann.owncloud.notes.persistence.SyncWorker; import it.niedermann.owncloud.notes.util.DeviceCredentialUtil; import it.niedermann.owncloud.notes.util.Notes; -public class PreferencesFragment extends PreferenceFragmentCompat { +public class PreferencesFragment extends PreferenceFragmentCompat implements Branded{ private static final String TAG = PreferencesFragment.class.getSimpleName(); + private BrandedSwitchPreference fontPref; + private BrandedSwitchPreference lockPref; + private BrandedSwitchPreference wifiOnlyPref; + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -28,7 +36,8 @@ public class PreferencesFragment extends PreferenceFragmentCompat { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.preferences); - final SwitchPreference lockPref = findPreference(getString(R.string.pref_key_lock)); + fontPref = findPreference(getString(R.string.pref_key_font)); + lockPref = findPreference(getString(R.string.pref_key_lock)); if (lockPref != null) { if (!DeviceCredentialUtil.areCredentialsAvailable(requireContext())) { lockPref.setVisible(false); @@ -51,7 +60,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat { return true; }); - final SwitchPreference wifiOnlyPref = findPreference(getString(R.string.pref_key_wifi_only)); + wifiOnlyPref = findPreference(getString(R.string.pref_key_wifi_only)); assert wifiOnlyPref != null; wifiOnlyPref.setOnPreferenceChangeListener((preference, newValue) -> { Log.i(TAG, "syncOnWifiOnly: " + newValue); @@ -66,4 +75,23 @@ public class PreferencesFragment extends PreferenceFragmentCompat { return true; }); } + + + @Override + public void onStart() { + super.onStart(); + @Nullable Context context = getContext(); + if (context != null) { + @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context); + @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context); + applyBrand(mainColor, textColor); + } + } + + @Override + public void applyBrand(int mainColor, int textColor) { + fontPref.applyBrand(mainColor, textColor); + lockPref.applyBrand(mainColor, textColor); + wifiOnlyPref.applyBrand(mainColor, textColor); + } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java index e1fa32ec..2716778b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java @@ -11,7 +11,6 @@ import android.widget.TextView; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; -import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; @@ -106,7 +105,7 @@ public class ItemAdapter extends RecyclerView.Adapter i nvHolder.noteTitle.setText(Html.fromHtml(note.getTitle())); nvHolder.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE); nvHolder.noteCategory.setText(Html.fromHtml(note.getCategory())); - DrawableCompat.setTint(nvHolder.noteCategory.getBackground(), mainColor); + // TODO set category border color from mainColor nvHolder.noteExcerpt.setText(Html.fromHtml(note.getExcerpt())); nvHolder.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); nvHolder.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp); diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index c0d1d5ac..4525725f 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1,7 +1,7 @@ - - - Date: Fri, 1 May 2020 21:52:58 +0200 Subject: #762 Branding TextInputLayout in category chooser --- .../android/fragment/CategoryDialogFragment.java | 5 ++- .../owncloud/notes/branding/BrandedActivity.java | 22 ----------- .../owncloud/notes/branding/BrandingUtil.java | 45 ++++++++++++++++++++++ app/src/main/res/layout/dialog_change_category.xml | 1 + 4 files changed, 49 insertions(+), 24 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java index 8a8ed237..3a73c6c6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java @@ -18,9 +18,9 @@ import androidx.fragment.app.Fragment; import java.util.List; import it.niedermann.owncloud.notes.R; -import it.niedermann.owncloud.notes.branding.BrandedActivity; import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder; import it.niedermann.owncloud.notes.branding.BrandedDialogFragment; +import it.niedermann.owncloud.notes.branding.BrandingUtil; import it.niedermann.owncloud.notes.databinding.DialogChangeCategoryBinding; import it.niedermann.owncloud.notes.model.NavigationAdapter; import it.niedermann.owncloud.notes.persistence.NotesDatabase; @@ -43,7 +43,8 @@ public class CategoryDialogFragment extends BrandedDialogFragment { @Override public void applyBrand(int mainColor, int textColor) { - BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.search); + BrandingUtil.applyBrandToEditText(mainColor, textColor, binding.search); + BrandingUtil.applyBrandToTextInputLayout(mainColor, textColor, binding.searchWrapper); } /** diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java index e2110729..10cd9d50 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java @@ -7,7 +7,6 @@ import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.Window; -import android.widget.EditText; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; @@ -24,7 +23,6 @@ import it.niedermann.owncloud.notes.R; import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES.LOLLIPOP; import static android.os.Build.VERSION_CODES.M; -import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark; public abstract class BrandedActivity extends AppCompatActivity implements Branded { @@ -68,26 +66,6 @@ public abstract class BrandedActivity extends AppCompatActivity implements Brand fab.setColorFilter(textColor); } - public static void applyBrandToEditText(@ColorInt int mainColor, @ColorInt int textColor, @NonNull EditText editText) { - @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(editText.getContext(), mainColor); - DrawableCompat.setTintList(editText.getBackground(), new ColorStateList( - new int[][]{ - new int[]{android.R.attr.state_active}, - new int[]{android.R.attr.state_activated}, - new int[]{android.R.attr.state_focused}, - new int[]{android.R.attr.state_pressed}, - new int[]{} - }, - new int[]{ - finalMainColor, - finalMainColor, - finalMainColor, - finalMainColor, - editText.getContext().getResources().getColor(R.color.fg_default) - } - )); - } - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java index 214fbd83..7d972324 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -2,13 +2,18 @@ package it.niedermann.owncloud.notes.branding; import android.content.Context; import android.content.SharedPreferences; +import android.content.res.ColorStateList; import android.graphics.Color; import android.util.Log; +import android.widget.EditText; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.DrawableCompat; import androidx.preference.PreferenceManager; +import com.google.android.material.textfield.TextInputLayout; + import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.android.DarkModeSetting; import it.niedermann.owncloud.notes.util.Notes; @@ -85,4 +90,44 @@ public class BrandingUtil { return mainColor; } } + + public static void applyBrandToEditText(@ColorInt int mainColor, @ColorInt int textColor, @NonNull EditText editText) { + @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(editText.getContext(), mainColor); + DrawableCompat.setTintList(editText.getBackground(), new ColorStateList( + new int[][]{ + new int[]{android.R.attr.state_active}, + new int[]{android.R.attr.state_activated}, + new int[]{android.R.attr.state_focused}, + new int[]{android.R.attr.state_pressed}, + new int[]{} + }, + new int[]{ + finalMainColor, + finalMainColor, + finalMainColor, + finalMainColor, + editText.getContext().getResources().getColor(R.color.fg_default) + } + )); + } + + public static void applyBrandToTextInputLayout(@ColorInt int mainColor, @ColorInt int textColor, @NonNull TextInputLayout til) { + @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(til.getContext(), mainColor); + til.setDefaultHintTextColor(new ColorStateList( + new int[][]{ + new int[]{android.R.attr.state_active}, + new int[]{android.R.attr.state_activated}, + new int[]{android.R.attr.state_focused}, + new int[]{android.R.attr.state_pressed}, + new int[]{} + }, + new int[]{ + finalMainColor, + finalMainColor, + finalMainColor, + finalMainColor, + til.getContext().getResources().getColor(R.color.fg_default) + } + )); + } } diff --git a/app/src/main/res/layout/dialog_change_category.xml b/app/src/main/res/layout/dialog_change_category.xml index a73a32e9..feea9021 100644 --- a/app/src/main/res/layout/dialog_change_category.xml +++ b/app/src/main/res/layout/dialog_change_category.xml @@ -8,6 +8,7 @@ android:orientation="vertical"> -- cgit v1.2.3 From e908abf9b863db9725e7792eec15ce1c65874672 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 1 May 2020 22:02:34 +0200 Subject: #762 Branding TextInputLayout in category chooser --- .../android/fragment/CategoryDialogFragment.java | 1 - .../owncloud/notes/branding/BrandingUtil.java | 22 ---------------------- app/src/main/res/layout/dialog_change_category.xml | 20 +++++++------------- 3 files changed, 7 insertions(+), 36 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java index 3a73c6c6..f46ad69a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java @@ -44,7 +44,6 @@ public class CategoryDialogFragment extends BrandedDialogFragment { @Override public void applyBrand(int mainColor, int textColor) { BrandingUtil.applyBrandToEditText(mainColor, textColor, binding.search); - BrandingUtil.applyBrandToTextInputLayout(mainColor, textColor, binding.searchWrapper); } /** diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java index 7d972324..b4556948 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -12,8 +12,6 @@ import androidx.annotation.NonNull; import androidx.core.graphics.drawable.DrawableCompat; import androidx.preference.PreferenceManager; -import com.google.android.material.textfield.TextInputLayout; - import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.android.DarkModeSetting; import it.niedermann.owncloud.notes.util.Notes; @@ -110,24 +108,4 @@ public class BrandingUtil { } )); } - - public static void applyBrandToTextInputLayout(@ColorInt int mainColor, @ColorInt int textColor, @NonNull TextInputLayout til) { - @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(til.getContext(), mainColor); - til.setDefaultHintTextColor(new ColorStateList( - new int[][]{ - new int[]{android.R.attr.state_active}, - new int[]{android.R.attr.state_activated}, - new int[]{android.R.attr.state_focused}, - new int[]{android.R.attr.state_pressed}, - new int[]{} - }, - new int[]{ - finalMainColor, - finalMainColor, - finalMainColor, - finalMainColor, - til.getContext().getResources().getColor(R.color.fg_default) - } - )); - } } diff --git a/app/src/main/res/layout/dialog_change_category.xml b/app/src/main/res/layout/dialog_change_category.xml index feea9021..86243c23 100644 --- a/app/src/main/res/layout/dialog_change_category.xml +++ b/app/src/main/res/layout/dialog_change_category.xml @@ -5,22 +5,16 @@ android:id="@+id/editCategoryLayout" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"> + android:orientation="vertical" + android:padding="?attr/dialogPreferredPadding"> - - - - + android:hint="@string/change_category_title" + android:importantForAutofill="no" + android:inputType="text" /> Date: Fri, 1 May 2020 22:33:39 +0200 Subject: #762 Branding Drawer header --- .../NoteListWidgetConfigurationActivity.java | 2 +- .../android/activity/NotesListViewActivity.java | 32 +++++++++++++++++++--- .../owncloud/notes/branding/BrandingUtil.java | 3 +- .../owncloud/notes/model/NavigationAdapter.java | 18 ++++++++++-- 4 files changed, 46 insertions(+), 9 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java index b633e3bf..f2e3e0cc 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java @@ -81,7 +81,7 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity { RecyclerView recyclerView; RecyclerView.LayoutManager layoutManager; - adapterCategories = new NavigationAdapter(new NavigationAdapter.ClickListener() { + adapterCategories = new NavigationAdapter(this, new NavigationAdapter.ClickListener() { @Override public void onItemClick(NavigationAdapter.NavigationItem item) { SharedPreferences.Editor sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index 8d6507a0..e8856a8e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -4,6 +4,9 @@ import android.app.SearchManager; import android.content.Intent; import android.content.res.Configuration; import android.database.sqlite.SQLiteConstraintException; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; @@ -68,6 +71,7 @@ import it.niedermann.owncloud.notes.persistence.LoadNotesListTask; import it.niedermann.owncloud.notes.persistence.LoadNotesListTask.NotesLoadedListener; import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper; import it.niedermann.owncloud.notes.persistence.NotesDatabase; +import it.niedermann.owncloud.notes.util.ColorUtil; import it.niedermann.owncloud.notes.util.NoteUtil; import static it.niedermann.owncloud.notes.util.SSOUtil.askForNewAccount; @@ -139,6 +143,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter activityBinding = ActivityNotesListViewBinding.bind(binding.activityNotesListView.getRoot()); setContentView(binding.getRoot()); + this.coordinatorLayout = binding.activityNotesListView.activityNotesListView; this.swipeRefreshLayout = binding.activityNotesListView.swiperefreshlayout; this.fabCreate = binding.activityNotesListView.fabCreate; @@ -358,7 +363,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter private void setupNavigationList(final String selectedItem) { itemRecent = new NavigationItem(ADAPTER_KEY_RECENT, getString(R.string.label_all_notes), null, R.drawable.ic_access_time_grey600_24dp); itemFavorites = new NavigationItem(ADAPTER_KEY_STARRED, getString(R.string.label_favorites), null, R.drawable.ic_star_yellow_24dp); - adapterCategories = new NavigationAdapter(new NavigationAdapter.ClickListener() { + adapterCategories = new NavigationAdapter(this, new NavigationAdapter.ClickListener() { @Override public void onItemClick(NavigationItem item) { selectItem(item, true); @@ -433,7 +438,26 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter applyBrandToPrimaryToolbar(mainColor, textColor, activityBinding.notesListActivityActionBar); applyBrandToFAB(mainColor, textColor, activityBinding.fabCreate); binding.headerViewBackground.setBackgroundColor(mainColor); + binding.appName.setTextColor(textColor); + binding.account.setTextColor(textColor); + + final boolean isDarkTextColor = ColorUtil.isColorDark(textColor); + if (isDarkTextColor) { + binding.appName.setShadowLayer(2, 0.5f, 0, Color.WHITE); + binding.account.setShadowLayer(2, 0.5f, 0, Color.WHITE); + } else { + binding.appName.setShadowLayer(2, 0.5f, 0, Color.BLACK); + binding.account.setShadowLayer(2, 0.5f, 0, Color.BLACK); + } + + final Drawable overflowDrawable = binding.accountArrow.getDrawable(); + if (overflowDrawable != null) { + overflowDrawable.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP); + binding.accountArrow.setImageDrawable(overflowDrawable); + } + adapter.applyBrand(mainColor, textColor); + adapterCategories.applyBrand(mainColor, textColor); } private class LoadCategoryListTask extends AsyncTask> { @@ -526,12 +550,12 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter final NavigationItem itemSettings = new NavigationItem("settings", getString(R.string.action_settings), null, R.drawable.ic_settings_grey600_24dp); final NavigationItem itemAbout = new NavigationItem("about", getString(R.string.simple_about), null, R.drawable.ic_info_outline_grey600_24dp); - ArrayList itemsMenu = new ArrayList<>(); + ArrayList itemsMenu = new ArrayList<>(3); itemsMenu.add(itemTrashbin); itemsMenu.add(itemSettings); itemsMenu.add(itemAbout); - NavigationAdapter adapterMenu = new NavigationAdapter(new NavigationAdapter.ClickListener() { + NavigationAdapter adapterMenu = new NavigationAdapter(this, new NavigationAdapter.ClickListener() { @Override public void onItemClick(NavigationItem item) { if (itemSettings.equals(item)) { @@ -661,7 +685,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter return true; } }); - return true; + return super.onCreateOptionsMenu(menu); } @Override diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java index b4556948..6fe3b61b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -75,8 +75,7 @@ public class BrandingUtil { * Since we may collide with dark theme in this area, we have to make sure that the color is visible depending on the background */ @ColorInt - public static int - getSecondaryForegroundColorDependingOnTheme(@NonNull Context context, @ColorInt int mainColor) { + public static int getSecondaryForegroundColorDependingOnTheme(@NonNull Context context, @ColorInt int mainColor) { final boolean isDarkTheme = Notes.getAppTheme(context) == DarkModeSetting.DARK; if (isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.BLACK)) { Log.v(TAG, "Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and dark theme is too low. Falling back to WHITE as brand color."); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java index 6b061109..9e96112a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java @@ -1,5 +1,6 @@ package it.niedermann.owncloud.notes.model; +import android.content.Context; import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; @@ -7,6 +8,7 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -17,11 +19,16 @@ import java.util.ArrayList; import java.util.List; import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.BrandingUtil; import it.niedermann.owncloud.notes.databinding.ItemNavigationBinding; import it.niedermann.owncloud.notes.util.NoteUtil; public class NavigationAdapter extends RecyclerView.Adapter { + @NonNull + private final Context context; + @ColorInt + private int mainColor; @DrawableRes public static final int ICON_FOLDER = R.drawable.ic_folder_grey600_24dp; @DrawableRes @@ -35,6 +42,11 @@ public class NavigationAdapter extends RecyclerView.Adapter Date: Fri, 1 May 2020 22:41:08 +0200 Subject: #762 Branding Apply new theme colors on Pull 2 refresh --- .../owncloud/notes/android/activity/NotesListViewActivity.java | 1 + 1 file changed, 1 insertion(+) (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index e8856a8e..ef4af97a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -336,6 +336,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter try { capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount); db.updateBrand(localAccount.getId(), capabilities); + BrandingUtil.saveBrandColors(this, Color.parseColor(capabilities.getColor()), Color.parseColor(capabilities.getTextColor())); db.updateApiVersion(localAccount.getId(), capabilities.getApiVersion()); Log.i(TAG, capabilities.toString()); } catch (Exception e) { -- cgit v1.2.3 From e26a6b2f8bd459fc16a80f9ea38f9512dc37e855 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 1 May 2020 22:44:18 +0200 Subject: #762 Branding Apply new theme colors on Pull 2 refresh --- .../owncloud/notes/android/activity/NotesListViewActivity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index ef4af97a..6e6f4c64 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -336,7 +336,9 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter try { capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount); db.updateBrand(localAccount.getId(), capabilities); - BrandingUtil.saveBrandColors(this, Color.parseColor(capabilities.getColor()), Color.parseColor(capabilities.getTextColor())); + localAccount.setColor(Color.parseColor(capabilities.getColor())); + localAccount.setTextColor(Color.parseColor(capabilities.getTextColor())); + BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor()); db.updateApiVersion(localAccount.getId(), capabilities.getApiVersion()); Log.i(TAG, capabilities.toString()); } catch (Exception e) { @@ -459,6 +461,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter adapter.applyBrand(mainColor, textColor); adapterCategories.applyBrand(mainColor, textColor); + invalidateOptionsMenu(); } private class LoadCategoryListTask extends AsyncTask> { -- cgit v1.2.3 From a30ab4cb25198ddae4aa0e57b761d5d92be46021 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 1 May 2020 23:38:20 +0200 Subject: #762 Branding Make a setting --- .../notes/android/fragment/PreferencesFragment.java | 19 ++++++++++++++++++- .../owncloud/notes/branding/BrandingUtil.java | 7 +++++-- .../main/res/drawable/ic_color_lens_grey600_24dp.xml | 5 +++++ app/src/main/res/values/attrs.xml | 3 +-- app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/values/styles.xml | 5 +++-- app/src/main/res/xml/preferences.xml | 9 ++++++++- 7 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java index ec1dda15..82cccba5 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java @@ -8,6 +8,7 @@ import android.util.Log; import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import androidx.preference.ListPreference; +import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import it.niedermann.owncloud.notes.R; @@ -19,13 +20,14 @@ import it.niedermann.owncloud.notes.persistence.SyncWorker; import it.niedermann.owncloud.notes.util.DeviceCredentialUtil; import it.niedermann.owncloud.notes.util.Notes; -public class PreferencesFragment extends PreferenceFragmentCompat implements Branded{ +public class PreferencesFragment extends PreferenceFragmentCompat implements Branded { private static final String TAG = PreferencesFragment.class.getSimpleName(); private BrandedSwitchPreference fontPref; private BrandedSwitchPreference lockPref; private BrandedSwitchPreference wifiOnlyPref; + private BrandedSwitchPreference brandingPref; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -37,6 +39,20 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra addPreferencesFromResource(R.xml.preferences); fontPref = findPreference(getString(R.string.pref_key_font)); + + brandingPref = findPreference(getString(R.string.pref_key_branding)); + if (brandingPref != null) { + brandingPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { + final Boolean branding = (Boolean) newValue; + Log.v(TAG, "branding: " + branding); + requireActivity().setResult(Activity.RESULT_OK); + requireActivity().recreate(); + return true; + }); + } else { + Log.e(TAG, "Could not find preference with key: \"" + getString(R.string.pref_key_branding) + "\""); + } + lockPref = findPreference(getString(R.string.pref_key_lock)); if (lockPref != null) { if (!DeviceCredentialUtil.areCredentialsAvailable(requireContext())) { @@ -93,5 +109,6 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra fontPref.applyBrand(mainColor, textColor); lockPref.applyBrand(mainColor, textColor); wifiOnlyPref.applyBrand(mainColor, textColor); + brandingPref.applyBrand(mainColor, textColor); } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java index 6fe3b61b..37b58b9d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -17,11 +17,11 @@ import it.niedermann.owncloud.notes.android.DarkModeSetting; import it.niedermann.owncloud.notes.util.Notes; import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient; +import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark; public class BrandingUtil { private static final String TAG = BrandingUtil.class.getSimpleName(); - private static final String pref_key_branding = "branding"; private static final String pref_key_branding_main = "branding_main"; private static final String pref_key_branding_text = "branding_text"; @@ -32,7 +32,7 @@ public class BrandingUtil { public static boolean isBrandingEnabled(@NonNull Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - return prefs.getBoolean(pref_key_branding, true); + return prefs.getBoolean(context.getString(R.string.pref_key_branding), true); } @ColorInt @@ -62,6 +62,9 @@ public class BrandingUtil { final BrandedActivity activity = (BrandedActivity) context; activity.applyBrand(mainColor, textColor); BrandedActivity.applyBrandToStatusbar(activity.getWindow(), mainColor, textColor); + // TODO if colors changed, recreate activity + activity.setTheme(isColorDark(textColor) ? R.style.AppThemeLightBrand : R.style.AppTheme); + activity.invalidateOptionsMenu(); } SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit(); Log.v(TAG, "--- Write: shared_preference_theme_main" + " | " + mainColor); diff --git a/app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml b/app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml new file mode 100644 index 00000000..33db0157 --- /dev/null +++ b/app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 808de48d..aafcde07 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -1,5 +1,4 @@ - - + \ 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 be9f36ff..abd1f614 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,6 +112,7 @@ noteMode darkTheme font + branding fontSize wifiOnly lock @@ -179,6 +180,7 @@ Your Nextcloud instance has no free storage left. Please delete some files to sync your local changes into your cloud. Please do not hesitate to contact us if the issues persist. You can find our contact information in the about section in the sidebar. We need the following technical information to help you: + Branding diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 25deffbb..e47c987a 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -7,15 +7,16 @@ @color/primary true @color/bg_normal + @android:color/white + + + - - - - - - - - - -- cgit v1.2.3 From e1ba4569d002c918f88a16f35772397026a305f0 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Jun 2020 17:57:32 +0200 Subject: Make toolbars the same background color as the main content --- .../android/activity/NotesListViewActivity.java | 4 +++ .../owncloud/notes/branding/BrandingUtil.java | 12 +++---- .../owncloud/notes/model/ItemAdapter.java | 2 +- .../owncloud/notes/model/NoteViewHolder.java | 2 +- .../notes/persistence/LoadNotesListTask.java | 2 +- .../owncloud/notes/util/MarkDownUtil.java | 2 +- app/src/main/res/drawable/ic_delete_white_24dp.xml | 5 --- app/src/main/res/drawable/ic_edit_grey600_24dp.xml | 5 +++ app/src/main/res/drawable/ic_edit_white_24dp.xml | 5 --- app/src/main/res/drawable/ic_send_grey600_24dp.xml | 5 +++ app/src/main/res/drawable/ic_send_white_24dp.xml | 5 --- app/src/main/res/layout/activity_about.xml | 38 +++++++++++++--------- app/src/main/res/layout/activity_edit.xml | 24 ++++++++------ app/src/main/res/layout/activity_exception.xml | 6 ++-- .../main/res/layout/activity_notes_list_view.xml | 24 ++++++++------ app/src/main/res/layout/activity_preferences.xml | 25 ++++++++------ app/src/main/res/layout/drawer_layout.xml | 27 +++++++-------- app/src/main/res/layout/fragment_note_edit.xml | 2 +- .../main/res/menu/menu_list_context_multiple.xml | 4 +-- app/src/main/res/menu/menu_note_activity.xml | 2 +- app/src/main/res/menu/menu_note_fragment.xml | 4 +-- app/src/main/res/values-night/colors.xml | 4 +-- app/src/main/res/values/colors.xml | 7 ++-- app/src/main/res/values/styles.xml | 6 +++- 24 files changed, 124 insertions(+), 98 deletions(-) delete mode 100644 app/src/main/res/drawable/ic_delete_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_edit_grey600_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_edit_white_24dp.xml create mode 100644 app/src/main/res/drawable/ic_send_grey600_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_send_white_24dp.xml (limited to 'app/src/main') diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java index a1b375f2..33888333 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java @@ -75,6 +75,7 @@ import it.niedermann.owncloud.notes.persistence.NotesDatabase; import it.niedermann.owncloud.notes.util.ColorUtil; import it.niedermann.owncloud.notes.util.NoteUtil; +import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient; import static it.niedermann.owncloud.notes.util.SSOUtil.askForNewAccount; public class NotesListViewActivity extends LockedActivity implements NoteClickListener, NoteServerSyncHelper.ViewProvider, AccountChooserListener { @@ -447,6 +448,9 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi public void applyBrand(int mainColor, int textColor) { applyBrandToPrimaryToolbar(mainColor, textColor, activityBinding.toolbar); applyBrandToFAB(mainColor, textColor, activityBinding.fabCreate); + + // TODO We assume, that the background of the spinner is always white + activityBinding.swiperefreshlayout.setColorSchemeColors(contrastRatioIsSufficient(Color.WHITE, mainColor) ? mainColor : Color.BLACK); binding.headerViewBackground.setBackgroundColor(mainColor); binding.appName.setTextColor(textColor); binding.account.setTextColor(textColor); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java index 46f92f93..dc627b4e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -13,7 +13,6 @@ import androidx.core.graphics.drawable.DrawableCompat; import androidx.preference.PreferenceManager; import it.niedermann.owncloud.notes.R; -import it.niedermann.owncloud.notes.android.DarkModeSetting; import it.niedermann.owncloud.notes.util.Notes; import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient; @@ -39,9 +38,9 @@ public class BrandingUtil { if (BrandingUtil.isBrandingEnabled(context)) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); Log.v(TAG, "--- Read: shared_preference_theme_main"); - return sharedPreferences.getInt(pref_key_branding_main, context.getApplicationContext().getResources().getColor(R.color.primary)); + return sharedPreferences.getInt(pref_key_branding_main, context.getApplicationContext().getResources().getColor(R.color.defaultBrand)); } else { - return context.getResources().getColor(R.color.primary); + return context.getResources().getColor(R.color.defaultBrand); } } @@ -78,11 +77,12 @@ public class BrandingUtil { */ @ColorInt public static int getSecondaryForegroundColorDependingOnTheme(@NonNull Context context, @ColorInt int mainColor) { - final boolean isDarkTheme = Notes.getAppTheme(context) == DarkModeSetting.DARK; - if (isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.BLACK)) { + final int primaryColor = context.getResources().getColor(R.color.primary); + final boolean isDarkTheme = Notes.isDarkThemeActive(context); + if (isDarkTheme && !contrastRatioIsSufficient(mainColor, primaryColor)) { Log.v(TAG, "Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and dark theme is too low. Falling back to WHITE as brand color."); return Color.WHITE; - } else if (!isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.WHITE)) { + } else if (!isDarkTheme && !contrastRatioIsSufficient(mainColor, primaryColor)) { Log.v(TAG, "Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and light theme is too low. Falling back to BLACK as brand color."); return Color.BLACK; } else { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java index b98c23b9..8da36203 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java @@ -38,7 +38,7 @@ public class ItemAdapter extends RecyclerView.Adapter i public ItemAdapter(@NonNull T context) { this.context = context; this.noteClickListener = context; - this.mainColor = context.getResources().getColor(R.color.primary); + this.mainColor = context.getResources().getColor(R.color.defaultBrand); this.textColor = context.getResources().getColor(android.R.color.white); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java index df55e39a..954ad8a2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java @@ -53,7 +53,7 @@ public class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLo binding.noteCategory.setText(Html.fromHtml(note.getCategory())); DrawableCompat.setTint(binding.noteCategory.getBackground(), mainColor); - binding.noteCategory.setTextColor(Notes.isDarkThemeActive(binding.getRoot().getContext()) ? Color.WHITE : Color.BLACK); + binding.noteCategory.setTextColor(Notes.isDarkThemeActive(binding.getRoot().getContext()) ? textColor : Color.BLACK); binding.noteExcerpt.setText(Html.fromHtml(note.getExcerpt())); binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java index a6b77024..ff3673d9 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java @@ -45,7 +45,7 @@ public class LoadNotesListTask extends AsyncTask> { this.searchQuery = searchQuery; this.accountId = accountId; this.searchBackground = context.getResources().getColor(R.color.bg_highlighted); - this.searchForeground = DisplayUtils.getForeground(Integer.toHexString(this.searchBackground)) ? Color.WHITE : context.getResources().getColor(R.color.primary); + this.searchForeground = DisplayUtils.getForeground(Integer.toHexString(this.searchBackground)) ? Color.WHITE : context.getResources().getColor(R.color.defaultBrand); } @Override diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java index 9d9abe95..66f89280 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java @@ -65,7 +65,7 @@ public class MarkDownUtil { darkTheme ? R.color.widget_fg_dark_theme : R.color.widget_fg_default, null)) .setTodoDoneColor(ResourcesCompat.getColor(context.getResources(), darkTheme ? R.color.widget_fg_dark_theme : R.color.widget_fg_default, null)) - .setLinkFontColor(ResourcesCompat.getColor(context.getResources(), R.color.primary, null)) + .setLinkFontColor(ResourcesCompat.getColor(context.getResources(), R.color.defaultBrand, null)) .setRxMDImageLoader(new NotesImageLoader(context)) .setDefaultImageSize(400, 300); } diff --git a/app/src/main/res/drawable/ic_delete_white_24dp.xml b/app/src/main/res/drawable/ic_delete_white_24dp.xml deleted file mode 100644 index 4d020aff..00000000 --- a/app/src/main/res/drawable/ic_delete_white_24dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_edit_grey600_24dp.xml b/app/src/main/res/drawable/ic_edit_grey600_24dp.xml new file mode 100644 index 00000000..1c520a99 --- /dev/null +++ b/app/src/main/res/drawable/ic_edit_grey600_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_edit_white_24dp.xml b/app/src/main/res/drawable/ic_edit_white_24dp.xml deleted file mode 100644 index 5af858dd..00000000 --- a/app/src/main/res/drawable/ic_edit_white_24dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_send_grey600_24dp.xml b/app/src/main/res/drawable/ic_send_grey600_24dp.xml new file mode 100644 index 00000000..08fdc123 --- /dev/null +++ b/app/src/main/res/drawable/ic_send_grey600_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_send_white_24dp.xml b/app/src/main/res/drawable/ic_send_white_24dp.xml deleted file mode 100644 index 97dd32a4..00000000 --- a/app/src/main/res/drawable/ic_send_white_24dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 7582ef75..10444a88 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -1,30 +1,36 @@ - + android:layout_height="wrap_content"> - + + + + + android:layout_height="wrap_content" + android:background="?attr/colorPrimary" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml index d089db72..2c884af4 100644 --- a/app/src/main/res/layout/activity_edit.xml +++ b/app/src/main/res/layout/activity_edit.xml @@ -1,21 +1,25 @@ - + android:layout_height="wrap_content"> + + + + android:text="@string/simple_close" + android:textColor="@color/defaultBrand" />