Fix conversation media overview underline flicker.
This commit is contained in:
parent
f2a490b07e
commit
911dd9efb1
5 changed files with 118 additions and 35 deletions
|
@ -4,6 +4,9 @@ import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -15,6 +18,8 @@ public class ControllableTabLayout extends TabLayout {
|
||||||
|
|
||||||
private List<View> touchables;
|
private List<View> touchables;
|
||||||
|
|
||||||
|
private NewTabListener newTabListener;
|
||||||
|
|
||||||
public ControllableTabLayout(Context context) {
|
public ControllableTabLayout(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
@ -39,4 +44,28 @@ public class ControllableTabLayout extends TabLayout {
|
||||||
|
|
||||||
super.setEnabled(enabled);
|
super.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNewTabListener(@Nullable NewTabListener newTabListener) {
|
||||||
|
this.newTabListener = newTabListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Tab newTab() {
|
||||||
|
Tab tab = super.newTab();
|
||||||
|
|
||||||
|
if (newTabListener != null) {
|
||||||
|
newTabListener.onNewTab(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows implementor to modify tabs when they are created, before they are added to the tab layout.
|
||||||
|
* This is useful for loading custom views, to ensure that time is not spent inflating these views
|
||||||
|
* as the user is switching between pages.
|
||||||
|
*/
|
||||||
|
public interface NewTabListener {
|
||||||
|
void onNewTab(@NonNull Tab tab);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.thoughtcrime.securesms.mediaoverview;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -27,19 +26,19 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
|
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.components.AnimatingToggle;
|
import org.thoughtcrime.securesms.components.AnimatingToggle;
|
||||||
|
import org.thoughtcrime.securesms.components.ControllableTabLayout;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MediaDatabase;
|
import org.thoughtcrime.securesms.database.MediaDatabase;
|
||||||
import org.thoughtcrime.securesms.database.MediaDatabase.Sorting;
|
import org.thoughtcrime.securesms.database.MediaDatabase.Sorting;
|
||||||
|
@ -51,6 +50,7 @@ import org.whispersystems.libsignal.util.Pair;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity for displaying media attachments in-app
|
* Activity for displaying media attachments in-app
|
||||||
|
@ -62,7 +62,7 @@ public final class MediaOverviewActivity extends PassphraseRequiredActivity {
|
||||||
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
|
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
|
||||||
|
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private TabLayout tabLayout;
|
private ControllableTabLayout tabLayout;
|
||||||
private ViewPager viewPager;
|
private ViewPager viewPager;
|
||||||
private TextView sortOrder;
|
private TextView sortOrder;
|
||||||
private View sortOrderArrow;
|
private View sortOrderArrow;
|
||||||
|
@ -98,6 +98,7 @@ public final class MediaOverviewActivity extends PassphraseRequiredActivity {
|
||||||
|
|
||||||
boolean allThreads = threadId == MediaDatabase.ALL_THREADS;
|
boolean allThreads = threadId == MediaDatabase.ALL_THREADS;
|
||||||
|
|
||||||
|
tabLayout.setNewTabListener(new NewTabListener());
|
||||||
tabLayout.addOnTabSelectedListener(new OnTabSelectedListener());
|
tabLayout.addOnTabSelectedListener(new OnTabSelectedListener());
|
||||||
fillTabLayoutIfFits(tabLayout);
|
fillTabLayoutIfFits(tabLayout);
|
||||||
tabLayout.setupWithViewPager(viewPager);
|
tabLayout.setupWithViewPager(viewPager);
|
||||||
|
@ -221,7 +222,7 @@ public final class MediaOverviewActivity extends PassphraseRequiredActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSortOrderDialog(View v) {
|
private void showSortOrderDialog(View v) {
|
||||||
new AlertDialog.Builder(MediaOverviewActivity.this)
|
new MaterialAlertDialogBuilder(MediaOverviewActivity.this)
|
||||||
.setTitle(R.string.MediaOverviewActivity_Sort_by)
|
.setTitle(R.string.MediaOverviewActivity_Sort_by)
|
||||||
.setSingleChoiceItems(R.array.MediaOverviewActivity_Sort_by,
|
.setSingleChoiceItems(R.array.MediaOverviewActivity_Sort_by,
|
||||||
currentSorting.ordinal(),
|
currentSorting.ordinal(),
|
||||||
|
@ -286,39 +287,33 @@ public final class MediaOverviewActivity extends PassphraseRequiredActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class OnTabSelectedListener implements TabLayout.OnTabSelectedListener {
|
private static final class NewTabListener implements ControllableTabLayout.NewTabListener {
|
||||||
|
@Override
|
||||||
|
public void onNewTab(@NonNull TabLayout.Tab tab) {
|
||||||
|
View customView = tab.getCustomView();
|
||||||
|
if (customView == null) {
|
||||||
|
tab.setCustomView(R.layout.media_overview_tab_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final Typeface tabUnselected = Typeface.create("sans-serif", Typeface.NORMAL);
|
private static final class OnTabSelectedListener implements TabLayout.OnTabSelectedListener {
|
||||||
private final Typeface tabSelected = Typeface.create("sans-serif-medium", Typeface.NORMAL);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabSelected(@NonNull TabLayout.Tab tab) {
|
public void onTabSelected(@NonNull TabLayout.Tab tab) {
|
||||||
View view = getCustomView(tab);
|
MediaOverviewTabItem view = (MediaOverviewTabItem) Objects.requireNonNull(tab.getCustomView());
|
||||||
TextView title = view.findViewById(android.R.id.text1);
|
view.select();
|
||||||
title.setTypeface(tabSelected);
|
|
||||||
title.setTextColor(ContextCompat.getColor(view.getContext(), R.color.signal_inverse_primary));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabUnselected(@NonNull TabLayout.Tab tab) {
|
public void onTabUnselected(@NonNull TabLayout.Tab tab) {
|
||||||
View view = getCustomView(tab);
|
MediaOverviewTabItem view = (MediaOverviewTabItem) Objects.requireNonNull(tab.getCustomView());
|
||||||
TextView title = view.findViewById(android.R.id.text1);
|
view.unselect();
|
||||||
title.setTypeface(tabUnselected);
|
|
||||||
title.setTextColor(ContextCompat.getColor(view.getContext(), R.color.signal_text_secondary));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabReselected(@NonNull TabLayout.Tab tab) {
|
public void onTabReselected(@NonNull TabLayout.Tab tab) {
|
||||||
// Intentionally Blank.
|
// Intentionally Blank.
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NonNull View getCustomView(@NonNull TabLayout.Tab tab) {
|
|
||||||
View customView = tab.getCustomView();
|
|
||||||
if (customView == null) {
|
|
||||||
tab.setCustomView(R.layout.custom_tab_layout_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tab.getCustomView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.thoughtcrime.securesms.mediaoverview
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.widget.doAfterTextChanged
|
||||||
|
import org.thoughtcrime.securesms.R
|
||||||
|
|
||||||
|
class MediaOverviewTabItem @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private lateinit var unselectedTextView: TextView
|
||||||
|
private lateinit var selectedTextView: TextView
|
||||||
|
|
||||||
|
override fun onFinishInflate() {
|
||||||
|
super.onFinishInflate()
|
||||||
|
|
||||||
|
unselectedTextView = findViewById(android.R.id.text1)
|
||||||
|
selectedTextView = findViewById(R.id.text1_bold)
|
||||||
|
|
||||||
|
unselectedTextView.doAfterTextChanged {
|
||||||
|
selectedTextView.text = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun select() {
|
||||||
|
unselectedTextView.alpha = 0f
|
||||||
|
selectedTextView.alpha = 1f
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unselect() {
|
||||||
|
unselectedTextView.alpha = 1f
|
||||||
|
selectedTextView.alpha = 0f
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@android:id/text1"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textAppearance="@style/TextAppearance.Signal.Body2"
|
|
||||||
android:maxLines="2"
|
|
||||||
tools:text="Media" />
|
|
30
app/src/main/res/layout/media_overview_tab_item.xml
Normal file
30
app/src/main/res/layout/media_overview_tab_item.xml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.thoughtcrime.securesms.mediaoverview.MediaOverviewTabItem xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="@style/TextAppearance.Signal.Body2"
|
||||||
|
android:textColor="@color/signal_text_secondary"
|
||||||
|
tools:text="Media" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text1_bold"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="0"
|
||||||
|
android:fontFamily="sans-serif-medium"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="@style/TextAppearance.Signal.Body2"
|
||||||
|
android:textColor="@color/signal_text_primary"
|
||||||
|
tools:text="Media" />
|
||||||
|
|
||||||
|
</org.thoughtcrime.securesms.mediaoverview.MediaOverviewTabItem>
|
Loading…
Add table
Reference in a new issue