mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-22 07:48:26 +00:00
Add empty state for conversation list
This commit is contained in:
parent
90ff0e58b0
commit
3097c2855e
BIN
res/drawable-hdpi/conversation_list_empty_state.png
Normal file
BIN
res/drawable-hdpi/conversation_list_empty_state.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
res/drawable-mdpi/conversation_list_empty_state.png
Normal file
BIN
res/drawable-mdpi/conversation_list_empty_state.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
res/drawable-xhdpi/conversation_list_empty_state.png
Normal file
BIN
res/drawable-xhdpi/conversation_list_empty_state.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
res/drawable-xxhdpi/conversation_list_empty_state.png
Normal file
BIN
res/drawable-xxhdpi/conversation_list_empty_state.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
BIN
res/drawable-xxxhdpi/conversation_list_empty_state.png
Normal file
BIN
res/drawable-xxxhdpi/conversation_list_empty_state.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -3,11 +3,30 @@
|
|||||||
<android.support.design.widget.CoordinatorLayout
|
<android.support.design.widget.CoordinatorLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:fab="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout android:id="@+id/empty_state"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView android:id="@+id/empty"
|
||||||
|
android:src="@drawable/conversation_list_empty_state"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
<TextView android:text="@string/conversation_list_fragment__give_your_inbox_something_to_write_home_about_get_started_by_messaging_a_friend"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<LinearLayout android:layout_width="match_parent"
|
<LinearLayout android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -28,7 +47,8 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
|
||||||
|
<org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton
|
||||||
android:id="@+id/fab"
|
android:id="@+id/fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -38,4 +58,5 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:contentDescription="@string/conversation_list_fragment__fab_content_description"/>
|
android:contentDescription="@string/conversation_list_fragment__fab_content_description"/>
|
||||||
|
|
||||||
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
@ -1490,6 +1490,7 @@
|
|||||||
<string name="recipient_preference_activity__shared_media">Shared media</string>
|
<string name="recipient_preference_activity__shared_media">Shared media</string>
|
||||||
<string name="registration_activity__verify_your_number">Verify Your Number</string>
|
<string name="registration_activity__verify_your_number">Verify Your Number</string>
|
||||||
<string name="registration_activity__please_enter_your_mobile_number_to_receive_a_verification_code_carrier_rates_may_apply">Please enter your mobile number to receive a verification code. Carrier rates may apply.</string>
|
<string name="registration_activity__please_enter_your_mobile_number_to_receive_a_verification_code_carrier_rates_may_apply">Please enter your mobile number to receive a verification code. Carrier rates may apply.</string>
|
||||||
|
<string name="conversation_list_fragment__give_your_inbox_something_to_write_home_about_get_started_by_messaging_a_friend">Give your inbox something to write home about. Get started by messaging a friend.</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- EOF -->
|
<!-- EOF -->
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -31,7 +31,6 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
@ -48,11 +47,11 @@ import android.view.Menu;
|
|||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
|
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
|
||||||
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
||||||
|
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
|
||||||
import org.thoughtcrime.securesms.components.reminder.DefaultSmsReminder;
|
import org.thoughtcrime.securesms.components.reminder.DefaultSmsReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.DozeReminder;
|
import org.thoughtcrime.securesms.components.reminder.DozeReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
|
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
|
||||||
@ -60,7 +59,6 @@ import org.thoughtcrime.securesms.components.reminder.OutdatedBuildReminder;
|
|||||||
import org.thoughtcrime.securesms.components.reminder.PushRegistrationReminder;
|
import org.thoughtcrime.securesms.components.reminder.PushRegistrationReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.Reminder;
|
import org.thoughtcrime.securesms.components.reminder.Reminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.ReminderView;
|
import org.thoughtcrime.securesms.components.reminder.ReminderView;
|
||||||
import org.thoughtcrime.securesms.components.reminder.ReminderView.OnDismissListener;
|
|
||||||
import org.thoughtcrime.securesms.components.reminder.ShareReminder;
|
import org.thoughtcrime.securesms.components.reminder.ShareReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder;
|
import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
@ -92,7 +90,8 @@ public class ConversationListFragment extends Fragment
|
|||||||
private ActionMode actionMode;
|
private ActionMode actionMode;
|
||||||
private RecyclerView list;
|
private RecyclerView list;
|
||||||
private ReminderView reminderView;
|
private ReminderView reminderView;
|
||||||
private FloatingActionButton fab;
|
private View emptyState;
|
||||||
|
private PulsingFloatingActionButton fab;
|
||||||
private Locale locale;
|
private Locale locale;
|
||||||
private String queryFilter = "";
|
private String queryFilter = "";
|
||||||
private boolean archive;
|
private boolean archive;
|
||||||
@ -112,16 +111,12 @@ public class ConversationListFragment extends Fragment
|
|||||||
reminderView = ViewUtil.findById(view, R.id.reminder);
|
reminderView = ViewUtil.findById(view, R.id.reminder);
|
||||||
list = ViewUtil.findById(view, R.id.list);
|
list = ViewUtil.findById(view, R.id.list);
|
||||||
fab = ViewUtil.findById(view, R.id.fab);
|
fab = ViewUtil.findById(view, R.id.fab);
|
||||||
|
emptyState = ViewUtil.findById(view, R.id.empty_state);
|
||||||
|
|
||||||
if (archive) fab.setVisibility(View.GONE);
|
if (archive) fab.setVisibility(View.GONE);
|
||||||
else fab.setVisibility(View.VISIBLE);
|
else fab.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
reminderView.setOnDismissListener(new OnDismissListener() {
|
reminderView.setOnDismissListener(this::updateReminders);
|
||||||
@Override
|
|
||||||
public void onDismiss() {
|
|
||||||
updateReminders();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
list.setHasFixedSize(true);
|
list.setHasFixedSize(true);
|
||||||
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
@ -137,12 +132,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
super.onActivityCreated(bundle);
|
super.onActivityCreated(bundle);
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
fab.setOnClickListener(new OnClickListener() {
|
fab.setOnClickListener(v -> startActivity(new Intent(getActivity(), NewConversationActivity.class)));
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
startActivity(new Intent(getActivity(), NewConversationActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
initializeListAdapter();
|
initializeListAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +144,13 @@ public class ConversationListFragment extends Fragment
|
|||||||
list.getAdapter().notifyDataSetChanged();
|
list.getAdapter().notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
fab.stopPulse();
|
||||||
|
}
|
||||||
|
|
||||||
public ConversationListAdapter getListAdapter() {
|
public ConversationListAdapter getListAdapter() {
|
||||||
return (ConversationListAdapter) list.getAdapter();
|
return (ConversationListAdapter) list.getAdapter();
|
||||||
}
|
}
|
||||||
@ -169,6 +166,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
private void updateReminders() {
|
private void updateReminders() {
|
||||||
reminderView.hide();
|
reminderView.hide();
|
||||||
new AsyncTask<Context, Void, Optional<? extends Reminder>>() {
|
new AsyncTask<Context, Void, Optional<? extends Reminder>>() {
|
||||||
@ -206,6 +204,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
getLoaderManager().restartLoader(0, null, this);
|
getLoaderManager().restartLoader(0, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
private void handleArchiveAllSelected() {
|
private void handleArchiveAllSelected() {
|
||||||
final Set<Long> selectedConversations = new HashSet<>(getListAdapter().getBatchSelections());
|
final Set<Long> selectedConversations = new HashSet<>(getListAdapter().getBatchSelections());
|
||||||
final boolean archive = this.archive;
|
final boolean archive = this.archive;
|
||||||
@ -252,6 +251,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
private void handleDeleteAllSelected() {
|
private void handleDeleteAllSelected() {
|
||||||
int conversationsCount = getListAdapter().getBatchSelections().size();
|
int conversationsCount = getListAdapter().getBatchSelections().size();
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
||||||
@ -262,9 +262,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
conversationsCount, conversationsCount));
|
conversationsCount, conversationsCount));
|
||||||
alert.setCancelable(true);
|
alert.setCancelable(true);
|
||||||
|
|
||||||
alert.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
alert.setPositiveButton(R.string.delete, (dialog, which) -> {
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
final Set<Long> selectedConversations = (getListAdapter())
|
final Set<Long> selectedConversations = (getListAdapter())
|
||||||
.getBatchSelections();
|
.getBatchSelections();
|
||||||
|
|
||||||
@ -297,7 +295,6 @@ public class ConversationListFragment extends Fragment
|
|||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
alert.setNegativeButton(android.R.string.cancel, null);
|
alert.setNegativeButton(android.R.string.cancel, null);
|
||||||
@ -307,7 +304,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
private void handleSelectAllThreads() {
|
private void handleSelectAllThreads() {
|
||||||
getListAdapter().selectAllThreads();
|
getListAdapter().selectAllThreads();
|
||||||
actionMode.setSubtitle(getString(R.string.conversation_fragment_cab__batch_selection_amount,
|
actionMode.setSubtitle(getString(R.string.conversation_fragment_cab__batch_selection_amount,
|
||||||
getListAdapter().getBatchSelections().size()));
|
String.valueOf(getListAdapter().getBatchSelections().size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
|
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
|
||||||
@ -321,6 +318,16 @@ public class ConversationListFragment extends Fragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
|
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
|
||||||
|
if (cursor == null || cursor.getCount() <= 0) {
|
||||||
|
list.setVisibility(View.INVISIBLE);
|
||||||
|
emptyState.setVisibility(View.VISIBLE);
|
||||||
|
fab.startPulse(3 * 1000);
|
||||||
|
} else {
|
||||||
|
list.setVisibility(View.VISIBLE);
|
||||||
|
emptyState.setVisibility(View.GONE);
|
||||||
|
fab.stopPulse();
|
||||||
|
}
|
||||||
|
|
||||||
getListAdapter().changeCursor(cursor);
|
getListAdapter().changeCursor(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +349,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
actionMode.finish();
|
actionMode.finish();
|
||||||
} else {
|
} else {
|
||||||
actionMode.setSubtitle(getString(R.string.conversation_fragment_cab__batch_selection_amount,
|
actionMode.setSubtitle(getString(R.string.conversation_fragment_cab__batch_selection_amount,
|
||||||
adapter.getBatchSelections().size()));
|
String.valueOf(adapter.getBatchSelections().size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
@ -378,7 +385,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
inflater.inflate(R.menu.conversation_list_batch, menu);
|
inflater.inflate(R.menu.conversation_list_batch, menu);
|
||||||
|
|
||||||
mode.setTitle(R.string.conversation_fragment_cab__batch_selection_mode);
|
mode.setTitle(R.string.conversation_fragment_cab__batch_selection_mode);
|
||||||
mode.setSubtitle(getString(R.string.conversation_fragment_cab__batch_selection_amount, 1));
|
mode.setSubtitle(getString(R.string.conversation_fragment_cab__batch_selection_amount, "1"));
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||||
@ -418,7 +425,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
|
|
||||||
private class ArchiveListenerCallback extends ItemTouchHelper.SimpleCallback {
|
private class ArchiveListenerCallback extends ItemTouchHelper.SimpleCallback {
|
||||||
|
|
||||||
public ArchiveListenerCallback() {
|
ArchiveListenerCallback() {
|
||||||
super(0, ItemTouchHelper.RIGHT);
|
super(0, ItemTouchHelper.RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,6 +450,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
return super.getSwipeDirs(recyclerView, viewHolder);
|
return super.getSwipeDirs(recyclerView, viewHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
@Override
|
@Override
|
||||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||||
final long threadId = ((ConversationListItem)viewHolder.itemView).getThreadId();
|
final long threadId = ((ConversationListItem)viewHolder.itemView).getThreadId();
|
||||||
@ -524,11 +532,9 @@ public class ConversationListFragment extends Fragment
|
|||||||
p);
|
p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 11) {
|
|
||||||
float alpha = 1.0f - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
|
float alpha = 1.0f - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
|
||||||
viewHolder.itemView.setAlpha(alpha);
|
viewHolder.itemView.setAlpha(alpha);
|
||||||
viewHolder.itemView.setTranslationX(dX);
|
viewHolder.itemView.setTranslationX(dX);
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package org.thoughtcrime.securesms.components.registration;
|
||||||
|
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||||
|
|
||||||
|
public class PulsingFloatingActionButton extends FloatingActionButton {
|
||||||
|
|
||||||
|
private boolean pulsing;
|
||||||
|
|
||||||
|
public PulsingFloatingActionButton(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PulsingFloatingActionButton(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PulsingFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startPulse(long periodMillis) {
|
||||||
|
if (!pulsing) {
|
||||||
|
pulsing = true;
|
||||||
|
pulse(periodMillis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopPulse() {
|
||||||
|
pulsing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pulse(long periodMillis) {
|
||||||
|
if (!pulsing) return;
|
||||||
|
|
||||||
|
this.animate().scaleX(1.2f).scaleY(1.2f).setDuration(150).setListener(new AnimationCompleteListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
clearAnimation();
|
||||||
|
animate().scaleX(1.0f).scaleY(1.0f).setDuration(150).setListener(new AnimationCompleteListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
PulsingFloatingActionButton.this.postDelayed(() -> pulse(periodMillis), periodMillis);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user