From 961a6b0c8e834e3bc957ddcdc86e7260f0bcf89d Mon Sep 17 00:00:00 2001 From: Christophe Beyls Date: Sun, 16 Dec 2018 19:47:20 +0100 Subject: [PATCH] Replace custom widgets with Material components for SnackBar, NavigationView, FAB and TabLayout --- app/build.gradle | 1 + .../fosdem/activities/MainActivity.java | 266 ++++------- .../fragments/EventDetailsFragment.java | 5 +- .../fosdem/fragments/LiveFragment.java | 9 +- .../fosdem/fragments/TracksFragment.java | 9 +- .../fosdem/widgets/AdapterLinearLayout.java | 115 ----- .../widgets/ForegroundLinearLayout.java | 230 ---------- .../widgets/ScrimInsetsFrameLayout.java | 116 ----- .../fosdem/widgets/SlidingTabLayout.java | 424 ------------------ .../main/res/animator-v21/fab_state_list.xml | 19 - app/src/main/res/drawable/fab_background.xml | 10 - .../drawable/fab_background_highlighted.xml | 13 - .../layout-sw600dp-land/track_schedule.xml | 72 ++- app/src/main/res/layout/fragment_live.xml | 11 +- app/src/main/res/layout/fragment_tracks.xml | 10 +- .../res/layout/include_navigation_drawer.xml | 69 --- app/src/main/res/layout/item_event.xml | 4 +- app/src/main/res/layout/item_main_menu.xml | 5 - app/src/main/res/layout/main.xml | 50 ++- app/src/main/res/layout/navigation_header.xml | 9 + app/src/main/res/menu/main_navigation.xml | 37 ++ app/src/main/res/values-v21/dimens.xml | 1 + app/src/main/res/values-v21/styles.xml | 7 - app/src/main/res/values/attrs.xml | 28 -- app/src/main/res/values/dimens.xml | 19 +- app/src/main/res/values/styles.xml | 30 +- 26 files changed, 258 insertions(+), 1311 deletions(-) delete mode 100644 app/src/main/java/be/digitalia/fosdem/widgets/AdapterLinearLayout.java delete mode 100644 app/src/main/java/be/digitalia/fosdem/widgets/ForegroundLinearLayout.java delete mode 100644 app/src/main/java/be/digitalia/fosdem/widgets/ScrimInsetsFrameLayout.java delete mode 100644 app/src/main/java/be/digitalia/fosdem/widgets/SlidingTabLayout.java delete mode 100644 app/src/main/res/animator-v21/fab_state_list.xml delete mode 100644 app/src/main/res/drawable/fab_background.xml delete mode 100644 app/src/main/res/drawable/fab_background_highlighted.xml delete mode 100644 app/src/main/res/layout/include_navigation_drawer.xml delete mode 100644 app/src/main/res/layout/item_main_menu.xml create mode 100644 app/src/main/res/layout/navigation_header.xml create mode 100644 app/src/main/res/menu/main_navigation.xml diff --git a/app/build.gradle b/app/build.gradle index 014844f..06d4943 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,6 +26,7 @@ android { dependencies { implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' implementation ('androidx.preference:preference:1.1.0-alpha01') { diff --git a/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.java b/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.java index 9a7d90a..9c30bb5 100644 --- a/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.java +++ b/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.java @@ -11,42 +11,36 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.PorterDuff; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; -import android.text.SpannableString; -import android.text.Spanned; import android.text.format.DateUtils; -import android.text.style.ForegroundColorSpan; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.widget.ProgressBar; -import android.widget.ScrollView; import android.widget.TextView; -import android.widget.Toast; -import androidx.annotation.DrawableRes; +import com.google.android.material.navigation.NavigationView; +import com.google.android.material.snackbar.Snackbar; + +import androidx.annotation.IdRes; import androidx.annotation.NonNull; -import androidx.annotation.StringRes; +import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.browser.customtabs.CustomTabsIntent; import androidx.core.content.ContextCompat; import androidx.core.view.GravityCompat; -import androidx.core.widget.TextViewCompat; +import androidx.core.view.OnApplyWindowInsetsListener; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; @@ -64,7 +58,6 @@ import be.digitalia.fosdem.fragments.LiveFragment; import be.digitalia.fosdem.fragments.MapFragment; import be.digitalia.fosdem.fragments.PersonsListFragment; import be.digitalia.fosdem.fragments.TracksFragment; -import be.digitalia.fosdem.widgets.AdapterLinearLayout; /** * Main entry point of the application. Allows to switch between section fragments and update the database. @@ -77,41 +70,33 @@ public class MainActivity extends AppCompatActivity { public static final String ACTION_SHORTCUT_LIVE = BuildConfig.APPLICATION_ID + ".intent.action.SHORTCUT_LIVE"; private enum Section { - TRACKS(TracksFragment.class, R.string.menu_tracks, R.drawable.ic_event_grey600_24dp, true, true), - BOOKMARKS(BookmarksListFragment.class, R.string.menu_bookmarks, R.drawable.ic_bookmark_grey600_24dp, false, false), - LIVE(LiveFragment.class, R.string.menu_live, R.drawable.ic_play_circle_outline_grey600_24dp, true, false), - SPEAKERS(PersonsListFragment.class, R.string.menu_speakers, R.drawable.ic_people_grey600_24dp, false, false), - MAP(MapFragment.class, R.string.menu_map, R.drawable.ic_map_grey600_24dp, false, false); + TRACKS(R.id.menu_tracks, TracksFragment.class, true, true), + BOOKMARKS(R.id.menu_bookmarks, BookmarksListFragment.class, false, false), + LIVE(R.id.menu_live, LiveFragment.class, true, false), + SPEAKERS(R.id.menu_speakers, PersonsListFragment.class, false, false), + MAP(R.id.menu_map, MapFragment.class, false, false); + private final int menuItemId; private final String fragmentClassName; - private final int titleResId; - private final int iconResId; private final boolean extendsAppBar; private final boolean keep; - Section(Class fragmentClass, int titleResId, int iconResId, - boolean extendsAppBar, boolean keep) { + Section(@IdRes int menuItemId, Class fragmentClass, boolean extendsAppBar, boolean keep) { + this.menuItemId = menuItemId; this.fragmentClassName = fragmentClass.getName(); - this.titleResId = titleResId; - this.iconResId = iconResId; this.extendsAppBar = extendsAppBar; this.keep = keep; } + @IdRes + public int getMenuItemId() { + return menuItemId; + } + public String getFragmentClassName() { return fragmentClassName; } - @StringRes - public int getTitleResId() { - return titleResId; - } - - @DrawableRes - public int getIconResId() { - return iconResId; - } - public boolean extendsAppBar() { return extendsAppBar; } @@ -119,12 +104,21 @@ public class MainActivity extends AppCompatActivity { public boolean shouldKeep() { return keep; } + + @Nullable + public static Section fromMenuItemId(@IdRes int menuItemId) { + for (Section section : Section.values()) { + if (section.menuItemId == menuItemId) { + return section; + } + } + return null; + } } private static final long DATABASE_VALIDITY_DURATION = DateUtils.DAY_IN_MILLIS; private static final long DOWNLOAD_REMINDER_SNOOZE_DURATION = DateUtils.DAY_IN_MILLIS; private static final String PREF_LAST_DOWNLOAD_REMINDER_TIME = "last_download_reminder_time"; - private static final String STATE_CURRENT_SECTION = "current_section"; private static final String LAST_UPDATE_DATE_FORMAT = "d MMM yyyy kk:mm:ss"; @@ -133,13 +127,12 @@ public class MainActivity extends AppCompatActivity { // Main menu Section currentSection; - int pendingMenuSection = -1; - int pendingMenuFooter = -1; + MenuItem pendingNavigationMenuItem = null; DrawerLayout drawerLayout; private ActionBarDrawerToggle drawerToggle; View mainMenu; + private NavigationView navigationView; private TextView lastUpdateTextView; - private MainMenuAdapter menuAdapter; private MenuItem searchMenuItem; @@ -162,7 +155,7 @@ public class MainActivity extends AppCompatActivity { default: message = getResources().getQuantityString(R.plurals.events_download_completed, result, result); } - Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show(); + Snackbar.make(findViewById(R.id.content), message, Snackbar.LENGTH_LONG).show(); } }; @@ -251,8 +244,7 @@ public class MainActivity extends AppCompatActivity { public void onDrawerStateChanged(int newState) { super.onDrawerStateChanged(newState); if (newState == DrawerLayout.STATE_DRAGGING) { - pendingMenuSection = -1; - pendingMenuFooter = -1; + pendingNavigationMenuItem = null; } } @@ -266,13 +258,9 @@ public class MainActivity extends AppCompatActivity { @Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); - if (pendingMenuSection != -1) { - selectMenuSection(pendingMenuSection); - pendingMenuSection = -1; - } - if (pendingMenuFooter != -1) { - selectMenuFooter(pendingMenuFooter); - pendingMenuFooter = -1; + if (pendingNavigationMenuItem != null) { + handleNavigationMenuItem(pendingNavigationMenuItem); + pendingNavigationMenuItem = null; } } }; @@ -284,11 +272,22 @@ public class MainActivity extends AppCompatActivity { // Setup Main menu mainMenu = findViewById(R.id.main_menu); - final AdapterLinearLayout sectionsList = findViewById(R.id.sections); - menuAdapter = new MainMenuAdapter(getLayoutInflater()); - sectionsList.setAdapter(menuAdapter); - mainMenu.findViewById(R.id.settings).setOnClickListener(menuFooterClickListener); - mainMenu.findViewById(R.id.volunteer).setOnClickListener(menuFooterClickListener); + // Forward window insets to NavigationView + ViewCompat.setOnApplyWindowInsetsListener(mainMenu, new OnApplyWindowInsetsListener() { + @Override + public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) { + return insets; + } + }); + navigationView = findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { + pendingNavigationMenuItem = menuItem; + drawerLayout.closeDrawer(mainMenu); + return true; + } + }); LocalBroadcastManager.getInstance(this).registerReceiver(scheduleRefreshedReceiver, new IntentFilter(DatabaseManager.ACTION_SCHEDULE_REFRESHED)); @@ -296,8 +295,8 @@ public class MainActivity extends AppCompatActivity { lastUpdateTextView = mainMenu.findViewById(R.id.last_update); updateLastUpdateTime(); - // Restore current section if (savedInstanceState == null) { + // Select initial section currentSection = Section.TRACKS; String action = getIntent().getAction(); if (action != null) { @@ -310,33 +309,18 @@ public class MainActivity extends AppCompatActivity { break; } } + navigationView.setCheckedItem(currentSection.getMenuItemId()); String fragmentClassName = currentSection.getFragmentClassName(); Fragment f = Fragment.instantiate(this, fragmentClassName); getSupportFragmentManager().beginTransaction().add(R.id.content, f, fragmentClassName).commit(); - } else { - currentSection = Section.values()[savedInstanceState.getInt(STATE_CURRENT_SECTION)]; } - // Ensure the current section is visible in the menu - sectionsList.post(new Runnable() { - @Override - public void run() { - if (sectionsList.getChildCount() > currentSection.ordinal()) { - ScrollView mainMenuScrollView = findViewById(R.id.main_menu_scroll); - int requiredScroll = sectionsList.getTop() - + sectionsList.getChildAt(currentSection.ordinal()).getBottom() - - mainMenuScrollView.getHeight(); - mainMenuScrollView.scrollTo(0, Math.max(0, requiredScroll)); - } - } - }); - updateActionBar(); } - private void updateActionBar() { - setTitle(currentSection.getTitleResId()); + private void updateActionBar(@NonNull Section section, @NonNull MenuItem menuItem) { + setTitle(menuItem.getTitle()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - toolbar.setElevation(currentSection.extendsAppBar() + toolbar.setElevation(section.extendsAppBar() ? 0f : getResources().getDimension(R.dimen.toolbar_elevation)); } } @@ -353,6 +337,17 @@ public class MainActivity extends AppCompatActivity { protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); drawerToggle.syncState(); + + // Restore current section from NavigationView + final MenuItem menuItem = navigationView.getCheckedItem(); + if (menuItem != null) { + if (currentSection == null) { + currentSection = Section.fromMenuItemId(menuItem.getItemId()); + } + if (currentSection != null) { + updateActionBar(currentSection, menuItem); + } + } } @Override @@ -367,10 +362,13 @@ public class MainActivity extends AppCompatActivity { @Override protected void onSaveInstanceState(Bundle outState) { // Ensure no fragment transaction attempt will occur after onSaveInstanceState() - pendingMenuSection = -1; - pendingMenuFooter = -1; + if (pendingNavigationMenuItem != null) { + pendingNavigationMenuItem = null; + if (currentSection != null) { + navigationView.setCheckedItem(currentSection.getMenuItemId()); + } + } super.onSaveInstanceState(outState); - outState.putInt(STATE_CURRENT_SECTION, currentSection.ordinal()); } @Override @@ -473,69 +471,32 @@ public class MainActivity extends AppCompatActivity { // MAIN MENU - private class MainMenuAdapter extends AdapterLinearLayout.Adapter
{ - - private final Section[] sections = Section.values(); - private final LayoutInflater inflater; - private final int currentSectionForegroundColor; - - public MainMenuAdapter(LayoutInflater inflater) { - this.inflater = inflater; - // Select the primary color to tint the current section - TypedArray a = getTheme().obtainStyledAttributes(new int[]{R.attr.colorPrimary}); - try { - currentSectionForegroundColor = a.getColor(0, Color.TRANSPARENT); - } finally { - a.recycle(); + void handleNavigationMenuItem(@NonNull MenuItem menuItem) { + final int menuItemId = menuItem.getItemId(); + final Section section = Section.fromMenuItemId(menuItemId); + if (section != null) { + selectMenuSection(section, menuItem); + } else { + switch (menuItemId) { + case R.id.menu_settings: + startActivity(new Intent(MainActivity.this, SettingsActivity.class)); + overridePendingTransition(R.anim.slide_in_right, R.anim.partial_zoom_out); + break; + case R.id.menu_volunteer: + try { + new CustomTabsIntent.Builder() + .setToolbarColor(ContextCompat.getColor(this, R.color.color_primary)) + .setShowTitle(true) + .build() + .launchUrl(this, Uri.parse(FosdemUrls.getVolunteer())); + } catch (ActivityNotFoundException ignore) { + } + break; } } - - @Override - public int getCount() { - return sections.length; - } - - @Override - public Section getItem(int position) { - return sections[position]; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = inflater.inflate(R.layout.item_main_menu, parent, false); - convertView.setOnClickListener(sectionClickListener); - } - - Section section = getItem(position); - convertView.setSelected(section == currentSection); - - TextView tv = convertView.findViewById(R.id.section_text); - SpannableString sectionTitle = new SpannableString(getString(section.getTitleResId())); - Drawable sectionIcon = AppCompatResources.getDrawable(MainActivity.this, section.getIconResId()); - if (section == currentSection) { - // Special color for the current section - sectionTitle.setSpan(new ForegroundColorSpan(currentSectionForegroundColor), 0, sectionTitle.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - // We need to mutate the drawable before applying the ColorFilter, or else all the similar drawable instances will be tinted. - sectionIcon.mutate().setColorFilter(currentSectionForegroundColor, PorterDuff.Mode.SRC_IN); - } - tv.setText(sectionTitle); - TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(tv, sectionIcon, null, null, null); - - return convertView; - } } - final View.OnClickListener sectionClickListener = new View.OnClickListener() { - @Override - public void onClick(View view) { - pendingMenuSection = ((ViewGroup) view.getParent()).indexOfChild(view); - drawerLayout.closeDrawer(mainMenu); - } - }; - - void selectMenuSection(int position) { - Section section = menuAdapter.getItem(position); + void selectMenuSection(@NonNull Section section, @NonNull MenuItem menuItem) { if (section != currentSection) { // Switch to new section FragmentManager fm = getSupportFragmentManager(); @@ -558,36 +519,7 @@ public class MainActivity extends AppCompatActivity { ft.commit(); currentSection = section; - updateActionBar(); - menuAdapter.notifyDataSetChanged(); - } - } - - private final View.OnClickListener menuFooterClickListener = new View.OnClickListener() { - - @Override - public void onClick(View view) { - pendingMenuFooter = view.getId(); - drawerLayout.closeDrawer(mainMenu); - } - }; - - void selectMenuFooter(int id) { - switch (id) { - case R.id.settings: - startActivity(new Intent(MainActivity.this, SettingsActivity.class)); - overridePendingTransition(R.anim.slide_in_right, R.anim.partial_zoom_out); - break; - case R.id.volunteer: - try { - new CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(this, R.color.color_primary)) - .setShowTitle(true) - .build() - .launchUrl(this, Uri.parse(FosdemUrls.getVolunteer())); - } catch (ActivityNotFoundException ignore) { - } - break; + updateActionBar(section, menuItem); } } } 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 2b7fac6..ed71823 100644 --- a/app/src/main/java/be/digitalia/fosdem/fragments/EventDetailsFragment.java +++ b/app/src/main/java/be/digitalia/fosdem/fragments/EventDetailsFragment.java @@ -24,7 +24,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; + +import com.google.android.material.snackbar.Snackbar; import java.text.DateFormat; import java.util.Date; @@ -369,7 +370,7 @@ public class EventDetailsFragment extends Fragment { try { startActivity(intent); } catch (ActivityNotFoundException e) { - Toast.makeText(getActivity(), R.string.calendar_not_found, Toast.LENGTH_LONG).show(); + Snackbar.make(getView(), R.string.calendar_not_found, Snackbar.LENGTH_LONG).show(); } } diff --git a/app/src/main/java/be/digitalia/fosdem/fragments/LiveFragment.java b/app/src/main/java/be/digitalia/fosdem/fragments/LiveFragment.java index 4d91e3a..f53d1c4 100644 --- a/app/src/main/java/be/digitalia/fosdem/fragments/LiveFragment.java +++ b/app/src/main/java/be/digitalia/fosdem/fragments/LiveFragment.java @@ -6,6 +6,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.google.android.material.tabs.TabLayout; + import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -13,13 +15,12 @@ import androidx.fragment.app.FragmentPagerAdapter; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.ViewPager; import be.digitalia.fosdem.R; -import be.digitalia.fosdem.widgets.SlidingTabLayout; public class LiveFragment extends Fragment implements RecycledViewPoolProvider { static class ViewHolder { ViewPager pager; - SlidingTabLayout slidingTabs; + TabLayout tabs; RecyclerView.RecycledViewPool recycledViewPool; } @@ -32,8 +33,8 @@ public class LiveFragment extends Fragment implements RecycledViewPoolProvider { holder = new ViewHolder(); holder.pager = view.findViewById(R.id.pager); holder.pager.setAdapter(new LivePagerAdapter(getChildFragmentManager(), getResources())); - holder.slidingTabs = view.findViewById(R.id.sliding_tabs); - holder.slidingTabs.setViewPager(holder.pager); + holder.tabs = view.findViewById(R.id.tabs); + holder.tabs.setupWithViewPager(holder.pager, false); holder.recycledViewPool = new RecyclerView.RecycledViewPool(); return view; diff --git a/app/src/main/java/be/digitalia/fosdem/fragments/TracksFragment.java b/app/src/main/java/be/digitalia/fosdem/fragments/TracksFragment.java index 412a108..2a7b70a 100644 --- a/app/src/main/java/be/digitalia/fosdem/fragments/TracksFragment.java +++ b/app/src/main/java/be/digitalia/fosdem/fragments/TracksFragment.java @@ -7,6 +7,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.google.android.material.tabs.TabLayout; + import java.util.List; import androidx.annotation.NonNull; @@ -20,7 +22,6 @@ import androidx.viewpager.widget.ViewPager; import be.digitalia.fosdem.R; import be.digitalia.fosdem.db.DatabaseManager; import be.digitalia.fosdem.model.Day; -import be.digitalia.fosdem.widgets.SlidingTabLayout; public class TracksFragment extends Fragment implements RecycledViewPoolProvider, Observer> { @@ -28,7 +29,7 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider View contentView; View emptyView; ViewPager pager; - SlidingTabLayout slidingTabs; + TabLayout tabs; DaysAdapter daysAdapter; RecyclerView.RecycledViewPool recycledViewPool; } @@ -56,7 +57,7 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider holder.contentView = view.findViewById(R.id.content); holder.emptyView = view.findViewById(android.R.id.empty); holder.pager = view.findViewById(R.id.pager); - holder.slidingTabs = view.findViewById(R.id.sliding_tabs); + holder.tabs = view.findViewById(R.id.tabs); holder.daysAdapter = new DaysAdapter(getChildFragmentManager()); holder.recycledViewPool = new RecyclerView.RecycledViewPool(); @@ -108,7 +109,7 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider holder.emptyView.setVisibility(View.GONE); if (holder.pager.getAdapter() == null) { holder.pager.setAdapter(holder.daysAdapter); - holder.slidingTabs.setViewPager(holder.pager); + holder.tabs.setupWithViewPager(holder.pager); } if (savedCurrentPage != -1) { holder.pager.setCurrentItem(Math.min(savedCurrentPage, totalPages - 1), false); diff --git a/app/src/main/java/be/digitalia/fosdem/widgets/AdapterLinearLayout.java b/app/src/main/java/be/digitalia/fosdem/widgets/AdapterLinearLayout.java deleted file mode 100644 index ec3182b..0000000 --- a/app/src/main/java/be/digitalia/fosdem/widgets/AdapterLinearLayout.java +++ /dev/null @@ -1,115 +0,0 @@ -package be.digitalia.fosdem.widgets; - -import android.content.Context; -import android.database.DataSetObservable; -import android.database.DataSetObserver; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -/** - * Vertical LinearLayout populated by a special adapter. - * - * @author Christophe Beyls - */ -public class AdapterLinearLayout extends LinearLayout { - - /** - * Implement this Adapter to populate the layout. - * Call notifyDataSetChanged() to update it. - */ - public static abstract class Adapter { - - final DataSetObservable mDataSetObservable = new DataSetObservable(); - - public void notifyDataSetChanged() { - mDataSetObservable.notifyChanged(); - } - - public abstract int getCount(); - - public abstract T getItem(int position); - - public abstract View getView(int position, View convertView, ViewGroup parent); - } - - class AdapterLinearLayoutDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - populateFromAdapter(); - } - } - - private Adapter mAdapter; - private AdapterLinearLayoutDataSetObserver mDataSetObserver; - - - public AdapterLinearLayout(Context context) { - this(context, null); - } - - public AdapterLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - setOrientation(VERTICAL); - } - - public void setAdapter(Adapter adapter) { - if (mAdapter == adapter) { - return; - } - if (mAdapter != null && mDataSetObserver != null) { - mAdapter.mDataSetObservable.unregisterObserver(mDataSetObserver); - } - removeAllViews(); - mAdapter = adapter; - if (adapter != null && mDataSetObserver != null) { - populateFromAdapter(); - adapter.mDataSetObservable.registerObserver(mDataSetObserver); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - mDataSetObserver = new AdapterLinearLayoutDataSetObserver(); - if (mAdapter != null) { - populateFromAdapter(); - mAdapter.mDataSetObservable.registerObserver(mDataSetObserver); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if ((mAdapter != null) && (mDataSetObserver != null)) { - mAdapter.mDataSetObservable.unregisterObserver(mDataSetObserver); - } - mDataSetObserver = null; - } - - void populateFromAdapter() { - final Adapter adapter = mAdapter; - final int currentCount = getChildCount(); - final int newCount = adapter.getCount(); - final int commonCount = Math.min(currentCount, newCount); - // 1. Update common views - for (int i = 0; i < commonCount; ++i) { - final View currentView = getChildAt(i); - final View newView = adapter.getView(i, currentView, this); - if (currentView != newView) { - // Edge case: View is not recycled - removeViewAt(i); - addView(newView, i); - } - } - // 2a. Add missing views - for (int i = commonCount; i < newCount; ++i) { - addView(adapter.getView(i, null, this)); - } - // 2b. Remove extra views (starting from the end to avoid array copies) - for (int i = currentCount - 1; i >= commonCount; --i) { - removeViewAt(i); - } - } -} diff --git a/app/src/main/java/be/digitalia/fosdem/widgets/ForegroundLinearLayout.java b/app/src/main/java/be/digitalia/fosdem/widgets/ForegroundLinearLayout.java deleted file mode 100644 index 27d6d2e..0000000 --- a/app/src/main/java/be/digitalia/fosdem/widgets/ForegroundLinearLayout.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2015 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 be.digitalia.fosdem.widgets; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.AttributeSet; -import android.view.Gravity; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.LinearLayoutCompat; -import be.digitalia.fosdem.R; - -public class ForegroundLinearLayout extends LinearLayoutCompat { - - private Drawable mForeground; - - private final Rect mSelfBounds = new Rect(); - - private final Rect mOverlayBounds = new Rect(); - - private int mForegroundGravity = Gravity.FILL; - - protected boolean mForegroundInPadding = true; - - boolean mForegroundBoundsChanged = false; - - public ForegroundLinearLayout(Context context) { - this(context, null); - } - - public ForegroundLinearLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public ForegroundLinearLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundLinearLayout, - defStyle, 0); - - mForegroundGravity = a.getInt( - R.styleable.ForegroundLinearLayout_android_foregroundGravity, mForegroundGravity); - - final Drawable d = a.getDrawable(R.styleable.ForegroundLinearLayout_android_foreground); - if (d != null) { - setForeground(d); - } - - mForegroundInPadding = a.getBoolean( - R.styleable.ForegroundLinearLayout_foregroundInsidePadding, true); - - a.recycle(); - } - - /** - * Describes how the foreground is positioned. - * - * @return foreground gravity. - * @see #setForegroundGravity(int) - */ - public int getForegroundGravity() { - return mForegroundGravity; - } - - /** - * Describes how the foreground is positioned. Defaults to START and TOP. - * - * @param foregroundGravity See {@link Gravity} - * @see #getForegroundGravity() - */ - public void setForegroundGravity(int foregroundGravity) { - if (mForegroundGravity != foregroundGravity) { - if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { - foregroundGravity |= Gravity.START; - } - - if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { - foregroundGravity |= Gravity.TOP; - } - - mForegroundGravity = foregroundGravity; - - if (mForegroundGravity == Gravity.FILL && mForeground != null) { - Rect padding = new Rect(); - mForeground.getPadding(padding); - } - - requestLayout(); - } - } - - @Override - protected boolean verifyDrawable(@NonNull Drawable who) { - return super.verifyDrawable(who) || (who == mForeground); - } - - @Override - public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - if (mForeground != null) { - mForeground.jumpToCurrentState(); - } - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - if (mForeground != null && mForeground.isStateful()) { - mForeground.setState(getDrawableState()); - } - } - - /** - * Supply a Drawable that is to be rendered on top of all of the child - * views in the frame layout. Any padding in the Drawable will be taken - * into account by ensuring that the children are inset to be placed - * inside of the padding area. - * - * @param drawable The Drawable to be drawn on top of the children. - */ - public void setForeground(Drawable drawable) { - if (mForeground != drawable) { - if (mForeground != null) { - mForeground.setCallback(null); - unscheduleDrawable(mForeground); - } - - mForeground = drawable; - - if (drawable != null) { - setWillNotDraw(false); - drawable.setCallback(this); - if (drawable.isStateful()) { - drawable.setState(getDrawableState()); - } - if (mForegroundGravity == Gravity.FILL) { - Rect padding = new Rect(); - drawable.getPadding(padding); - } - } else { - setWillNotDraw(true); - } - requestLayout(); - invalidate(); - } - } - - /** - * Returns the drawable used as the foreground of this FrameLayout. The - * foreground drawable, if non-null, is always drawn on top of the children. - * - * @return A Drawable or null if no foreground was set. - */ - public Drawable getForeground() { - return mForeground; - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - mForegroundBoundsChanged |= changed; - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - mForegroundBoundsChanged = true; - } - - @Override - public void draw(@NonNull Canvas canvas) { - super.draw(canvas); - - if (mForeground != null) { - final Drawable foreground = mForeground; - - if (mForegroundBoundsChanged) { - mForegroundBoundsChanged = false; - final Rect selfBounds = mSelfBounds; - final Rect overlayBounds = mOverlayBounds; - - final int w = getRight() - getLeft(); - final int h = getBottom() - getTop(); - - if (mForegroundInPadding) { - selfBounds.set(0, 0, w, h); - } else { - selfBounds.set(getPaddingLeft(), getPaddingTop(), - w - getPaddingRight(), h - getPaddingBottom()); - } - - Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), - foreground.getIntrinsicHeight(), selfBounds, overlayBounds); - foreground.setBounds(overlayBounds); - } - - foreground.draw(canvas); - } - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public void drawableHotspotChanged(float x, float y) { - super.drawableHotspotChanged(x, y); - if (mForeground != null) { - mForeground.setHotspot(x, y); - } - } - -} diff --git a/app/src/main/java/be/digitalia/fosdem/widgets/ScrimInsetsFrameLayout.java b/app/src/main/java/be/digitalia/fosdem/widgets/ScrimInsetsFrameLayout.java deleted file mode 100644 index bc9f3ab..0000000 --- a/app/src/main/java/be/digitalia/fosdem/widgets/ScrimInsetsFrameLayout.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2015 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 be.digitalia.fosdem.widgets; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import androidx.annotation.NonNull; -import androidx.core.view.ViewCompat; -import androidx.core.view.WindowInsetsCompat; -import be.digitalia.fosdem.R; - -public class ScrimInsetsFrameLayout extends FrameLayout { - Drawable mInsetForeground; - Rect mInsets; - private Rect mTempRect = new Rect(); - - public ScrimInsetsFrameLayout(Context context) { - this(context, null); - } - - public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - final TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.ScrimInsetsFrameLayout, defStyleAttr, - R.style.Widget_Design_ScrimInsetsFrameLayout); - mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsFrameLayout_insetForeground); - a.recycle(); - setWillNotDraw(true); // No need to draw until the insets are adjusted - ViewCompat.setOnApplyWindowInsetsListener(this, - new androidx.core.view.OnApplyWindowInsetsListener() { - @Override - public WindowInsetsCompat onApplyWindowInsets(View v, - WindowInsetsCompat insets) { - if (null == mInsets) { - mInsets = new Rect(); - } - mInsets.set(insets.getSystemWindowInsetLeft(), - insets.getSystemWindowInsetTop(), - insets.getSystemWindowInsetRight(), - insets.getSystemWindowInsetBottom()); - setWillNotDraw(mInsets.isEmpty() || mInsetForeground == null); - ViewCompat.postInvalidateOnAnimation(ScrimInsetsFrameLayout.this); - return insets.consumeSystemWindowInsets(); - } - }); - } - - @Override - public void draw(@NonNull Canvas canvas) { - super.draw(canvas); - int width = getWidth(); - int height = getHeight(); - if (mInsets != null && mInsetForeground != null) { - int sc = canvas.save(); - canvas.translate(getScrollX(), getScrollY()); - // Top - mTempRect.set(0, 0, width, mInsets.top); - mInsetForeground.setBounds(mTempRect); - mInsetForeground.draw(canvas); - // Bottom - mTempRect.set(0, height - mInsets.bottom, width, height); - mInsetForeground.setBounds(mTempRect); - mInsetForeground.draw(canvas); - // Left - mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom); - mInsetForeground.setBounds(mTempRect); - mInsetForeground.draw(canvas); - // Right - mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom); - mInsetForeground.setBounds(mTempRect); - mInsetForeground.draw(canvas); - canvas.restoreToCount(sc); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (mInsetForeground != null) { - mInsetForeground.setCallback(this); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mInsetForeground != null) { - mInsetForeground.setCallback(null); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/be/digitalia/fosdem/widgets/SlidingTabLayout.java b/app/src/main/java/be/digitalia/fosdem/widgets/SlidingTabLayout.java deleted file mode 100644 index 99788b4..0000000 --- a/app/src/main/java/be/digitalia/fosdem/widgets/SlidingTabLayout.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2014 Chris Banes - * Copyright 2016 Christophe Beyls - * - * 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 be.digitalia.fosdem.widgets; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Typeface; -import android.os.Build; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.widget.HorizontalScrollView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.IdRes; -import androidx.annotation.LayoutRes; -import androidx.viewpager.widget.PagerAdapter; -import androidx.viewpager.widget.ViewPager; -import be.digitalia.fosdem.R; - -/** - */ -public class SlidingTabLayout extends HorizontalScrollView { - - public interface TabListener { - - void onTabSelected(int pos); - - void onTabReSelected(int pos); - - } - - private static final int[][] TAB_COLOR_STATES = new int[][]{SELECTED_STATE_SET, EMPTY_STATE_SET}; - - private int mTitleOffset; - - private int mTabViewLayoutId; - private int mTabViewTextViewId; - private boolean mDistributeEvenly; - - private ColorStateList mTextColor; - - ViewPager mViewPager; - PagerAdapter mAdapter; - private final InternalViewPagerListener mPageChangeListener = new InternalViewPagerListener(); - private final PagerAdapterObserver mPagerAdapterObserver = new PagerAdapterObserver(); - - TabListener mTabListener; - - final SlidingTabStrip mTabStrip; - - public SlidingTabLayout(Context context) { - this(context, null); - } - - public SlidingTabLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - // Disable the Scroll Bar - setHorizontalScrollBarEnabled(false); - // Make sure that the Tab Strips fills this View - setFillViewport(true); - - mTabStrip = new SlidingTabStrip(context); - addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingTabLayout, - defStyle, R.style.SlidingTabLayout); - - mTabStrip.setSelectedIndicatorHeight(a.getDimensionPixelSize(R.styleable.SlidingTabLayout_indicatorHeight, 0)); - mTabStrip.setSelectedIndicatorColor(a.getColor(R.styleable.SlidingTabLayout_indicatorColor, 0)); - mTextColor = a.getColorStateList(R.styleable.SlidingTabLayout_textColor); - if ((mTextColor != null) && a.hasValue(R.styleable.SlidingTabLayout_selectedTextColor)) { - setTabTextColors(mTextColor.getDefaultColor(), a.getColor(R.styleable.SlidingTabLayout_selectedTextColor, 0)); - } - setContentInsetStart(a.getDimensionPixelSize(R.styleable.SlidingTabLayout_contentInsetStart, 0)); - setDistributeEvenly(a.getBoolean(R.styleable.SlidingTabLayout_distributeEvenly, false)); - - a.recycle(); - } - - public void setContentInsetStart(int offset) { - mTitleOffset = offset; - mTabStrip.setPadding(offset, 0, 0, 0); - } - - public void setDistributeEvenly(boolean distributeEvenly) { - mDistributeEvenly = distributeEvenly; - } - - /** - * Sets the color to be used for indicating the selected tab. - * This will override the style color. - */ - public void setSelectedTabIndicatorColor(@ColorInt int color) { - mTabStrip.setSelectedIndicatorColor(color); - } - - public void setSelectedTabIndicatorHeight(int height) { - mTabStrip.setSelectedIndicatorHeight(height); - } - - public void setTabTextColors(ColorStateList color) { - mTextColor = color; - } - - public void setTabTextColors(@ColorInt int normalColor, @ColorInt int selectedColor) { - mTextColor = createColorStateList(normalColor, selectedColor); - } - - private static ColorStateList createColorStateList(int defaultColor, int selectedColor) { - final int[] colors = new int[]{selectedColor, defaultColor}; - return new ColorStateList(TAB_COLOR_STATES, colors); - } - - /** - * Set the custom layout to be inflated for the tab views. - * - * @param layoutResId Layout id to be inflated - * @param textViewId id of the {@link TextView} in the inflated view - */ - public void setCustomTabView(@LayoutRes int layoutResId, @IdRes int textViewId) { - mTabViewLayoutId = layoutResId; - mTabViewTextViewId = textViewId; - } - - public void setTabListener(TabListener tabListener) { - mTabListener = tabListener; - } - - /** - * Sets the associated view pager. The ViewPager must have an adapter set. - * The SlidingTabLayout will then listen for changes and update the tabs automatically. - */ - public void setViewPager(ViewPager viewPager) { - if (mViewPager != null) { - mViewPager.removeOnPageChangeListener(mPageChangeListener); - mAdapter.unregisterDataSetObserver(mPagerAdapterObserver); - } - if (viewPager != null) { - PagerAdapter adapter = viewPager.getAdapter(); - if (adapter == null) { - throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set"); - } - mViewPager = viewPager; - mAdapter = adapter; - mPageChangeListener.reset(); - viewPager.addOnPageChangeListener(mPageChangeListener); - adapter.registerDataSetObserver(mPagerAdapterObserver); - } else { - mViewPager = null; - mAdapter = null; - } - notifyDataSetChanged(); - } - - void notifyDataSetChanged() { - mTabStrip.removeAllViews(); - if (mViewPager != null) { - populateTabStrip(); - } - } - - static void setSelectedCompat(View view, boolean selected) { - final boolean becomeSelected = selected && !view.isSelected(); - view.setSelected(selected); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && becomeSelected) { - // Pre-JB we need to manually send the TYPE_VIEW_SELECTED event - view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - } - } - - private void populateTabStrip() { - final int adapterCount = mAdapter.getCount(); - final View.OnClickListener tabClickListener = new TabClickListener(); - final LayoutInflater inflater = LayoutInflater.from(getContext()); - final int currentItem = mViewPager.getCurrentItem(); - - for (int i = 0; i < adapterCount; i++) { - View tabView; - TextView tabTitleView; - - if (mTabViewLayoutId != 0) { - // If there is a custom tab view layout id set, try and inflate it - tabView = inflater.inflate(mTabViewLayoutId, mTabStrip, false); - tabTitleView = tabView.findViewById(mTabViewTextViewId); - if (tabTitleView == null) { - tabTitleView = (TextView) tabView; - } - } else { - // Inflate our default tab layout - tabView = inflater.inflate(R.layout.widget_sliding_tab_layout_text, mTabStrip, false); - tabTitleView = (TextView) tabView; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - // Emulate Roboto Medium in previous Android versions - tabTitleView.setTypeface(Typeface.DEFAULT_BOLD); - } - } - if (mTextColor != null) { - tabTitleView.setTextColor(mTextColor); - } - - if (mDistributeEvenly) { - LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); - lp.width = 0; - lp.weight = 1; - } - - tabTitleView.setText(mAdapter.getPageTitle(i)); - tabView.setFocusable(true); - tabView.setOnClickListener(tabClickListener); - - mTabStrip.addView(tabView); - if (i == currentItem) { - setSelectedCompat(tabView, true); - } - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (mViewPager != null) { - scrollToTab(mViewPager.getCurrentItem(), 0); - } - announceSelectedTab(hasWindowFocus()); - } - - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - super.onWindowFocusChanged(hasWindowFocus); - announceSelectedTab(hasWindowFocus); - } - - private void announceSelectedTab(boolean hasWindowFocus) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && hasWindowFocus) { - getHandler().post(new Runnable() { - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - @Override - public void run() { - if (mViewPager != null && mAdapter != null && mAdapter.getCount() > 0) { - CharSequence pageTitle = mAdapter.getPageTitle(mViewPager.getCurrentItem()); - if (!TextUtils.isEmpty(pageTitle)) { - announceForAccessibility(pageTitle); - } - } - } - }); - } - } - - void scrollToTab(int tabIndex, float positionOffset) { - final int tabStripChildCount = mTabStrip.getChildCount(); - if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { - return; - } - - View selectedChild = mTabStrip.getChildAt(tabIndex); - if (selectedChild != null) { - int targetScrollX = selectedChild.getLeft() + - Math.round(positionOffset * selectedChild.getWidth()) - mTitleOffset; - - scrollTo(targetScrollX, 0); - } - } - - class InternalViewPagerListener implements ViewPager.OnPageChangeListener { - private int mScrollState; - - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - int tabStripChildCount = mTabStrip.getChildCount(); - if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { - return; - } - - mTabStrip.onViewPagerPageChanged(position, positionOffset); - - - scrollToTab(position, positionOffset); - } - - @Override - public void onPageScrollStateChanged(int state) { - mScrollState = state; - } - - @Override - public void onPageSelected(int position) { - if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { - mTabStrip.onViewPagerPageChanged(position, 0f); - scrollToTab(position, 0); - } - final int childCount = mTabStrip.getChildCount(); - for (int i = 0; i < childCount; i++) { - setSelectedCompat(mTabStrip.getChildAt(i), position == i); - } - } - - public void reset() { - mScrollState = ViewPager.SCROLL_STATE_IDLE; - } - } - - class PagerAdapterObserver extends DataSetObserver { - @Override - public void onChanged() { - notifyDataSetChanged(); - } - - @Override - public void onInvalidated() { - notifyDataSetChanged(); - } - } - - class TabClickListener implements View.OnClickListener { - @Override - public void onClick(View v) { - final int childCount = mTabStrip.getChildCount(); - for (int i = 0; i < childCount; i++) { - if (v == mTabStrip.getChildAt(i)) { - final int previousPos = mViewPager.getCurrentItem(); - mViewPager.setCurrentItem(i); - - if (mTabListener != null) { - if (previousPos != i) { - mTabListener.onTabSelected(i); - } else { - mTabListener.onTabReSelected(i); - } - } - - return; - } - } - } - } - - - static class SlidingTabStrip extends LinearLayout { - - private int mSelectedIndicatorHeight; - private final Paint mSelectedIndicatorPaint; - - private int mSelectedPosition; - private float mSelectionOffset; - - SlidingTabStrip(Context context) { - super(context); - setWillNotDraw(false); - mSelectedIndicatorPaint = new Paint(); - } - - void setSelectedIndicatorColor(@ColorInt int color) { - mSelectedIndicatorPaint.setColor(color); - invalidate(); - } - - void setSelectedIndicatorHeight(int height) { - mSelectedIndicatorHeight = height; - invalidate(); - } - - void onViewPagerPageChanged(int position, float positionOffset) { - mSelectedPosition = position; - mSelectionOffset = positionOffset; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - final int height = getHeight(); - final int childCount = getChildCount(); - - // Thick colored underline below the current selection - if (childCount > 0) { - View selectedTitle = getChildAt(mSelectedPosition); - int left = selectedTitle.getLeft(); - int right = selectedTitle.getRight(); - - if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { - // Draw the selection partway between the tabs - View nextTitle = getChildAt(mSelectedPosition + 1); - left = (int) (mSelectionOffset * nextTitle.getLeft() + - (1.0f - mSelectionOffset) * left); - right = (int) (mSelectionOffset * nextTitle.getRight() + - (1.0f - mSelectionOffset) * right); - } - - canvas.drawRect(left, height - mSelectedIndicatorHeight, right, - height, mSelectedIndicatorPaint); - } - } - } -} \ No newline at end of file diff --git a/app/src/main/res/animator-v21/fab_state_list.xml b/app/src/main/res/animator-v21/fab_state_list.xml deleted file mode 100644 index ee95ccc..0000000 --- a/app/src/main/res/animator-v21/fab_state_list.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/fab_background.xml b/app/src/main/res/drawable/fab_background.xml deleted file mode 100644 index 71807c5..0000000 --- a/app/src/main/res/drawable/fab_background.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/fab_background_highlighted.xml b/app/src/main/res/drawable/fab_background_highlighted.xml deleted file mode 100644 index 8ee6200..0000000 --- a/app/src/main/res/drawable/fab_background_highlighted.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ 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 66a3a2f..32ce480 100644 --- a/app/src/main/res/layout-sw600dp-land/track_schedule.xml +++ b/app/src/main/res/layout-sw600dp-land/track_schedule.xml @@ -1,52 +1,50 @@ - + - + android:layout_gravity="start" + android:layout_marginTop="128dp" /> - - - - + + android:layout_marginEnd="@dimen/detail_card_view_margin_end" + android:layout_marginRight="@dimen/detail_card_view_margin_end" + android:layout_marginBottom="@dimen/detail_card_view_margin_bottom" + app:cardElevation="@dimen/detail_card_view_elevation" + app:cardPreventCornerOverlap="false" /> - + android:theme="@style/ThemeOverlay.AppCompat.Dark" + app:fabSize="normal" + app:layout_anchor="@+id/toolbar" + app:layout_anchorGravity="bottom|end" + app:srcCompat="@drawable/ic_bookmark_outline_white_24dp" /> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_live.xml b/app/src/main/res/layout/fragment_live.xml index 6b9e29c..39c5da4 100644 --- a/app/src/main/res/layout/fragment_live.xml +++ b/app/src/main/res/layout/fragment_live.xml @@ -1,18 +1,15 @@ - + android:elevation="@dimen/toolbar_elevation"/> @@ -9,12 +10,13 @@ android:layout_height="match_parent" android:orientation="vertical"> - + android:elevation="@dimen/toolbar_elevation" + app:tabMode="scrollable"/> - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_event.xml b/app/src/main/res/layout/item_event.xml index 48bcd68..354a501 100644 --- a/app/src/main/res/layout/item_event.xml +++ b/app/src/main/res/layout/item_event.xml @@ -1,5 +1,5 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_main_menu.xml b/app/src/main/res/layout/item_main_menu.xml deleted file mode 100644 index ae63156..0000000 --- a/app/src/main/res/layout/item_main_menu.xml +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml index 8c29486..048c50f 100644 --- a/app/src/main/res/layout/main.xml +++ b/app/src/main/res/layout/main.xml @@ -1,6 +1,6 @@ - - @@ -23,13 +23,13 @@ android:id="@+id/toolbar" style="@style/Toolbar.Fosdem" android:layout_width="match_parent" - android:layout_height="wrap_content"/> + android:layout_height="wrap_content" /> + android:layout_weight="1" /> @@ -42,12 +42,46 @@ android:layout_marginTop="-7dp" android:max="100" android:visibility="gone" - tools:visibility="visible"/> + tools:visibility="visible" /> - + - + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/navigation_header.xml b/app/src/main/res/layout/navigation_header.xml new file mode 100644 index 0000000..85dfc4a --- /dev/null +++ b/app/src/main/res/layout/navigation_header.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/menu/main_navigation.xml b/app/src/main/res/menu/main_navigation.xml new file mode 100644 index 0000000..c6abf32 --- /dev/null +++ b/app/src/main/res/menu/main_navigation.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v21/dimens.xml b/app/src/main/res/values-v21/dimens.xml index b2b44cd..95d2f3a 100644 --- a/app/src/main/res/values-v21/dimens.xml +++ b/app/src/main/res/values-v21/dimens.xml @@ -6,5 +6,6 @@ 96dp 64dp 0dp + 20dp \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index 67915d5..e9aec12 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -10,11 +10,4 @@ @android:color/transparent - - - - \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index cce2245..aef9795 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -5,34 +5,6 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 0fb6171..7cb7b61 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,25 +1,20 @@ - 260dp 128dp 16dp - 32dp - 48dp 32dp 8dp 16dp 8dp 360dp 6dp - - 353dp - 89dp - 54dp - -10dp - 56dp - 8dp - 6dp + + 354dp + 90dp + 55dp + -9dp + 8dp \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 6ce558b..c5937d1 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -64,38 +64,12 @@ vertical - - - - - - - -