diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/MergeAdapter.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/MergeAdapter.java
deleted file mode 100644
index 7d8880be..00000000
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/MergeAdapter.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/**
- Copyright (c) 2008-2009 CommonsWare, LLC
- Portions (c) 2009 Google, Inc.
-
- 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 org.moire.ultrasonic.util;
-
-import android.database.DataSetObserver;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListAdapter;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Adapter that merges multiple child adapters and views
- * into a single contiguous whole.
- *
- * Adapters used as pieces within MergeAdapter must
- * have view type IDs monotonically increasing from 0. Ideally,
- * adapters also have distinct ranges for their row ids, as
- * returned by getItemId().
- */
-public class MergeAdapter extends BaseAdapter
-{
- private final CascadeDataSetObserver observer = new CascadeDataSetObserver();
- private final AbstractList pieces = new ArrayList();
-
- /**
- * Adds a new adapter to the roster of things to appear
- * in the aggregate list.
- *
- * @param adapter Source for row views for this section
- */
- public void addAdapter(ListAdapter adapter)
- {
- pieces.add(adapter);
- adapter.registerDataSetObserver(observer);
- }
-
- public void removeAdapter(ListAdapter adapter)
- {
- adapter.unregisterDataSetObserver(observer);
- pieces.remove(adapter);
- }
-
- /**
- * Adds a new View to the roster of things to appear
- * in the aggregate list.
- *
- * @param view Single view to add
- */
- public ListAdapter addView(View view)
- {
- return addView(view, false);
- }
-
- /**
- * Adds a new View to the roster of things to appear
- * in the aggregate list.
- *
- * @param view Single view to add
- * @param enabled false if views are disabled, true if enabled
- */
- public ListAdapter addView(View view, boolean enabled)
- {
- return addViews(Collections.singletonList(view), enabled);
- }
-
- /**
- * Adds a list of views to the roster of things to appear
- * in the aggregate list.
- *
- * @param views List of views to add
- */
- public ListAdapter addViews(List views)
- {
- return addViews(views, false);
- }
-
- /**
- * Adds a list of views to the roster of things to appear
- * in the aggregate list.
- *
- * @param views List of views to add
- * @param enabled false if views are disabled, true if enabled
- */
- public ListAdapter addViews(List views, boolean enabled)
- {
- ListAdapter adapter = enabled ? new EnabledSackAdapter(views) : new SackOfViewsAdapter(views);
- addAdapter(adapter);
- return adapter;
- }
-
- /**
- * Get the data item associated with the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public Object getItem(int position)
- {
- for (ListAdapter piece : pieces)
- {
- int size = piece.getCount();
-
- if (position < size)
- {
- return (piece.getItem(position));
- }
-
- position -= size;
- }
-
- return (null);
- }
-
- /**
- * How many items are in the data set represented by this
- * Adapter.
- */
- @Override
- public int getCount()
- {
- int total = 0;
-
- for (ListAdapter piece : pieces)
- {
- total += piece.getCount();
- }
-
- return (total);
- }
-
- /**
- * Returns the number of types of Views that will be
- * created by getView().
- */
- @Override
- public int getViewTypeCount()
- {
- int total = 0;
-
- for (ListAdapter piece : pieces)
- {
- total += piece.getViewTypeCount();
- }
-
- return (Math.max(total, 1)); // needed for setListAdapter() before content add'
- }
-
- /**
- * Get the type of View that will be created by getView()
- * for the specified item.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public int getItemViewType(int position)
- {
- int typeOffset = 0;
- int result = -1;
-
- for (ListAdapter piece : pieces)
- {
- int size = piece.getCount();
-
- if (position < size)
- {
- result = typeOffset + piece.getItemViewType(position);
- break;
- }
-
- position -= size;
- typeOffset += piece.getViewTypeCount();
- }
-
- return (result);
- }
-
- /**
- * Are all items in this ListAdapter enabled? If yes it
- * means all items are selectable and clickable.
- */
- @Override
- public boolean areAllItemsEnabled()
- {
- return (false);
- }
-
- /**
- * Returns true if the item at the specified position is
- * not a separator.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public boolean isEnabled(int position)
- {
- for (ListAdapter piece : pieces)
- {
- int size = piece.getCount();
-
- if (position < size)
- {
- return (piece.isEnabled(position));
- }
-
- position -= size;
- }
-
- return (false);
- }
-
- /**
- * Get a View that displays the data at the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- * @param convertView View to recycle, if not null
- * @param parent ViewGroup containing the returned View
- */
- @Override
- public View getView(int position, View convertView, ViewGroup parent)
- {
- for (ListAdapter piece : pieces)
- {
- int size = piece.getCount();
-
- if (position < size)
- {
-
- return (piece.getView(position, convertView, parent));
- }
-
- position -= size;
- }
-
- return (null);
- }
-
- /**
- * Get the row id associated with the specified position
- * in the list.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public long getItemId(int position)
- {
- for (ListAdapter piece : pieces)
- {
- int size = piece.getCount();
-
- if (position < size)
- {
- return (piece.getItemId(position));
- }
-
- position -= size;
- }
-
- return (-1);
- }
-
- private static class EnabledSackAdapter extends SackOfViewsAdapter
- {
- public EnabledSackAdapter(List views)
- {
- super(views);
- }
-
- @Override
- public boolean areAllItemsEnabled()
- {
- return (true);
- }
-
- @Override
- public boolean isEnabled(int position)
- {
- return (true);
- }
- }
-
- private class CascadeDataSetObserver extends DataSetObserver
- {
- @Override
- public void onChanged()
- {
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated()
- {
- notifyDataSetInvalidated();
- }
- }
-}
-
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/SackOfViewsAdapter.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/SackOfViewsAdapter.java
deleted file mode 100644
index 080e1430..00000000
--- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/SackOfViewsAdapter.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- Copyright (c) 2008-2009 CommonsWare, LLC
- Portions (c) 2009 Google, Inc.
-
- 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 org.moire.ultrasonic.util;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Adapter that simply returns row views from a list.
- *
- * If you supply a size, you must implement newView(), to
- * create a required view. The adapter will then cache these
- * views.
- *
- * If you supply a list of views in the constructor, that
- * list will be used directly. If any elements in the list
- * are null, then newView() will be called just for those
- * slots.
- *
- * Subclasses may also wish to override areAllItemsEnabled()
- * (default: false) and isEnabled() (default: false), if some
- * of their rows should be selectable.
- *
- * It is assumed each view is unique, and therefore will not
- * get recycled.
- *
- * Note that this adapter is not designed for long lists. It
- * is more for screens that should behave like a list. This
- * is particularly useful if you combine this with other
- * adapters (e.g., SectionedAdapter) that might have an
- * arbitrary number of rows, so it all appears seamless.
- */
-public class SackOfViewsAdapter extends BaseAdapter
-{
- private List views;
-
- /**
- * Constructor creating an empty list of views, but with
- * a specified count. Subclasses must override newView().
- */
- public SackOfViewsAdapter(int count)
- {
- super();
-
- views = new ArrayList(count);
-
- for (int i = 0; i < count; i++)
- {
- views.add(null);
- }
- }
-
- /**
- * Constructor wrapping a supplied list of views.
- * Subclasses must override newView() if any of the elements
- * in the list are null.
- */
- public SackOfViewsAdapter(List views)
- {
- for (View view : views)
- {
- view.setLayoutParams(new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
- }
- this.views = views;
- }
-
- /**
- * Get the data item associated with the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public Object getItem(int position)
- {
- return (views.get(position));
- }
-
- /**
- * How many items are in the data set represented by this
- * Adapter.
- */
- @Override
- public int getCount()
- {
- return (views.size());
- }
-
- /**
- * Returns the number of types of Views that will be
- * created by getView().
- */
- @Override
- public int getViewTypeCount()
- {
- return (getCount());
- }
-
- /**
- * Get the type of View that will be created by getView()
- * for the specified item.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public int getItemViewType(int position)
- {
- return (position);
- }
-
- /**
- * Are all items in this ListAdapter enabled? If yes it
- * means all items are selectable and clickable.
- */
- @Override
- public boolean areAllItemsEnabled()
- {
- return (false);
- }
-
- /**
- * Returns true if the item at the specified position is
- * not a separator.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public boolean isEnabled(int position)
- {
- return (false);
- }
-
- /**
- * Get a View that displays the data at the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- * @param convertView View to recycle, if not null
- * @param parent ViewGroup containing the returned View
- */
- @Override
- public View getView(int position, View convertView, ViewGroup parent)
- {
- View result = views.get(position);
-
- if (result == null)
- {
- result = newView(position, parent);
- views.set(position, result);
- }
-
- return (result);
- }
-
- /**
- * Get the row id associated with the specified position
- * in the list.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public long getItemId(int position)
- {
- return (position);
- }
-
- /**
- * Create a new View to go into the list at the specified
- * position.
- *
- * @param position Position of the item whose data we want
- * @param parent ViewGroup containing the returned View
- */
- protected static View newView(int position, ViewGroup parent)
- {
- throw new RuntimeException("You must override newView()!");
- }
-}
diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt
index 940fb1b5..6969a47f 100644
--- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt
+++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/MainFragment.kt
@@ -4,16 +4,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.AdapterView
-import android.widget.AdapterView.OnItemClickListener
-import android.widget.ListView
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import org.koin.core.component.KoinComponent
import org.moire.ultrasonic.R
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
import org.moire.ultrasonic.util.Constants
-import org.moire.ultrasonic.util.MergeAdapter
import org.moire.ultrasonic.util.Settings
import org.moire.ultrasonic.util.Util
@@ -21,26 +20,26 @@ import org.moire.ultrasonic.util.Util
* Displays the Main screen of Ultrasonic, where the music library can be browsed
*/
class MainFragment : Fragment(), KoinComponent {
- private var list: ListView? = null
- private lateinit var musicTitle: View
- private lateinit var artistsButton: View
- private lateinit var albumsButton: View
- private lateinit var genresButton: View
- private lateinit var videosTitle: View
- private lateinit var songsTitle: View
- private lateinit var randomSongsButton: View
- private lateinit var songsStarredButton: View
- private lateinit var albumsTitle: View
- private lateinit var albumsNewestButton: View
- private lateinit var albumsRandomButton: View
- private lateinit var albumsHighestButton: View
- private lateinit var albumsStarredButton: View
- private lateinit var albumsRecentButton: View
- private lateinit var albumsFrequentButton: View
- private lateinit var albumsAlphaByNameButton: View
- private lateinit var albumsAlphaByArtistButton: View
- private lateinit var videosButton: View
+ private lateinit var list: LinearLayout
+ private lateinit var musicTitle: TextView
+ private lateinit var artistsButton: TextView
+ private lateinit var albumsButton: TextView
+ private lateinit var genresButton: TextView
+ private lateinit var videosTitle: TextView
+ private lateinit var songsTitle: TextView
+ private lateinit var randomSongsButton: TextView
+ private lateinit var songsStarredButton: TextView
+ private lateinit var albumsTitle: TextView
+ private lateinit var albumsNewestButton: TextView
+ private lateinit var albumsRandomButton: TextView
+ private lateinit var albumsHighestButton: TextView
+ private lateinit var albumsStarredButton: TextView
+ private lateinit var albumsRecentButton: TextView
+ private lateinit var albumsFrequentButton: TextView
+ private lateinit var albumsAlphaByNameButton: TextView
+ private lateinit var albumsAlphaByArtistButton: TextView
+ private lateinit var videosButton: TextView
override fun onCreate(savedInstanceState: Bundle?) {
Util.applyTheme(this.context)
@@ -59,8 +58,8 @@ class MainFragment : Fragment(), KoinComponent {
list = view.findViewById(R.id.main_list)
setupButtons()
-
- if (list != null) setupMenuList(list!!)
+ setupClickListener()
+ setupItemVisibility()
super.onViewCreated(view, savedInstanceState)
}
@@ -71,134 +70,128 @@ class MainFragment : Fragment(), KoinComponent {
val currentId3Setting = Settings.shouldUseId3Tags
// If setting has changed...
- if (currentId3Setting != shouldUseId3) {
- shouldUseId3 = currentId3Setting
+ if (currentId3Setting != cachedId3Setting) {
+ cachedId3Setting = currentId3Setting
shouldRestart = true
}
// then setup the list anew.
if (shouldRestart) {
- if (list != null) setupMenuList(list!!)
+ setupItemVisibility()
}
}
private fun setupButtons() {
- val buttons = layoutInflater.inflate(R.layout.main_buttons, list, false)
- musicTitle = buttons.findViewById(R.id.main_music)
- artistsButton = buttons.findViewById(R.id.main_artists_button)
- albumsButton = buttons.findViewById(R.id.main_albums_button)
- genresButton = buttons.findViewById(R.id.main_genres_button)
- videosTitle = buttons.findViewById(R.id.main_videos_title)
- songsTitle = buttons.findViewById(R.id.main_songs)
- randomSongsButton = buttons.findViewById(R.id.main_songs_button)
- songsStarredButton = buttons.findViewById(R.id.main_songs_starred)
- albumsTitle = buttons.findViewById(R.id.main_albums)
- albumsNewestButton = buttons.findViewById(R.id.main_albums_newest)
- albumsRandomButton = buttons.findViewById(R.id.main_albums_random)
- albumsHighestButton = buttons.findViewById(R.id.main_albums_highest)
- albumsStarredButton = buttons.findViewById(R.id.main_albums_starred)
- albumsRecentButton = buttons.findViewById(R.id.main_albums_recent)
- albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent)
- albumsAlphaByNameButton = buttons.findViewById(R.id.main_albums_alphaByName)
- albumsAlphaByArtistButton = buttons.findViewById(R.id.main_albums_alphaByArtist)
- videosButton = buttons.findViewById(R.id.main_videos)
+ musicTitle = list.findViewById(R.id.main_music)
+ artistsButton = list.findViewById(R.id.main_artists_button)
+ albumsButton = list.findViewById(R.id.main_albums_button)
+ genresButton = list.findViewById(R.id.main_genres_button)
+ videosTitle = list.findViewById(R.id.main_videos_title)
+ songsTitle = list.findViewById(R.id.main_songs)
+ randomSongsButton = list.findViewById(R.id.main_songs_button)
+ songsStarredButton = list.findViewById(R.id.main_songs_starred)
+ albumsTitle = list.findViewById(R.id.main_albums)
+ albumsNewestButton = list.findViewById(R.id.main_albums_newest)
+ albumsRandomButton = list.findViewById(R.id.main_albums_random)
+ albumsHighestButton = list.findViewById(R.id.main_albums_highest)
+ albumsStarredButton = list.findViewById(R.id.main_albums_starred)
+ albumsRecentButton = list.findViewById(R.id.main_albums_recent)
+ albumsFrequentButton = list.findViewById(R.id.main_albums_frequent)
+ albumsAlphaByNameButton = list.findViewById(R.id.main_albums_alphaByName)
+ albumsAlphaByArtistButton = list.findViewById(R.id.main_albums_alphaByArtist)
+ videosButton = list.findViewById(R.id.main_videos)
}
- private fun setupMenuList(list: ListView) {
+ private fun setupItemVisibility() {
+ // Cache some values
+ cachedId3Setting = Settings.shouldUseId3Tags
+ val isOnline = !isOffline()
- // TODO: Should use RecyclerView
- val adapter = MergeAdapter()
+ // Music
+ musicTitle.isVisible = true
+ artistsButton.isVisible = true
+ albumsButton.isVisible = isOnline
+ genresButton.isVisible = true
- shouldUseId3 = Settings.shouldUseId3Tags
+ // Songs
+ songsTitle.isVisible = isOnline
+ randomSongsButton.isVisible = true
+ songsStarredButton.isVisible = isOnline
- if (!isOffline()) {
- adapter.addView(musicTitle, false)
- adapter.addViews(listOf(artistsButton, albumsButton, genresButton), true)
- adapter.addView(songsTitle, false)
- adapter.addViews(listOf(randomSongsButton, songsStarredButton), true)
- adapter.addView(albumsTitle, false)
- adapter.addViews(
- listOf(
- albumsNewestButton,
- albumsRecentButton,
- albumsFrequentButton
- ),
- true
- )
- if (!shouldUseId3) {
- adapter.addView(albumsHighestButton, true)
- }
- adapter.addViews(
- listOf(
- albumsRandomButton,
- albumsStarredButton,
- albumsAlphaByNameButton,
- albumsAlphaByArtistButton
- ),
- true
- )
- adapter.addView(videosTitle, false)
- adapter.addViews(listOf(videosButton), true)
- } else {
- // Offline supported calls
- adapter.addView(musicTitle, false)
- adapter.addViews(listOf(artistsButton, genresButton), true)
- adapter.addView(songsTitle, false)
- adapter.addView(randomSongsButton, true)
- }
+ // Albums
+ albumsTitle.isVisible = isOnline
+ albumsNewestButton.isVisible = isOnline
+ albumsRecentButton.isVisible = isOnline
+ albumsFrequentButton.isVisible = isOnline
+ albumsHighestButton.isVisible = isOnline && !cachedId3Setting
+ albumsRandomButton.isVisible = isOnline
+ albumsStarredButton.isVisible = isOnline
+ albumsAlphaByNameButton.isVisible = isOnline
+ albumsAlphaByArtistButton.isVisible = isOnline
- list.adapter = adapter
- list.onItemClickListener = listListener
+ // Videos
+ videosTitle.isVisible = isOnline
+ videosButton.isVisible = isOnline
}
- private val listListener =
- OnItemClickListener { _: AdapterView<*>?, view: View, _: Int, _: Long ->
- when {
- view === albumsNewestButton -> {
- showAlbumList("newest", R.string.main_albums_newest)
- }
- view === albumsRandomButton -> {
- showAlbumList("random", R.string.main_albums_random)
- }
- view === albumsHighestButton -> {
- showAlbumList("highest", R.string.main_albums_highest)
- }
- view === albumsRecentButton -> {
- showAlbumList("recent", R.string.main_albums_recent)
- }
- view === albumsFrequentButton -> {
- showAlbumList("frequent", R.string.main_albums_frequent)
- }
- view === albumsStarredButton -> {
- showAlbumList(Constants.STARRED, R.string.main_albums_starred)
- }
- view === albumsAlphaByNameButton -> {
- showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_alphaByName)
- }
- view === albumsAlphaByArtistButton -> {
- showAlbumList("alphabeticalByArtist", R.string.main_albums_alphaByArtist)
- }
- view === songsStarredButton -> {
- showStarredSongs()
- }
- view === artistsButton -> {
- showArtists()
- }
- view === albumsButton -> {
- showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_title)
- }
- view === randomSongsButton -> {
- showRandomSongs()
- }
- view === genresButton -> {
- showGenres()
- }
- view === videosButton -> {
- showVideos()
- }
- }
+ private fun setupClickListener() {
+ albumsNewestButton.setOnClickListener {
+ showAlbumList("newest", R.string.main_albums_newest)
}
+ albumsRandomButton.setOnClickListener {
+ showAlbumList("random", R.string.main_albums_random)
+ }
+
+ albumsHighestButton.setOnClickListener {
+ showAlbumList("highest", R.string.main_albums_highest)
+ }
+
+ albumsRecentButton.setOnClickListener {
+ showAlbumList("recent", R.string.main_albums_recent)
+ }
+
+ albumsFrequentButton.setOnClickListener {
+ showAlbumList("frequent", R.string.main_albums_frequent)
+ }
+
+ albumsStarredButton.setOnClickListener {
+ showAlbumList(Constants.STARRED, R.string.main_albums_starred)
+ }
+
+ albumsAlphaByNameButton.setOnClickListener {
+ showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_alphaByName)
+ }
+
+ albumsAlphaByArtistButton.setOnClickListener {
+ showAlbumList("alphabeticalByArtist", R.string.main_albums_alphaByArtist)
+ }
+
+ songsStarredButton.setOnClickListener {
+ showStarredSongs()
+ }
+
+ artistsButton.setOnClickListener {
+ showArtists()
+ }
+
+ albumsButton.setOnClickListener {
+ showAlbumList(Constants.ALPHABETICAL_BY_NAME, R.string.main_albums_title)
+ }
+
+ randomSongsButton.setOnClickListener {
+ showRandomSongs()
+ }
+
+ genresButton.setOnClickListener {
+ showGenres()
+ }
+
+ videosButton.setOnClickListener {
+ showVideos()
+ }
+ }
+
private fun showStarredSongs() {
val bundle = Bundle()
bundle.putInt(Constants.INTENT_STARRED, 1)
@@ -242,6 +235,6 @@ class MainFragment : Fragment(), KoinComponent {
}
companion object {
- private var shouldUseId3 = false
+ private var cachedId3Setting = false
}
}
diff --git a/ultrasonic/src/main/res/layout/main.xml b/ultrasonic/src/main/res/layout/main.xml
index dcd8fbd0..e6763155 100644
--- a/ultrasonic/src/main/res/layout/main.xml
+++ b/ultrasonic/src/main/res/layout/main.xml
@@ -1,18 +1,211 @@
+ a:orientation="vertical">
-
+ a:layout_height="wrap_content"
+ a:gravity="center_vertical"
+ a:paddingStart="6dp"
+ a:text="@string/main.music"
+ a:textAllCaps="true"
+ a:textAppearance="?android:attr/textAppearanceSmall"
+ a:textColor="@color/cyan"
+ a:textStyle="bold" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/ultrasonic/src/main/res/layout/main_buttons.xml b/ultrasonic/src/main/res/layout/main_buttons.xml
deleted file mode 100644
index ef1395c7..00000000
--- a/ultrasonic/src/main/res/layout/main_buttons.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-