diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2c563c2..474f732 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -53,11 +53,13 @@ android:theme="@style/AppTheme.NoActionBar"/> + android:label="@string/event_details" + android:theme="@style/AppTheme.NoActionBar"/> + android:parentActivityName=".activities.TrackScheduleActivity" + android:theme="@style/AppTheme.NoActionBar"> diff --git a/app/src/main/java/be/digitalia/fosdem/activities/EventDetailsActivity.java b/app/src/main/java/be/digitalia/fosdem/activities/EventDetailsActivity.java index f156531..b048825 100644 --- a/app/src/main/java/be/digitalia/fosdem/activities/EventDetailsActivity.java +++ b/app/src/main/java/be/digitalia/fosdem/activities/EventDetailsActivity.java @@ -1,15 +1,19 @@ package be.digitalia.fosdem.activities; import android.content.Intent; +import android.content.res.ColorStateList; import android.nfc.NdefRecord; import android.os.Bundle; +import android.view.View; +import android.widget.ImageButton; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import androidx.core.app.NavUtils; import androidx.core.app.TaskStackBuilder; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.Observer; @@ -17,10 +21,15 @@ import androidx.lifecycle.ViewModelProviders; import be.digitalia.fosdem.R; import be.digitalia.fosdem.fragments.EventDetailsFragment; import be.digitalia.fosdem.model.Event; +import be.digitalia.fosdem.model.Track; import be.digitalia.fosdem.utils.NfcUtils; import be.digitalia.fosdem.utils.NfcUtils.CreateNfcAppDataCallback; import be.digitalia.fosdem.utils.ThemeUtils; +import be.digitalia.fosdem.viewmodels.BookmarkStatusViewModel; import be.digitalia.fosdem.viewmodels.EventViewModel; +import be.digitalia.fosdem.widgets.BookmarkStatusAdapter; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.bottomappbar.BottomAppBar; /** * Displays a single event passed either as a complete Parcelable object in extras or as an id in data. @@ -31,16 +40,25 @@ public class EventDetailsActivity extends AppCompatActivity implements Observer< public static final String EXTRA_EVENT = "event"; + private AppBarLayout appBarLayout; + private Toolbar toolbar; + private BottomAppBar bottomAppBar; + + private BookmarkStatusViewModel bookmarkStatusViewModel; private Event event; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.content); + setContentView(R.layout.single_event); + appBarLayout = findViewById(R.id.appbar); + toolbar = findViewById(R.id.toolbar); + bottomAppBar = findViewById(R.id.bottom_appbar); + setSupportActionBar(bottomAppBar); - ActionBar bar = getSupportActionBar(); - bar.setDisplayHomeAsUpEnabled(false); - bar.setDisplayShowTitleEnabled(false); + ImageButton floatingActionButton = findViewById(R.id.fab); + bookmarkStatusViewModel = ViewModelProviders.of(this).get(BookmarkStatusViewModel.class); + BookmarkStatusAdapter.setupWithImageButton(bookmarkStatusViewModel, this, floatingActionButton); Event event = getIntent().getParcelableExtra(EXTRA_EVENT); @@ -94,14 +112,28 @@ public class EventDetailsActivity extends AppCompatActivity implements Observer< private void initEvent(@NonNull Event event) { this.event = event; // Enable up navigation only after getting the event details - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - ThemeUtils.setActionBarTrackColor(this, event.getTrack().getType()); + toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material); + toolbar.setNavigationContentDescription(R.string.abc_action_bar_up_description); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + navigateUp(); + } + }); + + final Track.Type trackType = event.getTrack().getType(); + ThemeUtils.setStatusBarTrackColor(this, trackType); + final ColorStateList trackColor = ContextCompat.getColorStateList(this, trackType.getColorResId()); + appBarLayout.setBackgroundColor(trackColor.getDefaultColor()); + bottomAppBar.setBackgroundTint(trackColor); + + bookmarkStatusViewModel.setEvent(event); + // Enable Android Beam NfcUtils.setAppDataPushMessageCallbackIfAvailable(this, this); } - @Override - public boolean onSupportNavigateUp() { + void navigateUp() { // Navigate up to the track associated with this event Intent upIntent = new Intent(this, TrackScheduleActivity.class); upIntent.putExtra(TrackScheduleActivity.EXTRA_DAY, event.getDay()); @@ -121,7 +153,6 @@ public class EventDetailsActivity extends AppCompatActivity implements Observer< startActivity(upIntent); finish(); } - return true; } // CreateNfcAppDataCallback diff --git a/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleActivity.java b/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleActivity.java index 9d176ad..1802d35 100644 --- a/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleActivity.java +++ b/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleActivity.java @@ -3,13 +3,15 @@ package be.digitalia.fosdem.activities; import android.content.Intent; import android.nfc.NdefRecord; import android.os.Bundle; -import android.widget.ImageView; +import android.widget.ImageButton; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.ViewModelProviders; import be.digitalia.fosdem.R; import be.digitalia.fosdem.fragments.EventDetailsFragment; import be.digitalia.fosdem.fragments.RoomImageDialogFragment; @@ -20,6 +22,8 @@ import be.digitalia.fosdem.model.Track; import be.digitalia.fosdem.utils.NfcUtils; import be.digitalia.fosdem.utils.NfcUtils.CreateNfcAppDataCallback; import be.digitalia.fosdem.utils.ThemeUtils; +import be.digitalia.fosdem.viewmodels.BookmarkStatusViewModel; +import be.digitalia.fosdem.widgets.BookmarkStatusAdapter; /** * Track Schedule container, works in both single pane and dual pane modes. @@ -27,9 +31,7 @@ import be.digitalia.fosdem.utils.ThemeUtils; * @author Christophe Beyls */ public class TrackScheduleActivity extends AppCompatActivity - implements TrackScheduleListFragment.Callbacks, - EventDetailsFragment.FloatingActionButtonProvider, - CreateNfcAppDataCallback { + implements TrackScheduleListFragment.Callbacks, CreateNfcAppDataCallback { public static final String EXTRA_DAY = "day"; public static final String EXTRA_TRACK = "track"; @@ -41,15 +43,14 @@ public class TrackScheduleActivity extends AppCompatActivity private boolean isTabletLandscape; private Event lastSelectedEvent; - private ImageView floatingActionButton; + private BookmarkStatusViewModel bookmarkStatusViewModel = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.track_schedule); - setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); - - floatingActionButton = findViewById(R.id.fab); + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); Bundle extras = getIntent().getExtras(); day = extras.getParcelable(EXTRA_DAY); @@ -60,7 +61,9 @@ public class TrackScheduleActivity extends AppCompatActivity bar.setTitle(track.toString()); bar.setSubtitle(day.toString()); setTitle(String.format("%1$s, %2$s", track.toString(), day.toString())); - ThemeUtils.setActionBarTrackColor(this, track.getType()); + ThemeUtils.setStatusBarTrackColor(this, track.getType()); + final int trackColor = ContextCompat.getColor(this, track.getType().getColorResId()); + toolbar.setBackgroundColor(trackColor); isTabletLandscape = getResources().getBoolean(R.bool.tablet_landscape); @@ -100,6 +103,12 @@ public class TrackScheduleActivity extends AppCompatActivity } if (isTabletLandscape) { + ImageButton floatingActionButton = findViewById(R.id.fab); + if (floatingActionButton != null) { + bookmarkStatusViewModel = ViewModelProviders.of(this).get(BookmarkStatusViewModel.class); + BookmarkStatusAdapter.setupWithImageButton(bookmarkStatusViewModel, this, floatingActionButton); + } + // Enable Android Beam NfcUtils.setAppDataPushMessageCallbackIfAvailable(this, this); } @@ -128,6 +137,10 @@ public class TrackScheduleActivity extends AppCompatActivity fm.beginTransaction().remove(currentFragment).commitAllowingStateLoss(); } } + + if (bookmarkStatusViewModel != null) { + bookmarkStatusViewModel.setEvent(event); + } } else { // Classic mode: Show event details in a new activity Intent intent = new Intent(this, TrackScheduleEventActivity.class); @@ -138,13 +151,6 @@ public class TrackScheduleActivity extends AppCompatActivity } } - // EventDetailsFragment.FloatingActionButtonProvider - - @Override - public ImageView getActionButton() { - return floatingActionButton; - } - // CreateNfcAppDataCallback @Override diff --git a/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleEventActivity.java b/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleEventActivity.java index 2e659bd..b659566 100644 --- a/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleEventActivity.java +++ b/app/src/main/java/be/digitalia/fosdem/activities/TrackScheduleEventActivity.java @@ -1,10 +1,12 @@ package be.digitalia.fosdem.activities; +import android.content.res.ColorStateList; import android.nfc.NdefRecord; import android.os.Bundle; import android.view.View; -import androidx.appcompat.app.ActionBar; +import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -21,9 +23,12 @@ import be.digitalia.fosdem.model.Track; import be.digitalia.fosdem.utils.NfcUtils; import be.digitalia.fosdem.utils.NfcUtils.CreateNfcAppDataCallback; import be.digitalia.fosdem.utils.ThemeUtils; +import be.digitalia.fosdem.viewmodels.BookmarkStatusViewModel; import be.digitalia.fosdem.viewmodels.TrackScheduleViewModel; +import be.digitalia.fosdem.widgets.BookmarkStatusAdapter; import be.digitalia.fosdem.widgets.ContentLoadingProgressBar; -import com.viewpagerindicator.UnderlinePageIndicator; +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.bottomappbar.BottomAppBar; import java.util.List; @@ -41,14 +46,18 @@ public class TrackScheduleEventActivity extends AppCompatActivity implements Obs private int initialPosition = -1; private ContentLoadingProgressBar progress; private ViewPager pager; - private UnderlinePageIndicator pageIndicator; - private TrackScheduleEventAdapter adapter; + TrackScheduleEventAdapter adapter; + + BookmarkStatusViewModel bookmarkStatusViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.track_schedule_event); + AppBarLayout appBarLayout = findViewById(R.id.appbar); + Toolbar toolbar = findViewById(R.id.toolbar); + BottomAppBar bottomAppBar = findViewById(R.id.bottom_appbar); + setSupportActionBar(bottomAppBar); Bundle extras = getIntent().getExtras(); final Day day = extras.getParcelable(EXTRA_DAY); @@ -57,26 +66,45 @@ public class TrackScheduleEventActivity extends AppCompatActivity implements Obs progress = findViewById(R.id.progress); pager = findViewById(R.id.pager); adapter = new TrackScheduleEventAdapter(getSupportFragmentManager()); - pageIndicator = findViewById(R.id.indicator); - pageIndicator.setSelectedColor(ContextCompat.getColor(this, track.getType().getColorResId())); if (savedInstanceState == null) { initialPosition = extras.getInt(EXTRA_POSITION, -1); } - ActionBar bar = getSupportActionBar(); - bar.setDisplayHomeAsUpEnabled(true); - bar.setTitle(track.toString()); - bar.setSubtitle(day.toString()); - ThemeUtils.setActionBarTrackColor(this, track.getType()); + toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material); + toolbar.setNavigationContentDescription(R.string.abc_action_bar_up_description); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + toolbar.setTitle(track.toString()); + toolbar.setSubtitle(day.toString()); + setTitle(String.format("%1$s, %2$s", track.toString(), day.toString())); + ThemeUtils.setStatusBarTrackColor(this, track.getType()); + final ColorStateList trackColor = ContextCompat.getColorStateList(this, track.getType().getColorResId()); + appBarLayout.setBackgroundColor(trackColor.getDefaultColor()); + bottomAppBar.setBackgroundTint(trackColor); - // Enable Android Beam - NfcUtils.setAppDataPushMessageCallbackIfAvailable(this, this); + // Monitor the currently displayed event to update the bookmark status in FAB + ImageButton floatingActionButton = findViewById(R.id.fab); + bookmarkStatusViewModel = ViewModelProviders.of(this).get(BookmarkStatusViewModel.class); + BookmarkStatusAdapter.setupWithImageButton(bookmarkStatusViewModel, this, floatingActionButton); + pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + bookmarkStatusViewModel.setEvent(adapter.getEvent(position)); + } + }); setCustomProgressVisibility(true); final TrackScheduleViewModel viewModel = ViewModelProviders.of(this).get(TrackScheduleViewModel.class); viewModel.setTrack(day, track); viewModel.getSchedule().observe(this, this); + + // Enable Android Beam + NfcUtils.setAppDataPushMessageCallbackIfAvailable(this, this); } private void setCustomProgressVisibility(boolean isVisible) { @@ -99,12 +127,6 @@ public class TrackScheduleEventActivity extends AppCompatActivity implements Obs return NfcUtils.createEventAppData(this, event); } - @Override - public boolean onSupportNavigateUp() { - finish(); - return true; - } - @Override public void onChanged(List schedule) { setCustomProgressVisibility(false); @@ -117,21 +139,25 @@ public class TrackScheduleEventActivity extends AppCompatActivity implements Obs // to ensure the current position is restored properly if (pager.getAdapter() == null) { pager.setAdapter(adapter); - pageIndicator.setViewPager(pager); - } - if (initialPosition != -1) { - pager.setCurrentItem(initialPosition, false); - initialPosition = -1; + if (initialPosition != -1) { + pager.setCurrentItem(initialPosition, false); + initialPosition = -1; + } + + final int currentPosition = pager.getCurrentItem(); + if (currentPosition >= 0) { + bookmarkStatusViewModel.setEvent(adapter.getEvent(currentPosition)); + } } } } - public static class TrackScheduleEventAdapter extends FragmentStatePagerAdapter { + private static class TrackScheduleEventAdapter extends FragmentStatePagerAdapter { private List events = null; - public TrackScheduleEventAdapter(FragmentManager fm) { + TrackScheduleEventAdapter(FragmentManager fm) { super(fm); } diff --git a/app/src/main/java/be/digitalia/fosdem/fragments/EventDetailsFragment.java b/app/src/main/java/be/digitalia/fosdem/fragments/EventDetailsFragment.java index 3d00d2e..6d15752 100644 --- a/app/src/main/java/be/digitalia/fosdem/fragments/EventDetailsFragment.java +++ b/app/src/main/java/be/digitalia/fosdem/fragments/EventDetailsFragment.java @@ -1,11 +1,8 @@ package be.digitalia.fosdem.fragments; -import android.annotation.SuppressLint; -import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; -import android.graphics.drawable.Animatable; import android.net.Uri; import android.os.Bundle; import android.provider.CalendarContract; @@ -13,10 +10,8 @@ import android.text.*; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.view.*; -import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.browser.customtabs.CustomTabsIntent; import androidx.core.app.ShareCompat; import androidx.core.content.ContextCompat; @@ -40,14 +35,6 @@ import java.util.Map; public class EventDetailsFragment extends Fragment { - /** - * Interface implemented by container activities - */ - public interface FloatingActionButtonProvider { - // May return null - ImageView getActionButton(); - } - static class ViewHolder { LayoutInflater inflater; TextView personsTextView; @@ -62,9 +49,6 @@ public class EventDetailsFragment extends Fragment { ViewHolder holder; EventDetailsViewModel viewModel; - private MenuItem bookmarkMenuItem; - private ImageView actionButton; - public static EventDetailsFragment newInstance(Event event) { EventDetailsFragment f = new EventDetailsFragment(); Bundle args = new Bundle(); @@ -79,6 +63,7 @@ public class EventDetailsFragment extends Fragment { event = getArguments().getParcelable(ARG_EVENT); viewModel = ViewModelProviders.of(this).get(EventDetailsViewModel.class); viewModel.setEvent(event); + setHasOptionsMenu(true); } public Event getEvent() { @@ -181,23 +166,6 @@ public class EventDetailsFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - Activity activity = getActivity(); - if (activity instanceof FloatingActionButtonProvider) { - actionButton = ((FloatingActionButtonProvider) activity).getActionButton(); - if (actionButton != null) { - actionButton.setOnClickListener(actionButtonClickListener); - } - } - - // Ensure the actionButton is initialized before creating the options menu - setHasOptionsMenu(true); - - viewModel.getBookmarkStatus().observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(@Nullable Boolean isBookmarked) { - updateBookmarkMenuItem(isBookmarked, true); - } - }); viewModel.getEventDetails().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(EventDetails eventDetails) { @@ -222,34 +190,16 @@ public class EventDetailsFragment extends Fragment { }); } - private final View.OnClickListener actionButtonClickListener = new View.OnClickListener() { - - @Override - public void onClick(View view) { - viewModel.toggleBookmarkStatus(); - } - }; - @Override public void onDestroyView() { super.onDestroyView(); holder = null; - if (actionButton != null) { - // Clear the reference to this fragment - actionButton.setOnClickListener(null); - actionButton = null; - } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.event, menu); menu.findItem(R.id.share).setIntent(getShareChooserIntent()); - bookmarkMenuItem = menu.findItem(R.id.bookmark); - if (actionButton != null) { - bookmarkMenuItem.setEnabled(false).setVisible(false); - } - updateBookmarkMenuItem(viewModel.getBookmarkStatus().getValue(), false); } private Intent getShareChooserIntent() { @@ -261,67 +211,9 @@ public class EventDetailsFragment extends Fragment { .createChooserIntent(); } - void updateBookmarkMenuItem(Boolean isBookmarked, boolean animate) { - if (actionButton != null) { - // Action Button is used as bookmark button - - if (isBookmarked == null) { - actionButton.setEnabled(false); - } else { - // Only animate if the button was showing a previous value - animate = animate && actionButton.isEnabled(); - actionButton.setEnabled(true); - - if (isBookmarked) { - actionButton.setContentDescription(getString(R.string.remove_bookmark)); - actionButton.setImageResource(animate ? R.drawable.avd_bookmark_add_24dp : R.drawable.ic_bookmark_white_24dp); - } else { - actionButton.setContentDescription(getString(R.string.add_bookmark)); - actionButton.setImageResource(animate ? R.drawable.avd_bookmark_remove_24dp : R.drawable.ic_bookmark_outline_white_24dp); - } - if (animate) { - ((Animatable) actionButton.getDrawable()).start(); - } - } - } else { - // Standard menu item is used as bookmark button - - if (bookmarkMenuItem != null) { - if (isBookmarked == null) { - bookmarkMenuItem.setEnabled(false); - } else { - // Only animate if the menu item was showing a previous value - animate = animate && bookmarkMenuItem.isEnabled(); - bookmarkMenuItem.setEnabled(true); - - if (isBookmarked) { - bookmarkMenuItem.setTitle(R.string.remove_bookmark); - bookmarkMenuItem.setIcon(animate ? R.drawable.avd_bookmark_add_24dp : R.drawable.ic_bookmark_white_24dp); - } else { - bookmarkMenuItem.setTitle(R.string.add_bookmark); - bookmarkMenuItem.setIcon(animate ? R.drawable.avd_bookmark_remove_24dp : R.drawable.ic_bookmark_outline_white_24dp); - } - if (animate) { - ((Animatable) bookmarkMenuItem.getIcon()).stop(); - ((Animatable) bookmarkMenuItem.getIcon()).start(); - } - } - } - } - } - - @Override - public void onDestroyOptionsMenu() { - super.onDestroyOptionsMenu(); - bookmarkMenuItem = null; - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.bookmark: - viewModel.toggleBookmarkStatus(); - return true; case R.id.add_to_agenda: addToAgenda(); return true; @@ -329,7 +221,6 @@ public class EventDetailsFragment extends Fragment { return false; } - @SuppressLint("InlinedApi") private void addToAgenda() { Intent intent = new Intent(Intent.ACTION_EDIT); intent.setType("vnd.android.cursor.item/event"); @@ -344,8 +235,7 @@ public class EventDetailsFragment extends Fragment { EventDetails details = viewModel.getEventDetails().getValue(); final int personsCount = (details == null) ? 0 : details.getPersons().size(); if (personsCount > 0) { - description = String.format("%1$s: %2$s\n\n%3$s", getResources().getQuantityString(R.plurals.speakers, personsCount), event.getPersonsSummary(), - description); + description = String.format("%1$s: %2$s\n\n%3$s", getResources().getQuantityString(R.plurals.speakers, personsCount), event.getPersonsSummary(), description); } intent.putExtra(CalendarContract.Events.DESCRIPTION, description); Date time = event.getStartTime(); diff --git a/app/src/main/java/be/digitalia/fosdem/model/BookmarkStatus.java b/app/src/main/java/be/digitalia/fosdem/model/BookmarkStatus.java new file mode 100644 index 0000000..99a7528 --- /dev/null +++ b/app/src/main/java/be/digitalia/fosdem/model/BookmarkStatus.java @@ -0,0 +1,20 @@ +package be.digitalia.fosdem.model; + +public class BookmarkStatus { + + private final boolean isBookmarked; + private final boolean isUpdate; + + public BookmarkStatus(boolean isBookmarked, boolean isUpdate) { + this.isBookmarked = isBookmarked; + this.isUpdate = isUpdate; + } + + public boolean isBookmarked() { + return isBookmarked; + } + + public boolean isUpdate() { + return isUpdate; + } +} diff --git a/app/src/main/java/be/digitalia/fosdem/utils/ThemeUtils.java b/app/src/main/java/be/digitalia/fosdem/utils/ThemeUtils.java index ac9010a..00f035f 100644 --- a/app/src/main/java/be/digitalia/fosdem/utils/ThemeUtils.java +++ b/app/src/main/java/be/digitalia/fosdem/utils/ThemeUtils.java @@ -1,24 +1,17 @@ package be.digitalia.fosdem.utils; +import android.app.Activity; import android.app.ActivityManager; -import android.graphics.drawable.ColorDrawable; import android.os.Build; - import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import be.digitalia.fosdem.model.Track; public class ThemeUtils { - @SuppressWarnings("deprecation") - public static void setActionBarTrackColor(@NonNull AppCompatActivity activity, @NonNull Track.Type trackType) { - ActionBar actionBar = activity.getSupportActionBar(); - final int color = ContextCompat.getColor(activity, trackType.getColorResId()); - actionBar.setBackgroundDrawable(new ColorDrawable(color)); - + public static void setStatusBarTrackColor(@NonNull Activity activity, @NonNull Track.Type trackType) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + final int color = ContextCompat.getColor(activity, trackType.getColorResId()); final int darkColor = ContextCompat.getColor(activity, trackType.getDarkColorResId()); activity.getWindow().setStatusBarColor(darkColor); final ActivityManager.TaskDescription taskDescription; diff --git a/app/src/main/java/be/digitalia/fosdem/viewmodels/BookmarkStatusViewModel.java b/app/src/main/java/be/digitalia/fosdem/viewmodels/BookmarkStatusViewModel.java new file mode 100644 index 0000000..afdd3d9 --- /dev/null +++ b/app/src/main/java/be/digitalia/fosdem/viewmodels/BookmarkStatusViewModel.java @@ -0,0 +1,83 @@ +package be.digitalia.fosdem.viewmodels; + +import android.app.Application; +import android.os.AsyncTask; +import androidx.annotation.NonNull; +import androidx.arch.core.util.Function; +import androidx.core.util.ObjectsCompat; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; +import be.digitalia.fosdem.db.AppDatabase; +import be.digitalia.fosdem.livedata.ExtraTransformations; +import be.digitalia.fosdem.model.BookmarkStatus; +import be.digitalia.fosdem.model.Event; + +public class BookmarkStatusViewModel extends AndroidViewModel { + + private final AppDatabase appDatabase = AppDatabase.getInstance(getApplication()); + private final MutableLiveData event = new MutableLiveData<>(); + private final LiveData bookmarkStatus = Transformations.switchMap(event, + new Function>() { + @Override + public LiveData apply(Event event) { + if (event == null) { + MutableLiveData singleNullResult = new MutableLiveData<>(); + singleNullResult.setValue(null); + return singleNullResult; + } + + return Transformations.map( + // Prevent updating the UI when a bookmark is added back or removed back + ExtraTransformations.distinctUntilChanged( + appDatabase.getBookmarksDao().getBookmarkStatus(event) + ), new Function() { + @Override + public BookmarkStatus apply(Boolean isBookmarked) { + if (isBookmarked == null) { + return null; + } + final boolean isUpdate = firstResultReceived; + firstResultReceived = true; + return new BookmarkStatus(isBookmarked, isUpdate); + } + } + ); + } + }); + private boolean firstResultReceived = false; + + public BookmarkStatusViewModel(@NonNull Application application) { + super(application); + } + + public void setEvent(Event event) { + if (!ObjectsCompat.equals(event, this.event.getValue())) { + firstResultReceived = false; + this.event.setValue(event); + } + } + + public LiveData getBookmarkStatus() { + return bookmarkStatus; + } + + public void toggleBookmarkStatus() { + final Event event = this.event.getValue(); + final BookmarkStatus currentStatus = bookmarkStatus.getValue(); + // Ignore the action if the status for the current event hasn't been received yet + if (event != null && currentStatus != null && firstResultReceived) { + AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + if (currentStatus.isBookmarked()) { + appDatabase.getBookmarksDao().removeBookmark(event); + } else { + appDatabase.getBookmarksDao().addBookmark(event); + } + } + }); + } + } +} diff --git a/app/src/main/java/be/digitalia/fosdem/viewmodels/EventDetailsViewModel.java b/app/src/main/java/be/digitalia/fosdem/viewmodels/EventDetailsViewModel.java index 05cca13..955e437 100644 --- a/app/src/main/java/be/digitalia/fosdem/viewmodels/EventDetailsViewModel.java +++ b/app/src/main/java/be/digitalia/fosdem/viewmodels/EventDetailsViewModel.java @@ -1,7 +1,6 @@ package be.digitalia.fosdem.viewmodels; import android.app.Application; -import android.os.AsyncTask; import androidx.annotation.NonNull; import androidx.arch.core.util.Function; import androidx.lifecycle.AndroidViewModel; @@ -9,7 +8,6 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Transformations; import be.digitalia.fosdem.db.AppDatabase; -import be.digitalia.fosdem.livedata.ExtraTransformations; import be.digitalia.fosdem.model.Event; import be.digitalia.fosdem.model.EventDetails; @@ -17,16 +15,6 @@ public class EventDetailsViewModel extends AndroidViewModel { private final AppDatabase appDatabase = AppDatabase.getInstance(getApplication()); private final MutableLiveData event = new MutableLiveData<>(); - private final LiveData bookmarkStatus = Transformations.switchMap(event, - new Function>() { - @Override - public LiveData apply(Event event) { - // Prevent animating the UI when a bookmark is added back or removed back - return ExtraTransformations.distinctUntilChanged( - appDatabase.getBookmarksDao().getBookmarkStatus(event) - ); - } - }); private final LiveData eventDetails = Transformations.switchMap(event, new Function>() { @Override @@ -45,27 +33,6 @@ public class EventDetailsViewModel extends AndroidViewModel { } } - public LiveData getBookmarkStatus() { - return bookmarkStatus; - } - - public void toggleBookmarkStatus() { - final Event event = this.event.getValue(); - final Boolean isBookmarked = bookmarkStatus.getValue(); - if (event != null && isBookmarked != null) { - AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() { - @Override - public void run() { - if (isBookmarked) { - appDatabase.getBookmarksDao().removeBookmark(event); - } else { - appDatabase.getBookmarksDao().addBookmark(event); - } - } - }); - } - } - public LiveData getEventDetails() { return eventDetails; } diff --git a/app/src/main/java/be/digitalia/fosdem/widgets/BookmarkStatusAdapter.java b/app/src/main/java/be/digitalia/fosdem/widgets/BookmarkStatusAdapter.java new file mode 100644 index 0000000..0a41362 --- /dev/null +++ b/app/src/main/java/be/digitalia/fosdem/widgets/BookmarkStatusAdapter.java @@ -0,0 +1,56 @@ +package be.digitalia.fosdem.widgets; + +import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.ImageButton; +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.Observer; +import be.digitalia.fosdem.R; +import be.digitalia.fosdem.model.BookmarkStatus; +import be.digitalia.fosdem.viewmodels.BookmarkStatusViewModel; + +public class BookmarkStatusAdapter { + + private BookmarkStatusAdapter() { + } + + /** + * Connect an ImageButton to a BookmarkStatusViewModel + * to update its icon according to the current status and trigger a bookmark toggle on click. + */ + public static void setupWithImageButton(@NonNull final BookmarkStatusViewModel viewModel, @NonNull LifecycleOwner owner, + @NonNull final ImageButton imageButton) { + imageButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + viewModel.toggleBookmarkStatus(); + } + }); + viewModel.getBookmarkStatus().observe(owner, new Observer() { + @Override + public void onChanged(BookmarkStatus bookmarkStatus) { + if (bookmarkStatus == null) { + imageButton.setEnabled(false); + imageButton.setImageResource(R.drawable.ic_bookmark_outline_white_24dp); + } else { + // Only animate updates, when the button was already enabled + final boolean animate = bookmarkStatus.isUpdate() && imageButton.isEnabled(); + imageButton.setEnabled(true); + if (bookmarkStatus.isBookmarked()) { + imageButton.setContentDescription(imageButton.getContext().getString(R.string.remove_bookmark)); + imageButton.setImageResource(animate ? R.drawable.avd_bookmark_add_24dp : R.drawable.ic_bookmark_white_24dp); + } else { + imageButton.setContentDescription(imageButton.getContext().getString(R.string.add_bookmark)); + imageButton.setImageResource(animate ? R.drawable.avd_bookmark_remove_24dp : R.drawable.ic_bookmark_outline_white_24dp); + } + final Drawable drawable = imageButton.getDrawable(); + if (drawable instanceof Animatable) { + ((Animatable) drawable).start(); + } + } + } + }); + } +} diff --git a/app/src/main/java/com/viewpagerindicator/PageIndicator.java b/app/src/main/java/com/viewpagerindicator/PageIndicator.java deleted file mode 100644 index a4ff396..0000000 --- a/app/src/main/java/com/viewpagerindicator/PageIndicator.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2011 Patrik Akerfeldt - * Copyright (C) 2011 Jake Wharton - * - * 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 com.viewpagerindicator; - -import androidx.viewpager.widget.ViewPager; - -/** - * A PageIndicator is responsible to show an visual indicator on the total views - * number and the current visible view. - */ -public interface PageIndicator extends ViewPager.OnPageChangeListener { - /** - * Bind the indicator to a ViewPager. - * - * @param view - */ - void setViewPager(ViewPager view); - - /** - * Bind the indicator to a ViewPager. - * - * @param view - * @param initialPosition - */ - void setViewPager(ViewPager view, int initialPosition); - - /** - *

Set the current page of both the ViewPager and indicator.

- * - *

This must be used if you need to set the page before - * the views are drawn on screen (e.g., default start page).

- * - * @param item - */ - void setCurrentItem(int item); - - /** - * Notify the indicator that the fragment list has changed. - */ - void notifyDataSetChanged(); -} diff --git a/app/src/main/java/com/viewpagerindicator/UnderlinePageIndicator.java b/app/src/main/java/com/viewpagerindicator/UnderlinePageIndicator.java deleted file mode 100644 index f279bdd..0000000 --- a/app/src/main/java/com/viewpagerindicator/UnderlinePageIndicator.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2012 Jake Wharton - * - * 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 com.viewpagerindicator; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.drawable.Drawable; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -import androidx.annotation.NonNull; -import androidx.core.view.ViewCompat; -import androidx.viewpager.widget.ViewPager; -import be.digitalia.fosdem.R; - -/** - * Draws a line for each page. The current page line is colored differently - * than the unselected page lines. - */ -public class UnderlinePageIndicator extends View implements PageIndicator { - private static final int INVALID_POINTER = -1; - static final int FADE_FRAME_MS = 30; - - final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - - boolean mFades; - private int mFadeDelay; - private int mFadeLength; - int mFadeBy; - - private ViewPager mViewPager; - private int mScrollState; - private int mCurrentPage; - private float mPositionOffset; - - private int mTouchSlop; - private float mLastMotionX = -1; - private int mActivePointerId = INVALID_POINTER; - private boolean mIsDragging; - - final Runnable mFadeRunnable = new Runnable() { - @Override public void run() { - if (!mFades) return; - - final int alpha = Math.max(mPaint.getAlpha() - mFadeBy, 0); - mPaint.setAlpha(alpha); - invalidate(); - if (alpha > 0) { - postDelayed(this, FADE_FRAME_MS); - } - } - }; - - public UnderlinePageIndicator(Context context) { - this(context, null); - } - - public UnderlinePageIndicator(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.vpiUnderlinePageIndicatorStyle); - } - - public UnderlinePageIndicator(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - if (isInEditMode()) return; - - //Retrieve styles attributes - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UnderlinePageIndicator, defStyle, R.style.UnderlinePageIndicator); - - setFades(a.getBoolean(R.styleable.UnderlinePageIndicator_fades, false)); - setSelectedColor(a.getColor(R.styleable.UnderlinePageIndicator_selectedColor, 0)); - setFadeDelay(a.getInteger(R.styleable.UnderlinePageIndicator_fadeDelay, 0)); - setFadeLength(a.getInteger(R.styleable.UnderlinePageIndicator_fadeLength, 0)); - - Drawable background = a.getDrawable(R.styleable.UnderlinePageIndicator_android_background); - if (background != null) { - ViewCompat.setBackground(this, background); - } - - a.recycle(); - - mTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop(); - } - - public boolean getFades() { - return mFades; - } - - public void setFades(boolean fades) { - if (fades != mFades) { - mFades = fades; - if (fades) { - post(mFadeRunnable); - } else { - removeCallbacks(mFadeRunnable); - mPaint.setAlpha(0xFF); - invalidate(); - } - } - } - - public int getFadeDelay() { - return mFadeDelay; - } - - public void setFadeDelay(int fadeDelay) { - mFadeDelay = fadeDelay; - } - - public int getFadeLength() { - return mFadeLength; - } - - public void setFadeLength(int fadeLength) { - mFadeLength = fadeLength; - mFadeBy = 0xFF / (mFadeLength / FADE_FRAME_MS); - } - - public int getSelectedColor() { - return mPaint.getColor(); - } - - public void setSelectedColor(int selectedColor) { - mPaint.setColor(selectedColor); - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (mViewPager == null) { - return; - } - final int count = mViewPager.getAdapter().getCount(); - if (count == 0) { - return; - } - - if (mCurrentPage >= count) { - setCurrentItem(count - 1); - return; - } - - final int paddingLeft = getPaddingLeft(); - final float pageWidth = (getWidth() - paddingLeft - getPaddingRight()) / (1f * count); - final float left = paddingLeft + pageWidth * (mCurrentPage + mPositionOffset); - final float right = left + pageWidth; - final float top = getPaddingTop(); - final float bottom = getHeight() - getPaddingBottom(); - canvas.drawRect(left, top, right, bottom, mPaint); - } - - @Override - public boolean onTouchEvent(@NonNull MotionEvent ev) { - if (super.onTouchEvent(ev)) { - return true; - } - if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { - return false; - } - - final int action = ev.getAction() & MotionEvent.ACTION_MASK; - switch (action) { - case MotionEvent.ACTION_DOWN: - mActivePointerId = ev.getPointerId(0); - mLastMotionX = ev.getX(); - break; - - case MotionEvent.ACTION_MOVE: { - final int activePointerIndex = ev.findPointerIndex(mActivePointerId); - final float x = ev.getX(activePointerIndex); - final float deltaX = x - mLastMotionX; - - if (!mIsDragging) { - if (Math.abs(deltaX) > mTouchSlop) { - mIsDragging = true; - } - } - - if (mIsDragging) { - mLastMotionX = x; - if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { - mViewPager.fakeDragBy(deltaX); - } - } - - break; - } - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - if (!mIsDragging) { - final int count = mViewPager.getAdapter().getCount(); - final int width = getWidth(); - final float halfWidth = width / 2f; - final float sixthWidth = width / 6f; - - if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { - if (action != MotionEvent.ACTION_CANCEL) { - mViewPager.setCurrentItem(mCurrentPage - 1); - } - return true; - } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { - if (action != MotionEvent.ACTION_CANCEL) { - mViewPager.setCurrentItem(mCurrentPage + 1); - } - return true; - } - } - - mIsDragging = false; - mActivePointerId = INVALID_POINTER; - if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); - break; - - case MotionEvent.ACTION_POINTER_DOWN: { - final int index = ev.getActionIndex(); - mLastMotionX = ev.getX(index); - mActivePointerId = ev.getPointerId(index); - break; - } - - case MotionEvent.ACTION_POINTER_UP: - final int pointerIndex = ev.getActionIndex(); - final int pointerId = ev.getPointerId(pointerIndex); - if (pointerId == mActivePointerId) { - final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mActivePointerId = ev.getPointerId(newPointerIndex); - } - mLastMotionX = ev.getX(ev.findPointerIndex(mActivePointerId)); - break; - } - - return true; - } - - @Override - public void setViewPager(ViewPager viewPager) { - if (mViewPager == viewPager) { - return; - } - if (mViewPager != null) { - //Clear us from the old pager. - mViewPager.removeOnPageChangeListener(this); - } - if (viewPager.getAdapter() == null) { - throw new IllegalStateException("ViewPager does not have adapter instance."); - } - mViewPager = viewPager; - mViewPager.addOnPageChangeListener(this); - invalidate(); - post(new Runnable() { - @Override public void run() { - if (mFades) { - post(mFadeRunnable); - } - } - }); - } - - @Override - public void setViewPager(ViewPager view, int initialPosition) { - setViewPager(view); - setCurrentItem(initialPosition); - } - - @Override - public void setCurrentItem(int item) { - if (mViewPager == null) { - throw new IllegalStateException("ViewPager has not been bound."); - } - mViewPager.setCurrentItem(item); - mCurrentPage = item; - invalidate(); - } - - @Override - public void notifyDataSetChanged() { - invalidate(); - } - - @Override - public void onPageScrollStateChanged(int state) { - mScrollState = state; - } - - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - mCurrentPage = position; - mPositionOffset = positionOffset; - if (mFades) { - if (positionOffsetPixels > 0) { - removeCallbacks(mFadeRunnable); - mPaint.setAlpha(0xFF); - } else if (mScrollState != ViewPager.SCROLL_STATE_DRAGGING) { - postDelayed(mFadeRunnable, mFadeDelay); - } - } - invalidate(); - } - - @Override - public void onPageSelected(int position) { - if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { - mCurrentPage = position; - mPositionOffset = 0; - invalidate(); - mFadeRunnable.run(); - } - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState savedState = (SavedState)state; - super.onRestoreInstanceState(savedState.getSuperState()); - mCurrentPage = savedState.currentPage; - requestLayout(); - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - SavedState savedState = new SavedState(superState); - savedState.currentPage = mCurrentPage; - return savedState; - } - - static class SavedState extends BaseSavedState { - int currentPage; - - public SavedState(Parcelable superState) { - super(superState); - } - - SavedState(Parcel in) { - super(in); - currentPage = in.readInt(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(currentPage); - } - - public static final Creator CREATOR = new Creator() { - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } -} \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp-land/track_schedule.xml b/app/src/main/res/layout-sw600dp-land/track_schedule.xml index 32ce480..739548d 100644 --- a/app/src/main/res/layout-sw600dp-land/track_schedule.xml +++ b/app/src/main/res/layout-sw600dp-land/track_schedule.xml @@ -18,7 +18,7 @@ style="@style/Toolbar.Fosdem" android:layout_width="match_parent" android:layout_height="128dp" - android:elevation="4dp" + android:elevation="@dimen/toolbar_elevation" android:gravity="top" /> + app:layout_anchorGravity="bottom|end" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_event_details.xml b/app/src/main/res/layout/fragment_event_details.xml index 3a2af92..41384a9 100644 --- a/app/src/main/res/layout/fragment_event_details.xml +++ b/app/src/main/res/layout/fragment_event_details.xml @@ -1,15 +1,17 @@ - + + android:orientation="vertical" + android:paddingBottom="@dimen/detail_bottom_padding"> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/single_event.xml b/app/src/main/res/layout/single_event.xml new file mode 100644 index 0000000..2f8a996 --- /dev/null +++ b/app/src/main/res/layout/single_event.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/track_schedule_event.xml b/app/src/main/res/layout/track_schedule_event.xml index 003cc9e..870db68 100644 --- a/app/src/main/res/layout/track_schedule_event.xml +++ b/app/src/main/res/layout/track_schedule_event.xml @@ -1,7 +1,24 @@ - + + + + + + + + android:visibility="gone" /> + android:layout_marginBottom="?attr/actionBarSize" + android:visibility="gone" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - + android:layout_height="?attr/actionBarSize" + android:layout_gravity="bottom" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" + app:backgroundTint="?attr/colorPrimary" + app:fabAlignmentMode="end" /> - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/menu/event.xml b/app/src/main/res/menu/event.xml index bbcaee0..e42ac57 100644 --- a/app/src/main/res/menu/event.xml +++ b/app/src/main/res/menu/event.xml @@ -1,21 +1,16 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - + app:showAsAction="ifRoom" /> + app:showAsAction="ifRoom" /> \ No newline at end of file diff --git a/app/src/main/res/values-sw600dp-land/dimens.xml b/app/src/main/res/values-sw600dp-land/dimens.xml new file mode 100644 index 0000000..4af3b70 --- /dev/null +++ b/app/src/main/res/values-sw600dp-land/dimens.xml @@ -0,0 +1,6 @@ + + + + 0dp + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 7cb7b61..7223ff2 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,8 +6,9 @@ 32dp 8dp 16dp - 8dp + 4dp 360dp + 12dp 6dp diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 1cbd170..546e1a8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -70,6 +70,14 @@ @android:color/white + + - - \ No newline at end of file