From ed482a14c98fe458d17f57a3174a092f0e042f6f Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Sun, 9 May 2021 20:19:54 +0300 Subject: [PATCH] visual improvements in template list add a divider between items, similarly to the account list --- .../ui/templates/TemplateListDivider.java | 168 ++++++++++++++++++ .../ui/templates/TemplateListFragment.java | 12 +- .../TemplatesRecyclerViewAdapter.java | 4 +- app/src/main/res/layout/account_list_row.xml | 4 +- .../res/layout/templates_fallback_divider.xml | 29 +-- 5 files changed, 187 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListDivider.java diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListDivider.java b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListDivider.java new file mode 100644 index 00000000..9860e804 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListDivider.java @@ -0,0 +1,168 @@ +/* + * Copyright © 2021 Damyan Ivanov. + * This file is part of MoLe. + * MoLe is free software: you can distribute it and/or modify it + * under the term of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your opinion), any later version. + * + * MoLe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License terms for details. + * + * You should have received a copy of the GNU General Public License + * along with MoLe. If not, see . + */ + +// +// Substantial portions taken from DividerItemDecoration subject to the following license terms: +// +// Copyright 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +package net.ktnx.mobileledger.ui.templates; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.Objects; + +class TemplateListDivider extends DividerItemDecoration { + private final Rect mBounds = new Rect(); + private int mOrientation; + public TemplateListDivider(Context context, int orientation) { + super(context, orientation); + mOrientation = orientation; + } + @Override + public void setOrientation(int orientation) { + super.setOrientation(orientation); + mOrientation = orientation; + } + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + if (parent.getLayoutManager() == null || getDrawable() == null) { + return; + } + if (mOrientation == VERTICAL) { + drawVertical(c, parent); + } + else { + drawHorizontal(c, parent); + } + } + + private void drawVertical(Canvas canvas, RecyclerView parent) { + canvas.save(); + final int left; + final int right; + //noinspection AndroidLintNewApi - NewApi lint fails to handle overrides. + if (parent.getClipToPadding()) { + left = parent.getPaddingLeft(); + right = parent.getWidth() - parent.getPaddingRight(); + canvas.clipRect(left, parent.getPaddingTop(), right, + parent.getHeight() - parent.getPaddingBottom()); + } + else { + left = 0; + right = parent.getWidth(); + } + + final Drawable divider = Objects.requireNonNull(getDrawable()); + final int childCount = parent.getChildCount(); + final TemplatesRecyclerViewAdapter adapter = + (TemplatesRecyclerViewAdapter) Objects.requireNonNull(parent.getAdapter()); + final int itemCount = adapter.getItemCount(); + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + final int childAdapterPosition = parent.getChildAdapterPosition(child); + if (adapter.getItemViewType(childAdapterPosition) == + TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER || + childAdapterPosition + 1 < itemCount && + adapter.getItemViewType(childAdapterPosition + 1) == + TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER) + continue; + parent.getDecoratedBoundsWithMargins(child, mBounds); + final int bottom = mBounds.bottom + Math.round(child.getTranslationY()); + final int top = bottom - divider.getIntrinsicHeight(); + divider.setBounds(left, top, right, bottom); + divider.draw(canvas); + } + canvas.restore(); + } + + private void drawHorizontal(Canvas canvas, RecyclerView parent) { + canvas.save(); + final int top; + final int bottom; + //noinspection AndroidLintNewApi - NewApi lint fails to handle overrides. + if (parent.getClipToPadding()) { + top = parent.getPaddingTop(); + bottom = parent.getHeight() - parent.getPaddingBottom(); + canvas.clipRect(parent.getPaddingLeft(), top, + parent.getWidth() - parent.getPaddingRight(), bottom); + } + else { + top = 0; + bottom = parent.getHeight(); + } + + final Drawable divider = Objects.requireNonNull(getDrawable()); + final int childCount = parent.getChildCount(); + final TemplatesRecyclerViewAdapter adapter = + (TemplatesRecyclerViewAdapter) Objects.requireNonNull(parent.getAdapter()); + final int itemCount = adapter.getItemCount(); + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + final int childAdapterPosition = parent.getChildAdapterPosition(child); + if (adapter.getItemViewType(childAdapterPosition) == + TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER || + childAdapterPosition + 1 < itemCount && + adapter.getItemViewType(childAdapterPosition + 1) == + TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER) + continue; + parent.getLayoutManager() + .getDecoratedBoundsWithMargins(child, mBounds); + final int right = mBounds.right + Math.round(child.getTranslationX()); + final int left = right - divider.getIntrinsicWidth(); + divider.setBounds(left, top, right, bottom); + divider.draw(canvas); + } + canvas.restore(); + } + @Override + public void getItemOffsets(Rect outRect, View child, RecyclerView parent, + RecyclerView.State state) { + final int childAdapterPosition = parent.getChildAdapterPosition(child); + final TemplatesRecyclerViewAdapter adapter = + (TemplatesRecyclerViewAdapter) Objects.requireNonNull(parent.getAdapter()); + final int itemCount = adapter.getItemCount(); + + if (adapter.getItemViewType(childAdapterPosition) == + TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER || + childAdapterPosition + 1 < itemCount && + adapter.getItemViewType(childAdapterPosition + 1) == + TemplatesRecyclerViewAdapter.ITEM_TYPE_DIVIDER) + return; + + super.getItemOffsets(outRect, child, parent, state); + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListFragment.java b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListFragment.java index eb291194..53eb604f 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListFragment.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplateListFragment.java @@ -33,6 +33,7 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleEventObserver; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LiveData; +import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -97,6 +98,10 @@ public class TemplateListFragment extends Fragment { Bundle savedInstanceState) { Logger.debug("flow", "PatternListFragment.onCreateView()"); b = FragmentTemplateListBinding.inflate(inflater); + FragmentActivity activity = requireActivity(); + + if (activity instanceof FabManager.FabHandler) + FabManager.handle((FabManager.FabHandler) activity, b.templateList); TemplatesRecyclerViewAdapter modelAdapter = new TemplatesRecyclerViewAdapter(); @@ -108,10 +113,9 @@ public class TemplateListFragment extends Fragment { LinearLayoutManager llm = new LinearLayoutManager(getContext()); llm.setOrientation(RecyclerView.VERTICAL); b.templateList.setLayoutManager(llm); - - FragmentActivity activity = requireActivity(); - if (activity instanceof FabManager.FabHandler) - FabManager.handle((FabManager.FabHandler) activity, b.templateList); + DividerItemDecoration did = + new TemplateListDivider(activity, DividerItemDecoration.VERTICAL); + b.templateList.addItemDecoration(did); return b.getRoot(); } diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplatesRecyclerViewAdapter.java b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplatesRecyclerViewAdapter.java index 320adc57..0b1c827b 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplatesRecyclerViewAdapter.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/templates/TemplatesRecyclerViewAdapter.java @@ -35,8 +35,8 @@ import java.util.ArrayList; import java.util.List; public class TemplatesRecyclerViewAdapter extends RecyclerView.Adapter { - private static final int ITEM_TYPE_TEMPLATE = 1; - private static final int ITEM_TYPE_DIVIDER = 2; + static final int ITEM_TYPE_TEMPLATE = 1; + static final int ITEM_TYPE_DIVIDER = 2; private final AsyncListDiffer listDiffer; public TemplatesRecyclerViewAdapter() { diff --git a/app/src/main/res/layout/account_list_row.xml b/app/src/main/res/layout/account_list_row.xml index 083eb5ab..185faf80 100644 --- a/app/src/main/res/layout/account_list_row.xml +++ b/app/src/main/res/layout/account_list_row.xml @@ -42,13 +42,11 @@ android:gravity="center_vertical" android:longClickable="true" android:paddingStart="8dp" - android:text="AccountName" + android:text="Example AccountName That Is Too Long And Has to Be Wrapped On More Than One Line Words Words Words" android:textAppearance="@android:style/TextAppearance.Material.Medium" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/account_expander_container" - app:layout_constraintHorizontal_bias="0.0" - app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:ignore="HardcodedText" diff --git a/app/src/main/res/layout/templates_fallback_divider.xml b/app/src/main/res/layout/templates_fallback_divider.xml index 0276db96..bac6bd20 100644 --- a/app/src/main/res/layout/templates_fallback_divider.xml +++ b/app/src/main/res/layout/templates_fallback_divider.xml @@ -20,34 +20,21 @@ android:layout_width="match_parent" android:layout_height="wrap_content" > - - \ No newline at end of file -- 2.39.2