diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-06-09 22:44:39 +0300 |
---|---|---|
committer | Niedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com> | 2020-06-09 23:43:05 +0300 |
commit | 68498313f30179ea846ac38b2083e1ab0f352233 (patch) | |
tree | 198db36f5641584a919b3dce85ac54dcac4d938e /app/src/main | |
parent | f2a7499afb102f958f1e725854c2841eca0daec8 (diff) |
#374 Title and category should be centered if no excerpt is given
Diffstat (limited to 'app/src/main')
-rw-r--r-- | app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java | 63 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java | 114 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java | 126 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java | 126 | ||||
-rw-r--r-- | app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java | 6 | ||||
-rw-r--r-- | app/src/main/res/layout/activity_notes_list_view.xml | 2 | ||||
-rw-r--r-- | app/src/main/res/layout/item_notes_list_note_item_with_excerpt.xml (renamed from app/src/main/res/layout/item_notes_list_note_item.xml) | 0 | ||||
-rw-r--r-- | app/src/main/res/layout/item_notes_list_note_item_without_excerpt.xml | 96 |
8 files changed, 398 insertions, 135 deletions
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 ba6042bc..ee5132f8 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 @@ -2,9 +2,9 @@ package it.niedermann.owncloud.notes.model; import android.content.Context; import android.graphics.Color; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; -import android.view.View; import android.view.ViewGroup; import androidx.annotation.ColorInt; @@ -16,19 +16,22 @@ import java.util.List; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.Branded; +import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithExcerptBinding; +import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding; + +import static it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithoutExcerptBinding.inflate; public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 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 static final int TYPE_SECTION = R.layout.item_notes_list_section_item; + private static final int TYPE_NOTE_WITH_EXCERPT = R.layout.item_notes_list_note_item_with_excerpt; + private static final int TYPE_NOTE_WITHOUT_EXCERPT = R.layout.item_notes_list_note_item_without_excerpt; private final NoteClickListener noteClickListener; private List<Item> itemList = new ArrayList<>(); private boolean showCategory = true; private CharSequence searchQuery; - @NonNull - private Context context; private final List<Integer> selected = new ArrayList<>(); @ColorInt private int mainColor; @@ -36,7 +39,6 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i private int textColor; public <T extends Context & NoteClickListener> ItemAdapter(@NonNull T context) { - this.context = context; this.noteClickListener = context; this.mainColor = context.getResources().getColor(R.color.defaultBrand); this.textColor = Color.WHITE; @@ -74,24 +76,37 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View v; - if (viewType == section_type) { - v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_notes_list_section_item, parent, false); - return new SectionViewHolder(v); - } else { - v = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.item_notes_list_note_item, parent, false); - return new NoteViewHolder(v, noteClickListener); + switch (viewType) { + case TYPE_SECTION: { + return new SectionViewHolder(ItemNotesListSectionItemBinding.inflate(LayoutInflater.from(parent.getContext()))); + } + case TYPE_NOTE_WITH_EXCERPT: { + return new NoteViewHolderWithExcerpt(ItemNotesListNoteItemWithExcerptBinding.inflate(LayoutInflater.from(parent.getContext())), noteClickListener); + } + case TYPE_NOTE_WITHOUT_EXCERPT: { + return new NoteViewHolderWithoutExcerpt(inflate(LayoutInflater.from(parent.getContext())), noteClickListener); + } + default: { + throw new IllegalArgumentException("Not supported viewType: " + viewType); + } } } @Override public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { - final Item item = itemList.get(position); - if (item.isSection()) { - ((SectionViewHolder) holder).bind((SectionItem) item); - } else { - ((NoteViewHolder) holder).bind((DBNote) item, noteClickListener, showCategory, mainColor, textColor, searchQuery); + switch (getItemViewType(position)) { + case TYPE_SECTION: { + ((SectionViewHolder) holder).bind((SectionItem) itemList.get(position)); + break; + } + case TYPE_NOTE_WITH_EXCERPT: { + ((NoteViewHolderWithExcerpt) holder).bind((DBNote) itemList.get(position), noteClickListener, showCategory, mainColor, textColor, searchQuery); + break; + } + case TYPE_NOTE_WITHOUT_EXCERPT: { + ((NoteViewHolderWithoutExcerpt) holder).bind((DBNote) itemList.get(position), noteClickListener, showCategory, mainColor, textColor, searchQuery); + break; + } } } @@ -147,7 +162,15 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i @Override public int getItemViewType(int position) { - return getItem(position).isSection() ? section_type : note_type; + Item item = getItem(position); + if (item == null) { + throw new IllegalArgumentException("Item at position " + position + " must not be null"); + } + return getItem(position).isSection() + ? TYPE_SECTION + : TextUtils.isEmpty(((DBNote) getItem(position)).getExcerpt()) + ? TYPE_NOTE_WITHOUT_EXCERPT + : TYPE_NOTE_WITH_EXCERPT; } @Override 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 a42c8377..00c06073 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 @@ -1,40 +1,16 @@ package it.niedermann.owncloud.notes.model; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.GradientDrawable; -import android.os.Build; -import android.text.SpannableString; -import android.text.TextUtils; -import android.text.style.BackgroundColorSpan; -import android.text.style.ForegroundColorSpan; import android.view.View; -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import it.niedermann.owncloud.notes.R; -import it.niedermann.owncloud.notes.branding.BrandingUtil; -import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemBinding; -import it.niedermann.owncloud.notes.util.Notes; - import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; -import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient; -import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark; -public class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { - private final ItemNotesListNoteItemBinding binding; +public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { private final NoteClickListener noteClickListener; public NoteViewHolder(View v, NoteClickListener noteClickListener) { super(v); - binding = ItemNotesListNoteItemBinding.bind(v); this.noteClickListener = noteClickListener; v.setOnClickListener(this); v.setOnLongClickListener(this); @@ -53,91 +29,7 @@ public class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLo return noteClickListener.onNoteLongClick(getAdapterPosition(), v); } - public void showSwipe(boolean left) { - binding.noteFavoriteLeft.setVisibility(left ? View.VISIBLE : View.INVISIBLE); - binding.noteDeleteRight.setVisibility(left ? View.INVISIBLE : View.VISIBLE); - binding.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention); - } - - public void bind(DBNote note, NoteClickListener noteClickListener, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { - @NonNull final Context context = itemView.getContext(); - final boolean isDarkThemeActive = Notes.isDarkThemeActive(context); - - binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); - - binding.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE); - binding.noteCategory.setText(note.getCategory()); - - @ColorInt int categoryForeground; - @ColorInt int categoryBackground; - - if (isDarkThemeActive) { - if (isColorDark(mainColor)) { - if (contrastRatioIsSufficient(mainColor, Color.BLACK)) { - categoryBackground = mainColor; - categoryForeground = Color.WHITE; - } else { - categoryBackground = Color.WHITE; - categoryForeground = mainColor; - } - } else { - categoryBackground = mainColor; - categoryForeground = Color.BLACK; - } - } else { - categoryForeground = Color.BLACK; - if (isColorDark(mainColor) || contrastRatioIsSufficient(mainColor, Color.WHITE)) { - categoryBackground = mainColor; - } else { - categoryBackground = Color.BLACK; - } - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - DrawableCompat.setTint(binding.noteCategory.getBackground(), categoryBackground); - } else { - final GradientDrawable drawable = (GradientDrawable) binding.noteCategory.getBackground(); - drawable.setStroke(1, categoryBackground); - drawable.setColor(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT); - } - binding.noteCategory.setTextColor(categoryForeground); - - binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); - binding.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp); - binding.noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view)); - - if (!TextUtils.isEmpty(searchQuery)) { - @ColorInt final int searchBackground = context.getResources().getColor(R.color.bg_highlighted); - @ColorInt final int searchForeground = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor); - - // The Pattern.quote method will add \Q to the very beginning of the string and \E to the end of the string - // It implies that the string between \Q and \E is a literal string and thus the reserved keyword in such string will be ignored. - // See https://stackoverflow.com/questions/15409296/what-is-the-use-of-pattern-quote-method - final Pattern pattern = Pattern.compile("(" + Pattern.quote(searchQuery.toString()) + ")", Pattern.CASE_INSENSITIVE); - SpannableString spannableString = new SpannableString(note.getTitle()); - Matcher matcher = pattern.matcher(spannableString); - while (matcher.find()) { - spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0); - spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0); - } - - binding.noteTitle.setText(spannableString); + public abstract void showSwipe(boolean left); - spannableString = new SpannableString(note.getExcerpt()); - matcher = pattern.matcher(spannableString); - while (matcher.find()) { - spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0); - spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0); - } - - binding.noteExcerpt.setText(spannableString); - } else { - binding.noteTitle.setText(note.getTitle()); - binding.noteExcerpt.setText(note.getExcerpt()); - } - } - - public View getNoteSwipeable() { - return binding.noteSwipeable; - } + public abstract View getNoteSwipeable(); }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java new file mode 100644 index 00000000..bb64d009 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java @@ -0,0 +1,126 @@ +package it.niedermann.owncloud.notes.model; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; +import android.os.Build; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.BackgroundColorSpan; +import android.text.style.ForegroundColorSpan; +import android.view.View; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.DrawableCompat; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.BrandingUtil; +import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithExcerptBinding; +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 NoteViewHolderWithExcerpt extends NoteViewHolder { + @NonNull + private final ItemNotesListNoteItemWithExcerptBinding binding; + + public NoteViewHolderWithExcerpt(@NonNull ItemNotesListNoteItemWithExcerptBinding binding, @NonNull NoteClickListener noteClickListener) { + super(binding.getRoot(), noteClickListener); + this.binding = binding; + itemView.setOnClickListener(this); + itemView.setOnLongClickListener(this); + } + + public void showSwipe(boolean left) { + binding.noteFavoriteLeft.setVisibility(left ? View.VISIBLE : View.INVISIBLE); + binding.noteDeleteRight.setVisibility(left ? View.INVISIBLE : View.VISIBLE); + binding.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention); + } + + public void bind(DBNote note, NoteClickListener noteClickListener, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + @NonNull final Context context = itemView.getContext(); + final boolean isDarkThemeActive = Notes.isDarkThemeActive(context); + + binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); + binding.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE); + binding.noteCategory.setText(note.getCategory()); + + @ColorInt int categoryForeground; + @ColorInt int categoryBackground; + + if (isDarkThemeActive) { + if (isColorDark(mainColor)) { + if (contrastRatioIsSufficient(mainColor, Color.BLACK)) { + categoryBackground = mainColor; + categoryForeground = Color.WHITE; + } else { + categoryBackground = Color.WHITE; + categoryForeground = mainColor; + } + } else { + categoryBackground = mainColor; + categoryForeground = Color.BLACK; + } + } else { + categoryForeground = Color.BLACK; + if (isColorDark(mainColor) || contrastRatioIsSufficient(mainColor, Color.WHITE)) { + categoryBackground = mainColor; + } else { + categoryBackground = Color.BLACK; + } + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + DrawableCompat.setTint(binding.noteCategory.getBackground(), categoryBackground); + } else { + final GradientDrawable drawable = (GradientDrawable) binding.noteCategory.getBackground(); + drawable.setStroke(1, categoryBackground); + drawable.setColor(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT); + } + binding.noteCategory.setTextColor(categoryForeground); + + binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); + binding.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp); + binding.noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view)); + + if (!TextUtils.isEmpty(searchQuery)) { + @ColorInt final int searchBackground = context.getResources().getColor(R.color.bg_highlighted); + @ColorInt final int searchForeground = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor); + + // The Pattern.quote method will add \Q to the very beginning of the string and \E to the end of the string + // It implies that the string between \Q and \E is a literal string and thus the reserved keyword in such string will be ignored. + // See https://stackoverflow.com/questions/15409296/what-is-the-use-of-pattern-quote-method + final Pattern pattern = Pattern.compile("(" + Pattern.quote(searchQuery.toString()) + ")", Pattern.CASE_INSENSITIVE); + SpannableString spannableString = new SpannableString(note.getTitle()); + Matcher matcher = pattern.matcher(spannableString); + while (matcher.find()) { + spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0); + spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0); + } + + binding.noteTitle.setText(spannableString); + + spannableString = new SpannableString(note.getExcerpt()); + matcher = pattern.matcher(spannableString); + while (matcher.find()) { + spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0); + spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0); + } + + binding.noteExcerpt.setText(spannableString); + } else { + binding.noteTitle.setText(note.getTitle()); + binding.noteExcerpt.setText(note.getExcerpt()); + } + } + + public View getNoteSwipeable() { + return binding.noteSwipeable; + } +}
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java new file mode 100644 index 00000000..a20245d2 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java @@ -0,0 +1,126 @@ +package it.niedermann.owncloud.notes.model; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; +import android.os.Build; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.BackgroundColorSpan; +import android.text.style.ForegroundColorSpan; +import android.view.View; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.DrawableCompat; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import it.niedermann.owncloud.notes.R; +import it.niedermann.owncloud.notes.branding.BrandingUtil; +import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithoutExcerptBinding; +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 NoteViewHolderWithoutExcerpt extends NoteViewHolder { + @NonNull + private final ItemNotesListNoteItemWithoutExcerptBinding binding; + + public NoteViewHolderWithoutExcerpt(@NonNull ItemNotesListNoteItemWithoutExcerptBinding binding, @NonNull NoteClickListener noteClickListener) { + super(binding.getRoot(), noteClickListener); + this.binding = binding; + itemView.setOnClickListener(this); + itemView.setOnLongClickListener(this); + } + + + public void showSwipe(boolean left) { + binding.noteFavoriteLeft.setVisibility(left ? View.VISIBLE : View.INVISIBLE); + binding.noteDeleteRight.setVisibility(left ? View.INVISIBLE : View.VISIBLE); + binding.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention); + } + + public void bind(DBNote note, NoteClickListener noteClickListener, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + @NonNull final Context context = itemView.getContext(); + final boolean isDarkThemeActive = Notes.isDarkThemeActive(context); + + binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); + + binding.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE); + binding.noteCategory.setText(note.getCategory()); + + @ColorInt int categoryForeground; + @ColorInt int categoryBackground; + + if (isDarkThemeActive) { + if (isColorDark(mainColor)) { + if (contrastRatioIsSufficient(mainColor, Color.BLACK)) { + categoryBackground = mainColor; + categoryForeground = Color.WHITE; + } else { + categoryBackground = Color.WHITE; + categoryForeground = mainColor; + } + } else { + categoryBackground = mainColor; + categoryForeground = Color.BLACK; + } + } else { + categoryForeground = Color.BLACK; + if (isColorDark(mainColor) || contrastRatioIsSufficient(mainColor, Color.WHITE)) { + categoryBackground = mainColor; + } else { + categoryBackground = Color.BLACK; + } + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + DrawableCompat.setTint(binding.noteCategory.getBackground(), categoryBackground); + } else { + final GradientDrawable drawable = (GradientDrawable) binding.noteCategory.getBackground(); + drawable.setStroke(1, categoryBackground); + drawable.setColor(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT); + } + binding.noteCategory.setTextColor(categoryForeground); + + binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); + binding.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp); + binding.noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view)); + + if (!TextUtils.isEmpty(searchQuery)) { + @ColorInt final int searchBackground = context.getResources().getColor(R.color.bg_highlighted); + @ColorInt final int searchForeground = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor); + + // The Pattern.quote method will add \Q to the very beginning of the string and \E to the end of the string + // It implies that the string between \Q and \E is a literal string and thus the reserved keyword in such string will be ignored. + // See https://stackoverflow.com/questions/15409296/what-is-the-use-of-pattern-quote-method + final Pattern pattern = Pattern.compile("(" + Pattern.quote(searchQuery.toString()) + ")", Pattern.CASE_INSENSITIVE); + SpannableString spannableString = new SpannableString(note.getTitle()); + Matcher matcher = pattern.matcher(spannableString); + while (matcher.find()) { + spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0); + spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0); + } + + binding.noteTitle.setText(spannableString); + + spannableString = new SpannableString(note.getExcerpt()); + matcher = pattern.matcher(spannableString); + while (matcher.find()) { + spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0); + spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0); + } + + } else { + binding.noteTitle.setText(note.getTitle()); + } + } + + public View getNoteSwipeable() { + return binding.noteSwipeable; + } +}
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java index 3441cc85..98a273a2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java @@ -9,9 +9,9 @@ import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding; public class SectionViewHolder extends RecyclerView.ViewHolder { private final ItemNotesListSectionItemBinding binding; - public SectionViewHolder(View view) { - super(view); - binding = ItemNotesListSectionItemBinding.bind(view); + public SectionViewHolder(ItemNotesListSectionItemBinding binding) { + super(binding.getRoot()); + this.binding = binding; } public void bind(SectionItem item) { diff --git a/app/src/main/res/layout/activity_notes_list_view.xml b/app/src/main/res/layout/activity_notes_list_view.xml index e94a5c5c..b1f318ed 100644 --- a/app/src/main/res/layout/activity_notes_list_view.xml +++ b/app/src/main/res/layout/activity_notes_list_view.xml @@ -124,7 +124,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" - tools:listitem="@layout/item_notes_list_note_item" /> + tools:listitem="@layout/item_notes_list_note_item_with_excerpt" /> </FrameLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> diff --git a/app/src/main/res/layout/item_notes_list_note_item.xml b/app/src/main/res/layout/item_notes_list_note_item_with_excerpt.xml index ba88af2a..ba88af2a 100644 --- a/app/src/main/res/layout/item_notes_list_note_item.xml +++ b/app/src/main/res/layout/item_notes_list_note_item_with_excerpt.xml diff --git a/app/src/main/res/layout/item_notes_list_note_item_without_excerpt.xml b/app/src/main/res/layout/item_notes_list_note_item_without_excerpt.xml new file mode 100644 index 00000000..6645dc2e --- /dev/null +++ b/app/src/main/res/layout/item_notes_list_note_item_without_excerpt.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/noteSwipeFrame" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@color/bg_attention"> + + <ImageView + android:id="@+id/noteFavoriteLeft" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center_vertical" + android:layout_marginStart="@dimen/button_padding" + android:layout_marginLeft="@dimen/button_padding" + android:contentDescription="@string/menu_favorite" + app:srcCompat="@drawable/ic_star_white_24dp" /> + + <ImageView + android:id="@+id/noteDeleteRight" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="@dimen/button_padding" + android:layout_marginRight="@dimen/button_padding" + android:contentDescription="@string/menu_delete" + app:srcCompat="@drawable/ic_delete_white_32dp" /> + + <LinearLayout + android:id="@+id/noteSwipeable" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/list_item_background_selector" + android:baselineAligned="false" + android:gravity="center_vertical"> + + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/noteFavorite" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/menu_favorite" + android:padding="@dimen/spacer_2x" + tools:src="@drawable/ic_star_yellow_24dp" /> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/noteStatus" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + android:layout_marginTop="12dp" + android:layout_marginEnd="4dp" + android:layout_marginRight="4dp" + android:baseline="14dp" + app:srcCompat="@drawable/ic_sync_blue_18dp" /> + </FrameLayout> + + <TextView + android:id="@+id/noteTitle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:ellipsize="end" + android:maxLines="1" + android:paddingTop="@dimen/spacer_2x" + android:paddingBottom="@dimen/spacer_2x" + android:textColor="?android:textColorPrimary" + android:textSize="@dimen/primary_font_size" + tools:text="@tools:sample/lorem/random" /> + + <TextView + android:id="@+id/noteCategory" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacer_1x" + android:layout_marginLeft="@dimen/spacer_1x" + android:layout_marginEnd="@dimen/spacer_2x" + android:layout_marginRight="@dimen/spacer_2x" + android:background="@drawable/border" + android:maxLines="1" + android:paddingLeft="@dimen/spacer_1x" + android:paddingRight="@dimen/spacer_1x" + android:paddingBottom="1dp" + android:singleLine="true" + android:textColor="?android:textColorPrimary" + android:textSize="@dimen/secondary_font_size" + tools:maxLength="15" + tools:text="@tools:sample/lorem/random" /> + </LinearLayout> + +</FrameLayout> |