From 85b2aab3e8471ace33cb34d649a9c2d774f28cc5 Mon Sep 17 00:00:00 2001 From: Duffman Date: Wed, 31 May 2017 17:08:40 -0400 Subject: [PATCH 01/97] Put song title text view into a horizontal scrollview so you can see the full song title on songs with longer song titles --- app/src/main/res/layout/item_list.xml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 791d75875..c27c875ea 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -67,13 +67,20 @@ android:paddingRight="0dp" android:paddingStart="16dp"> - + + + + Date: Thu, 8 Jun 2017 00:49:09 -0400 Subject: [PATCH 02/97] fixed textview not being clickable and made album titles scrollable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Making the text scrollable took away the ripple animations and it’s ability to field the onclicklistener, so I had to recreate and implement ripple animations and on touch from scratch. It works, although not as smoothly as I’d like. Test it out and let me know your thoughts. I’m not sure there’s an easier way to do this, but someone can try and find one. --- .gitignore | 2 + .../adapter/base/MediaEntryViewHolder.java | 35 +++++++++++++++ .../adapter/song/PlayingQueueAdapter.java | 45 ++++++++++++++++++- .../gramophone/adapter/song/SongAdapter.java | 44 ++++++++++++++++++ .../ui/activities/AlbumDetailActivity.java | 3 ++ .../player/card/CardPlayerFragment.java | 45 +++++++++++++++++++ .../player/flat/FlatPlayerFragment.java | 45 +++++++++++++++++++ .../main/res/drawable-v21/rect_selector.xml | 3 +- app/src/main/res/drawable/rect_selector.xml | 6 +-- .../main/res/layout/activity_album_detail.xml | 2 + app/src/main/res/layout/item_list.xml | 10 +++-- app/src/main/res/values/colors.xml | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 13 files changed, 235 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 7574c77b0..fbff0d586 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ captures/ # Mac .DS_Store + +*.gradle diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index 8ad2a3f10..905ba6651 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -1,11 +1,15 @@ package com.kabouzeid.gramophone.adapter.base; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.View; +import android.widget.HorizontalScrollView; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.kabouzeid.gramophone.R; @@ -17,6 +21,10 @@ * @author Karim Abou Zeid (kabouzeid) */ public class MediaEntryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { + @Nullable + @BindView(R.id.song_view) + public LinearLayout songView; + @Nullable @BindView(R.id.image) public ImageView image; @@ -29,6 +37,10 @@ public class MediaEntryViewHolder extends RecyclerView.ViewHolder implements Vie @BindView(R.id.title) public TextView title; + @Nullable + @BindView(R.id.title_scrollview) + public HorizontalScrollView title_scrollview; + @Nullable @BindView(R.id.text) public TextView text; @@ -76,4 +88,27 @@ public boolean onLongClick(View v) { public void onClick(View v) { } + + /** + * Forces a ripple animation in a view at a specified set of coordinates + * @param view the view where the ripple will be contained + * @param x the x coordinate of where the ripple should begin + * @param y the y coordinate where the ripple should begin + */ + public void forceRippleAnimation(View view, int x , int y) + { + Drawable background = view.getBackground(); + + if(Build.VERSION.SDK_INT >= 21 && background instanceof RippleDrawable) + { + final RippleDrawable rippleDrawable = (RippleDrawable) background; + + rippleDrawable.setHotspot(x,y); + + rippleDrawable.setState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}); + + rippleDrawable.setState(new int[]{}); + + } + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java index 1ee58b3e7..b0e7f1c7d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java @@ -4,7 +4,9 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; +import android.view.GestureDetector; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter; @@ -41,7 +43,7 @@ protected SongAdapter.ViewHolder createViewHolder(View view) { } @Override - public void onBindViewHolder(@NonNull SongAdapter.ViewHolder holder, int position) { + public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) { super.onBindViewHolder(holder, position); if (holder.imageText != null) { holder.imageText.setText(String.valueOf(position - current)); @@ -49,6 +51,47 @@ public void onBindViewHolder(@NonNull SongAdapter.ViewHolder holder, int positio if (holder.getItemViewType() == HISTORY || holder.getItemViewType() == CURRENT) { setAlpha(holder, 0.5f); } + //allows the scrollview to be clickable, long clickable and have a ripple animation onclick + if (holder.title_scrollview !=null){ + final GestureDetector gestureDetector = new GestureDetector(activity, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + int x = (int)e.getRawX(); + int y = holder.title_scrollview.getBottom(); + holder.forceRippleAnimation(holder.songView, x, y); + + if (isInQuickSelectMode()) { + toggleChecked(holder.getAdapterPosition()); + } else { + MusicPlayerRemote.openQueue(dataSet, holder.getAdapterPosition(), true); + } + + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + super.onLongPress(e); + int x = (int)e.getRawX(); + int y = holder.title_scrollview.getBottom(); + holder.forceRippleAnimation(holder.songView, x, y); + toggleChecked(holder.getAdapterPosition()); + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + return super.onDoubleTap(e); + } + }); + + holder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + + return gestureDetector.onTouchEvent(event); + } + }); + } } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index ea1094469..d04d4be16 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -6,8 +6,10 @@ import android.support.annotation.Nullable; import android.support.v4.util.Pair; import android.support.v7.app.AppCompatActivity; +import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -110,6 +112,46 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); } + //allows the scrollview to be clickable, long clickable and have a ripple animation onclick + if (holder.title_scrollview !=null){ + final GestureDetector gestureDetector = new GestureDetector(activity, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + int x = (int)e.getRawX(); + int y = holder.title_scrollview.getBottom(); + holder.forceRippleAnimation(holder.songView, x, y); + + if (isInQuickSelectMode()) { + toggleChecked(holder.getAdapterPosition()); + } else { + MusicPlayerRemote.openQueue(dataSet, holder.getAdapterPosition(), true); + } + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + super.onLongPress(e); + int x = (int)e.getRawX(); + int y = holder.title_scrollview.getBottom(); + holder.forceRippleAnimation(holder.songView, x, y); + toggleChecked(holder.getAdapterPosition()); + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + return super.onDoubleTap(e); + } + }); + + holder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + + return gestureDetector.onTouchEvent(event); + } + }); + } if (holder.text != null) { holder.text.setText(getSongText(song)); } @@ -118,6 +160,8 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { } + + private void setColors(int color, ViewHolder holder) { if (holder.paletteColorContainer != null) { holder.paletteColorContainer.setBackgroundColor(color); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index c3929f9d0..f53180979 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -10,6 +10,7 @@ import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; +import android.text.method.ScrollingMovementMethod; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -327,6 +328,8 @@ public void setStatusbarColor(int color) { private void setAlbum(Album album) { this.album = album; loadAlbumCover(); + //allows album title's that are longer then their container to be scrolled horizontally + albumTitleView.setMovementMethod(new ScrollingMovementMethod()); albumTitleView.setText(album.getTitle()); adapter.swapDataSet(album.songs); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java index 46ae480bf..e042ae405 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java @@ -16,9 +16,12 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.TextUtils; +import android.util.Log; +import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; @@ -528,6 +531,48 @@ public void onClick(View v) { } } }); + //allows the scrollview to be clickable, long clickable and have a ripple animation onclick + if (currentSongViewHolder.title_scrollview !=null){ + final GestureDetector gestureDetector = new GestureDetector(fragment.getActivity(), new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + int x = (int)e.getRawX(); + int y = currentSongViewHolder.title_scrollview.getBottom(); + Log.d("on touch position","X = "+Integer.toString(x)+" Y = "+Integer.toString(y)); + currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); + + // toggle the panel + if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); + } else if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } + + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + super.onLongPress(e); + int x = (int)e.getRawX(); + int y = currentSongViewHolder.title_scrollview.getBottom(); + currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + return super.onDoubleTap(e); + } + }); + + currentSongViewHolder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + + return gestureDetector.onTouchEvent(event); + } + }); + } currentSongViewHolder.menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu((AppCompatActivity) fragment.getActivity()) { @Override public Song getSong() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java index 1b07a2f64..22cecf110 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java @@ -15,9 +15,12 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.TextUtils; +import android.util.Log; +import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -510,6 +513,48 @@ public void onClick(View v) { } } }); + //allows the scrollview to be clickable, long clickable and have a ripple animation onclick + if (currentSongViewHolder.title_scrollview !=null){ + final GestureDetector gestureDetector = new GestureDetector(fragment.getActivity(), new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + int x = (int)e.getRawX(); + int y = currentSongViewHolder.title_scrollview.getBottom(); + Log.d("on touch position","X = "+Integer.toString(x)+" Y = "+Integer.toString(y)); + currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); + + // toggle the panel + if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); + } else if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } + + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + super.onLongPress(e); + int x = (int)e.getRawX(); + int y = currentSongViewHolder.title_scrollview.getBottom(); + currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + return super.onDoubleTap(e); + } + }); + + currentSongViewHolder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + + return gestureDetector.onTouchEvent(event); + } + }); + } currentSongViewHolder.menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu((AppCompatActivity) fragment.getActivity()) { @Override public Song getSong() { diff --git a/app/src/main/res/drawable-v21/rect_selector.xml b/app/src/main/res/drawable-v21/rect_selector.xml index f12d9ce1d..a9bdc4343 100644 --- a/app/src/main/res/drawable-v21/rect_selector.xml +++ b/app/src/main/res/drawable-v21/rect_selector.xml @@ -1,5 +1,5 @@ + android:color="@color/ripple_control_lighter"> + \ No newline at end of file diff --git a/app/src/main/res/drawable/rect_selector.xml b/app/src/main/res/drawable/rect_selector.xml index 75e988c0b..950fb518e 100644 --- a/app/src/main/res/drawable/rect_selector.xml +++ b/app/src/main/res/drawable/rect_selector.xml @@ -1,9 +1,9 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 3b313d792..3a21aa348 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -33,6 +33,7 @@ android:layout_height="wrap_content" android:orientation="vertical"> + diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index c27c875ea..de2438474 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -21,10 +21,12 @@ tools:ignore="ContentDescription" /> + android:orientation="horizontal" + android:background="?attr/rectSelector"> + android:paddingStart="16dp" + > @@ -79,7 +83,7 @@ android:fontFamily="sans-serif" android:singleLine="true" android:scrollHorizontally="true" - android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> + android:textAppearance="@style/TextAppearance.AppCompat.Subhead"/> #34000000 - + #60000000 #607d8b #f5f5f5 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4c8eae3c4..e015abbb4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Apr 11 17:46:33 SGT 2017 +#Wed Jun 07 15:02:52 EDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip From f405353fe43b8ac0c8c312d87090597982553a5a Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 01:55:34 -0400 Subject: [PATCH 03/97] Added custom FrameLayout to control Touch Events Added a custom FrameLayout view that intercepts touch events and decides whether to consume them or pass on the touch events to it's children. This gives us control over if the FramLayout or the HorizontalScrollView is the one getting the touch event. --- app/src/main/AndroidManifest.xml | 1 + .../adapter/base/MediaEntryViewHolder.java | 27 +-------- .../adapter/song/PlayingQueueAdapter.java | 43 -------------- .../gramophone/adapter/song/SongAdapter.java | 40 ------------- .../player/card/CardPlayerFragment.java | 45 --------------- .../player/flat/FlatPlayerFragment.java | 45 --------------- .../gramophone/views/CustomFrameLayout.java | 57 +++++++++++++++++++ .../main/res/drawable-v21/rect_selector.xml | 2 +- app/src/main/res/drawable/rect_selector.xml | 2 +- app/src/main/res/layout/item_list.xml | 19 +++++-- 10 files changed, 76 insertions(+), 205 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f7db9ff8e..cda243601 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -180,6 +180,7 @@ android:name=".appshortcuts.AppShortcutLauncherActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:launchMode="singleInstance"/> + diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index 905ba6651..ffcc97539 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -1,7 +1,5 @@ package com.kabouzeid.gramophone.adapter.base; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.RippleDrawable; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -65,7 +63,7 @@ public class MediaEntryViewHolder extends RecyclerView.ViewHolder implements Vie @BindView(R.id.palette_color_container) public View paletteColorContainer; - public MediaEntryViewHolder(View itemView) { + public MediaEntryViewHolder(final View itemView) { super(itemView); ButterKnife.bind(this, itemView); @@ -88,27 +86,4 @@ public boolean onLongClick(View v) { public void onClick(View v) { } - - /** - * Forces a ripple animation in a view at a specified set of coordinates - * @param view the view where the ripple will be contained - * @param x the x coordinate of where the ripple should begin - * @param y the y coordinate where the ripple should begin - */ - public void forceRippleAnimation(View view, int x , int y) - { - Drawable background = view.getBackground(); - - if(Build.VERSION.SDK_INT >= 21 && background instanceof RippleDrawable) - { - final RippleDrawable rippleDrawable = (RippleDrawable) background; - - rippleDrawable.setHotspot(x,y); - - rippleDrawable.setState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}); - - rippleDrawable.setState(new int[]{}); - - } - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java index b0e7f1c7d..4b63782ae 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java @@ -4,9 +4,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; -import android.view.GestureDetector; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter; @@ -51,47 +49,6 @@ public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int p if (holder.getItemViewType() == HISTORY || holder.getItemViewType() == CURRENT) { setAlpha(holder, 0.5f); } - //allows the scrollview to be clickable, long clickable and have a ripple animation onclick - if (holder.title_scrollview !=null){ - final GestureDetector gestureDetector = new GestureDetector(activity, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - int x = (int)e.getRawX(); - int y = holder.title_scrollview.getBottom(); - holder.forceRippleAnimation(holder.songView, x, y); - - if (isInQuickSelectMode()) { - toggleChecked(holder.getAdapterPosition()); - } else { - MusicPlayerRemote.openQueue(dataSet, holder.getAdapterPosition(), true); - } - - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - super.onLongPress(e); - int x = (int)e.getRawX(); - int y = holder.title_scrollview.getBottom(); - holder.forceRippleAnimation(holder.songView, x, y); - toggleChecked(holder.getAdapterPosition()); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return super.onDoubleTap(e); - } - }); - - holder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - - return gestureDetector.onTouchEvent(event); - } - }); - } } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index d04d4be16..415d4d5b5 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -6,10 +6,8 @@ import android.support.annotation.Nullable; import android.support.v4.util.Pair; import android.support.v7.app.AppCompatActivity; -import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -111,46 +109,8 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); - } - //allows the scrollview to be clickable, long clickable and have a ripple animation onclick - if (holder.title_scrollview !=null){ - final GestureDetector gestureDetector = new GestureDetector(activity, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - int x = (int)e.getRawX(); - int y = holder.title_scrollview.getBottom(); - holder.forceRippleAnimation(holder.songView, x, y); - - if (isInQuickSelectMode()) { - toggleChecked(holder.getAdapterPosition()); - } else { - MusicPlayerRemote.openQueue(dataSet, holder.getAdapterPosition(), true); - } - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - super.onLongPress(e); - int x = (int)e.getRawX(); - int y = holder.title_scrollview.getBottom(); - holder.forceRippleAnimation(holder.songView, x, y); - toggleChecked(holder.getAdapterPosition()); - } - @Override - public boolean onDoubleTap(MotionEvent e) { - return super.onDoubleTap(e); - } - }); - holder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - - return gestureDetector.onTouchEvent(event); - } - }); } if (holder.text != null) { holder.text.setText(getSongText(song)); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java index e042ae405..46ae480bf 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java @@ -16,12 +16,9 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.TextUtils; -import android.util.Log; -import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; @@ -531,48 +528,6 @@ public void onClick(View v) { } } }); - //allows the scrollview to be clickable, long clickable and have a ripple animation onclick - if (currentSongViewHolder.title_scrollview !=null){ - final GestureDetector gestureDetector = new GestureDetector(fragment.getActivity(), new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - int x = (int)e.getRawX(); - int y = currentSongViewHolder.title_scrollview.getBottom(); - Log.d("on touch position","X = "+Integer.toString(x)+" Y = "+Integer.toString(y)); - currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); - - // toggle the panel - if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { - fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); - } else if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { - fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); - } - - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - super.onLongPress(e); - int x = (int)e.getRawX(); - int y = currentSongViewHolder.title_scrollview.getBottom(); - currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return super.onDoubleTap(e); - } - }); - - currentSongViewHolder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - - return gestureDetector.onTouchEvent(event); - } - }); - } currentSongViewHolder.menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu((AppCompatActivity) fragment.getActivity()) { @Override public Song getSong() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java index 22cecf110..1b07a2f64 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java @@ -15,12 +15,9 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.TextUtils; -import android.util.Log; -import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -513,48 +510,6 @@ public void onClick(View v) { } } }); - //allows the scrollview to be clickable, long clickable and have a ripple animation onclick - if (currentSongViewHolder.title_scrollview !=null){ - final GestureDetector gestureDetector = new GestureDetector(fragment.getActivity(), new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - int x = (int)e.getRawX(); - int y = currentSongViewHolder.title_scrollview.getBottom(); - Log.d("on touch position","X = "+Integer.toString(x)+" Y = "+Integer.toString(y)); - currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); - - // toggle the panel - if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { - fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); - } else if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { - fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); - } - - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - super.onLongPress(e); - int x = (int)e.getRawX(); - int y = currentSongViewHolder.title_scrollview.getBottom(); - currentSongViewHolder.forceRippleAnimation(currentSongViewHolder.songView, x, y); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return super.onDoubleTap(e); - } - }); - - currentSongViewHolder.title_scrollview.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - - return gestureDetector.onTouchEvent(event); - } - }); - } currentSongViewHolder.menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu((AppCompatActivity) fragment.getActivity()) { @Override public Song getSong() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java new file mode 100644 index 000000000..79b4d4a1d --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java @@ -0,0 +1,57 @@ +package com.kabouzeid.gramophone.views; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +/** + * Created by lincoln on 6/8/17. + */ + +/** + * A custom FrameLayout view that intercepts touch events and decides whether to consume them or + * pass on the touch events to it's children + */ +public class CustomFrameLayout extends FrameLayout { + + + public CustomFrameLayout(@NonNull Context context) { + super(context); + } + + public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + /** + * This intercepts the touch event and, by returning false, passes the touchevent to both itself and it's + * child views (by calling TouchEvent it passes it to itself). However, if the action is ACTION_MOVE it cancels the touch event in itself and + * only gives it to it's children, which, in this case is a HorizontalScrollView + * @param e the intercepted touch event + * @return If this function returns true, the MotionEvent will be intercepted, + * meaning it will be not be passed on to the child, but rather to the onTouchEvent of this View. + */ + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + Log.d("current motion event = ", e.toString()); + + switch (e.getAction()) { + case MotionEvent.ACTION_MOVE: { + MotionEvent eUp = e; + eUp.setAction(MotionEvent.ACTION_CANCEL); + onTouchEvent(eUp); + } + + } + onTouchEvent(e); + return false; + } +} diff --git a/app/src/main/res/drawable-v21/rect_selector.xml b/app/src/main/res/drawable-v21/rect_selector.xml index a9bdc4343..6e43eb2e1 100644 --- a/app/src/main/res/drawable-v21/rect_selector.xml +++ b/app/src/main/res/drawable-v21/rect_selector.xml @@ -1,5 +1,5 @@ + android:color="@color/ripple_material_light"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index de2438474..fd713bea5 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,5 +1,5 @@ - + + + android:orientation="horizontal"> + - \ No newline at end of file + \ No newline at end of file From c33623d2299ce3ea7c1a6878a8652037e46c011e Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 02:22:10 -0400 Subject: [PATCH 04/97] fixed formatting and removed debugging --- .gitignore | 2 ++ .../gramophone/adapter/base/MediaEntryViewHolder.java | 2 +- .../com/kabouzeid/gramophone/views/CustomFrameLayout.java | 4 ---- build.gradle | 6 +++++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index fbff0d586..9c736d013 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ captures/ .DS_Store *.gradle + +build.gradle diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index ffcc97539..e9162b980 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -63,7 +63,7 @@ public class MediaEntryViewHolder extends RecyclerView.ViewHolder implements Vie @BindView(R.id.palette_color_container) public View paletteColorContainer; - public MediaEntryViewHolder(final View itemView) { + public MediaEntryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java index 79b4d4a1d..b6135a5b1 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java @@ -4,7 +4,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; @@ -18,7 +17,6 @@ */ public class CustomFrameLayout extends FrameLayout { - public CustomFrameLayout(@NonNull Context context) { super(context); } @@ -41,7 +39,6 @@ public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - Log.d("current motion event = ", e.toString()); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: { @@ -49,7 +46,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { eUp.setAction(MotionEvent.ACTION_CANCEL); onTouchEvent(eUp); } - } onTouchEvent(e); return false; diff --git a/build.gradle b/build.gradle index 8ccd9c97b..b7452fdd4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,13 @@ buildscript { repositories { jcenter() + maven { + url 'https://maven.google.com' + } + } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:3.0.0-alpha3' } } From b232b399e47a8b45cf85aa891c6302ff1188fe53 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 02:22:23 -0400 Subject: [PATCH 05/97] fixed formatting --- app/src/main/AndroidManifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cda243601..f7db9ff8e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -180,7 +180,6 @@ android:name=".appshortcuts.AppShortcutLauncherActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:launchMode="singleInstance"/> - From 1d990f8436165e4c1905f54b637ff18e9f6d3978 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 12:26:20 -0400 Subject: [PATCH 06/97] Fix Menu Item Click being stolen by parent view --- .../kabouzeid/gramophone/adapter/song/SongAdapter.java | 8 ++++++++ app/src/main/res/layout/item_list.xml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 415d4d5b5..0d0de988a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -8,6 +8,7 @@ import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -201,6 +202,13 @@ public ViewHolder(@NonNull View itemView) { if (menu == null) { return; } + menu.setOnTouchListener(new View.OnTouchListener() + {public boolean onTouch(View v, MotionEvent ev) + { + menu.getParent().requestDisallowInterceptTouchEvent(true); + return false; + } + }); menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) { @Override public Song getSong() { diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index fd713bea5..04ee8645f 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -80,7 +80,7 @@ From f07d337d97896af705278ca722ba2e931bc0415b Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 14:26:36 -0400 Subject: [PATCH 07/97] Fixed Longclick not firing in every spot in the view --- .gitignore | 2 -- .../adapter/base/MediaEntryViewHolder.java | 5 ++++ .../gramophone/views/CustomFrameLayout.java | 29 ++++++++++++++++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 9c736d013..fbff0d586 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,3 @@ captures/ .DS_Store *.gradle - -build.gradle diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index e9162b980..afe305b15 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -11,6 +11,7 @@ import android.widget.TextView; import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.views.CustomFrameLayout; import butterknife.BindView; import butterknife.ButterKnife; @@ -67,6 +68,10 @@ public MediaEntryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); + if(title_scrollview != null && itemView instanceof CustomFrameLayout){ + ((CustomFrameLayout) itemView).getScrollView(title_scrollview); + } + itemView.setOnClickListener(this); itemView.setOnLongClickListener(this); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java index b6135a5b1..bf12415fd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java @@ -1,11 +1,13 @@ package com.kabouzeid.gramophone.views; import android.content.Context; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; /** * Created by lincoln on 6/8/17. @@ -17,6 +19,8 @@ */ public class CustomFrameLayout extends FrameLayout { + private HorizontalScrollView scrollView; + public CustomFrameLayout(@NonNull Context context) { super(context); } @@ -29,18 +33,35 @@ public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, super(context, attrs, defStyleAttr); } + public void getScrollView(HorizontalScrollView view){ + scrollView = view; + } + /** - * This intercepts the touch event and, by returning false, passes the touchevent to both itself and it's - * child views (by calling TouchEvent it passes it to itself). However, if the action is ACTION_MOVE it cancels the touch event in itself and - * only gives it to it's children, which, in this case is a HorizontalScrollView + * This intercepts the touch event and, by returning false and onTouchEvent(), passes the touchevent to both itself and it's + * child views (by calling TouchEvent it passes it to itself). It also detects where the touch was placed + * so that if the touch is not in the scrollview the touch is not passed to the HorizontalScrollView, avoiding + * the child view swallowing up the long click. False is passed to still allow MenuItemClick to happen. + * However, if the action is ACTION_MOVE it cancels the touch event in itself and + * only gives it to it's children, which, in this case is a HorizontalScrollView. * @param e the intercepted touch event * @return If this function returns true, the MotionEvent will be intercepted, * meaning it will be not be passed on to the child, but rather to the onTouchEvent of this View. */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - switch (e.getAction()) { + case MotionEvent.ACTION_DOWN:{ + int x = Math.round(e.getRawX()); + int y = Math.round(e.getRawY()); + Rect scrollViewLocation = new Rect(); + scrollView.getGlobalVisibleRect(scrollViewLocation); + if (!(x > scrollViewLocation.left && x < scrollViewLocation.right + && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { + return false; + } + break; + } case MotionEvent.ACTION_MOVE: { MotionEvent eUp = e; eUp.setAction(MotionEvent.ACTION_CANCEL); From 5e92a74d69aed6f647b04115690a1aee538008ea Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 15:39:38 -0400 Subject: [PATCH 08/97] Reverted gradle changes and changed "get" to "set" --- .../kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java | 2 +- .../java/com/kabouzeid/gramophone/views/CustomFrameLayout.java | 2 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index afe305b15..c5f68de18 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -69,7 +69,7 @@ public MediaEntryViewHolder(View itemView) { ButterKnife.bind(this, itemView); if(title_scrollview != null && itemView instanceof CustomFrameLayout){ - ((CustomFrameLayout) itemView).getScrollView(title_scrollview); + ((CustomFrameLayout) itemView).setScrollView(title_scrollview); } itemView.setOnClickListener(this); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java index bf12415fd..0088fc645 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java @@ -33,7 +33,7 @@ public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, super(context, attrs, defStyleAttr); } - public void getScrollView(HorizontalScrollView view){ + public void setScrollView(HorizontalScrollView view){ scrollView = view; } diff --git a/build.gradle b/build.gradle index b7452fdd4..1a64fa7d0 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0-alpha3' + classpath 'com.android.tools.build:gradle:2.3.1' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e015abbb4..6da6a4732 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip From dc7b7b293afc9fa89c518a18db8639f5e1cbd442 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 15:41:59 -0400 Subject: [PATCH 09/97] more grade reverts --- build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1a64fa7d0..6d2477f78 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,6 @@ buildscript { repositories { jcenter() - maven { - url 'https://maven.google.com' - } } dependencies { From 47430277a9b32b07134f6bd0c50da1f8d303e8d4 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 16:41:51 -0400 Subject: [PATCH 10/97] Changed CustomFrameLayout name to more descriptive name --- .../gramophone/adapter/base/MediaEntryViewHolder.java | 6 +++--- ...tomFrameLayout.java => TouchInterceptFrameLayout.java} | 8 ++++---- app/src/main/res/layout/item_list.xml | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) rename app/src/main/java/com/kabouzeid/gramophone/views/{CustomFrameLayout.java => TouchInterceptFrameLayout.java} (88%) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index c5f68de18..703051514 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -11,7 +11,7 @@ import android.widget.TextView; import com.kabouzeid.gramophone.R; -import com.kabouzeid.gramophone.views.CustomFrameLayout; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import butterknife.BindView; import butterknife.ButterKnife; @@ -68,8 +68,8 @@ public MediaEntryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); - if(title_scrollview != null && itemView instanceof CustomFrameLayout){ - ((CustomFrameLayout) itemView).setScrollView(title_scrollview); + if(title_scrollview != null && itemView instanceof TouchInterceptFrameLayout){ + ((TouchInterceptFrameLayout ) itemView).setScrollView(title_scrollview); } itemView.setOnClickListener(this); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java similarity index 88% rename from app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java rename to app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 0088fc645..f29a30900 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/CustomFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -17,19 +17,19 @@ * A custom FrameLayout view that intercepts touch events and decides whether to consume them or * pass on the touch events to it's children */ -public class CustomFrameLayout extends FrameLayout { +public class TouchInterceptFrameLayout extends FrameLayout { private HorizontalScrollView scrollView; - public CustomFrameLayout(@NonNull Context context) { + public TouchInterceptFrameLayout (@NonNull Context context) { super(context); } - public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + public TouchInterceptFrameLayout (@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } - public CustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + public TouchInterceptFrameLayout (@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 04ee8645f..b89390258 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,5 +1,5 @@ - - \ No newline at end of file + \ No newline at end of file From 585f9e736fbc3b546f930ccf81b7f3763644ebba Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 16:55:14 -0400 Subject: [PATCH 11/97] Added logging --- .../gramophone/views/TouchInterceptFrameLayout.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index f29a30900..84b0062ad 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -5,6 +5,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; @@ -50,24 +51,35 @@ public void setScrollView(HorizontalScrollView view){ */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { + Log.d("Touch Event Intercepted",e.toString()); switch (e.getAction()) { case MotionEvent.ACTION_DOWN:{ + Log.d("ACTION_DOWN?","True"); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); Rect scrollViewLocation = new Rect(); + Log.d("Event X",""); + Log.d("Event Y",""); + Log.d("View Left",""); + Log.d("View Right",""); + Log.d("View Top",""); + Log.d("View Bottom",""); scrollView.getGlobalVisibleRect(scrollViewLocation); if (!(x > scrollViewLocation.left && x < scrollViewLocation.right && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { + Log.d("Outside Scrollview","True"); return false; } break; } case MotionEvent.ACTION_MOVE: { + Log.d("ACTION MOVE","True"); MotionEvent eUp = e; eUp.setAction(MotionEvent.ACTION_CANCEL); onTouchEvent(eUp); } } + Log.d("InterceptTouch Finished","True"); onTouchEvent(e); return false; } From c697fa7abacb24fffce9161803b77c957164eff6 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 17:08:16 -0400 Subject: [PATCH 12/97] Added coordinate logs --- .../gramophone/views/TouchInterceptFrameLayout.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 84b0062ad..9f97f497d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -58,12 +58,12 @@ public boolean onInterceptTouchEvent(MotionEvent e) { int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); Rect scrollViewLocation = new Rect(); - Log.d("Event X",""); - Log.d("Event Y",""); - Log.d("View Left",""); - Log.d("View Right",""); - Log.d("View Top",""); - Log.d("View Bottom",""); + Log.d("Event X",Integer.toString(x)); + Log.d("Event Y",Integer.toString(y)); + Log.d("View Left",Integer.toString(scrollViewLocation.left)); + Log.d("View Right",Integer.toString(scrollViewLocation.right)); + Log.d("View Top",Integer.toString(scrollViewLocation.top)); + Log.d("View Bottom",Integer.toString(scrollViewLocation.bottom)); scrollView.getGlobalVisibleRect(scrollViewLocation); if (!(x > scrollViewLocation.left && x < scrollViewLocation.right && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { From 677d0337c456b2b75b304012a91ad0a0d4d9ad72 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 17:10:54 -0400 Subject: [PATCH 13/97] fixed coordinate logging --- .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 9f97f497d..34b65d3f2 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -58,13 +58,13 @@ public boolean onInterceptTouchEvent(MotionEvent e) { int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); Rect scrollViewLocation = new Rect(); + scrollView.getGlobalVisibleRect(scrollViewLocation); Log.d("Event X",Integer.toString(x)); Log.d("Event Y",Integer.toString(y)); Log.d("View Left",Integer.toString(scrollViewLocation.left)); Log.d("View Right",Integer.toString(scrollViewLocation.right)); Log.d("View Top",Integer.toString(scrollViewLocation.top)); Log.d("View Bottom",Integer.toString(scrollViewLocation.bottom)); - scrollView.getGlobalVisibleRect(scrollViewLocation); if (!(x > scrollViewLocation.left && x < scrollViewLocation.right && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { Log.d("Outside Scrollview","True"); From 0b7c2349676833cf509d2d73b947358c87f30c30 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 18:44:38 -0400 Subject: [PATCH 14/97] Possible fix so it works on all phones --- .../views/TouchInterceptFrameLayout.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 34b65d3f2..6898f5cf0 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -2,8 +2,10 @@ import android.content.Context; import android.graphics.Rect; +import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -20,18 +22,23 @@ */ public class TouchInterceptFrameLayout extends FrameLayout { + private Context c; private HorizontalScrollView scrollView; + private static final int MAX_CLICK_DURATION = 200; public TouchInterceptFrameLayout (@NonNull Context context) { super(context); + c = context; } public TouchInterceptFrameLayout (@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); + c = context; } public TouchInterceptFrameLayout (@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + c = context; } public void setScrollView(HorizontalScrollView view){ @@ -49,6 +56,7 @@ public void setScrollView(HorizontalScrollView view){ * @return If this function returns true, the MotionEvent will be intercepted, * meaning it will be not be passed on to the child, but rather to the onTouchEvent of this View. */ + @RequiresApi(api = Build.VERSION_CODES.N) @Override public boolean onInterceptTouchEvent(MotionEvent e) { Log.d("Touch Event Intercepted",e.toString()); @@ -72,6 +80,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } break; } + case MotionEvent.ACTION_UP: { + long clickDuration = e.getEventTime() - e.getDownTime(); + if(clickDuration < MAX_CLICK_DURATION) { + Log.d("ACTION_UP click?", "true"); + onTouchEvent(e); + return false; + } + break; + } case MotionEvent.ACTION_MOVE: { Log.d("ACTION MOVE","True"); MotionEvent eUp = e; From 0f003adcbfb5c84fcdb66dea442cb3a4cd9554b2 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 19:16:09 -0400 Subject: [PATCH 15/97] Manually forced click --- .../gramophone/views/TouchInterceptFrameLayout.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 6898f5cf0..8ce7c76cd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -84,16 +84,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { long clickDuration = e.getEventTime() - e.getDownTime(); if(clickDuration < MAX_CLICK_DURATION) { Log.d("ACTION_UP click?", "true"); - onTouchEvent(e); - return false; + performContextClick(e.getX(),e.getY()); } break; } case MotionEvent.ACTION_MOVE: { Log.d("ACTION MOVE","True"); - MotionEvent eUp = e; - eUp.setAction(MotionEvent.ACTION_CANCEL); - onTouchEvent(eUp); + MotionEvent eCancel = e; + eCancel.setAction(MotionEvent.ACTION_CANCEL); + onTouchEvent(eCancel); } } Log.d("InterceptTouch Finished","True"); From 8c18349474ea4ef6b8d2b2b16946ffad6a9476bd Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 19:23:16 -0400 Subject: [PATCH 16/97] callonclick manually --- .../java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java | 2 ++ .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 0d0de988a..a3654304f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -6,6 +6,7 @@ import android.support.annotation.Nullable; import android.support.v4.util.Pair; import android.support.v7.app.AppCompatActivity; +import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.MotionEvent; @@ -251,6 +252,7 @@ protected boolean onSongMenuItemClick(MenuItem item) { @Override public void onClick(View v) { + Log.d("OnClick?","True"); if (isInQuickSelectMode()) { toggleChecked(getAdapterPosition()); } else { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 8ce7c76cd..688c94e19 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -84,7 +84,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { long clickDuration = e.getEventTime() - e.getDownTime(); if(clickDuration < MAX_CLICK_DURATION) { Log.d("ACTION_UP click?", "true"); - performContextClick(e.getX(),e.getY()); + callOnClick(); } break; } From d7cfe75ffb9a5e4c9b107bfd18ec337eefd2a40e Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 19:36:24 -0400 Subject: [PATCH 17/97] something different --- .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 688c94e19..df382c9ac 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -84,7 +84,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { long clickDuration = e.getEventTime() - e.getDownTime(); if(clickDuration < MAX_CLICK_DURATION) { Log.d("ACTION_UP click?", "true"); - callOnClick(); + performClick(); } break; } @@ -93,6 +93,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { MotionEvent eCancel = e; eCancel.setAction(MotionEvent.ACTION_CANCEL); onTouchEvent(eCancel); + return false; } } Log.d("InterceptTouch Finished","True"); From f6dd6350284f37582f1d8d0897f774721c54f07f Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 19:47:17 -0400 Subject: [PATCH 18/97] trying to gauge on move --- .../views/TouchInterceptFrameLayout.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index df382c9ac..b735dc66b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -60,13 +60,13 @@ public void setScrollView(HorizontalScrollView view){ @Override public boolean onInterceptTouchEvent(MotionEvent e) { Log.d("Touch Event Intercepted",e.toString()); + int x = Math.round(e.getRawX()); + int y = Math.round(e.getRawY()); + Rect scrollViewLocation = new Rect(); + scrollView.getGlobalVisibleRect(scrollViewLocation); switch (e.getAction()) { case MotionEvent.ACTION_DOWN:{ Log.d("ACTION_DOWN?","True"); - int x = Math.round(e.getRawX()); - int y = Math.round(e.getRawY()); - Rect scrollViewLocation = new Rect(); - scrollView.getGlobalVisibleRect(scrollViewLocation); Log.d("Event X",Integer.toString(x)); Log.d("Event Y",Integer.toString(y)); Log.d("View Left",Integer.toString(scrollViewLocation.left)); @@ -81,19 +81,28 @@ public boolean onInterceptTouchEvent(MotionEvent e) { break; } case MotionEvent.ACTION_UP: { - long clickDuration = e.getEventTime() - e.getDownTime(); - if(clickDuration < MAX_CLICK_DURATION) { - Log.d("ACTION_UP click?", "true"); - performClick(); - } +// long clickDuration = e.getEventTime() - e.getDownTime(); +// if(clickDuration < MAX_CLICK_DURATION) { +// if ((x > scrollViewLocation.left && x < scrollViewLocation.right +// && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { +// Log.d("Outside Scrollview","True"); +// +// return false; +// } +// } break; } case MotionEvent.ACTION_MOVE: { Log.d("ACTION MOVE","True"); + if ((x > scrollViewLocation.left && x < scrollViewLocation.right + && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { + Log.d("Outside Scrollview","True"); + + return false; + } MotionEvent eCancel = e; eCancel.setAction(MotionEvent.ACTION_CANCEL); onTouchEvent(eCancel); - return false; } } Log.d("InterceptTouch Finished","True"); From f5e4aba8af6b578b42cf709537753d5a166eb40d Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 20:37:05 -0400 Subject: [PATCH 19/97] fixed long press when scrolling --- .../views/TouchInterceptFrameLayout.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index b735dc66b..58e6efb94 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -22,9 +22,13 @@ */ public class TouchInterceptFrameLayout extends FrameLayout { - private Context c; + private static Context c; private HorizontalScrollView scrollView; - private static final int MAX_CLICK_DURATION = 200; + private static final int MAX_CLICK_DISTANCE = 15; + + private float pressedX; + private float pressedY; + private boolean stayedWithinClickDistance; public TouchInterceptFrameLayout (@NonNull Context context) { super(context); @@ -66,6 +70,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { scrollView.getGlobalVisibleRect(scrollViewLocation); switch (e.getAction()) { case MotionEvent.ACTION_DOWN:{ + pressedX = e.getX(); + pressedY = e.getY(); Log.d("ACTION_DOWN?","True"); Log.d("Event X",Integer.toString(x)); Log.d("Event Y",Integer.toString(y)); @@ -97,6 +103,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if ((x > scrollViewLocation.left && x < scrollViewLocation.right && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { Log.d("Outside Scrollview","True"); + if (!stayedWithinClickDistance && !(distance(pressedX, pressedY, e.getX(), e.getY()) > MAX_CLICK_DISTANCE)) { + Log.d("scrolling","True"); + stayedWithinClickDistance = false; + MotionEvent eCancel = e; + eCancel.setAction(MotionEvent.ACTION_CANCEL); + onTouchEvent(eCancel); + onTouchEvent(e); + return false; + } return false; } @@ -109,4 +124,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { onTouchEvent(e); return false; } + + private static float distance(float x1, float y1, float x2, float y2) { + float dx = x1 - x2; + float dy = y1 - y2; + float distanceInPx = (float) Math.sqrt(dx * dx + dy * dy); + return pxToDp(distanceInPx); + } + + private static float pxToDp(float px) { + return px / c.getResources().getDisplayMetrics().density; + } } From 76ab6ee228dcd963a5dff2412bf14440fcc35885 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 20:54:02 -0400 Subject: [PATCH 20/97] smaller click distance --- .../views/TouchInterceptFrameLayout.java | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 58e6efb94..03ef27c7f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -23,9 +23,11 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static Context c; + private HorizontalScrollView scrollView; - private static final int MAX_CLICK_DISTANCE = 15; + private Rect scrollViewLocation = new Rect(); + private static final int MAX_CLICK_DISTANCE = 10; private float pressedX; private float pressedY; private boolean stayedWithinClickDistance; @@ -66,12 +68,13 @@ public boolean onInterceptTouchEvent(MotionEvent e) { Log.d("Touch Event Intercepted",e.toString()); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); - Rect scrollViewLocation = new Rect(); scrollView.getGlobalVisibleRect(scrollViewLocation); + boolean isScrollViewLocation = (x > scrollViewLocation.left && x < scrollViewLocation.right + && y > scrollViewLocation.top && y < scrollViewLocation.bottom); + pressedX = e.getX(); + pressedY = e.getY(); switch (e.getAction()) { case MotionEvent.ACTION_DOWN:{ - pressedX = e.getX(); - pressedY = e.getY(); Log.d("ACTION_DOWN?","True"); Log.d("Event X",Integer.toString(x)); Log.d("Event Y",Integer.toString(y)); @@ -79,29 +82,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { Log.d("View Right",Integer.toString(scrollViewLocation.right)); Log.d("View Top",Integer.toString(scrollViewLocation.top)); Log.d("View Bottom",Integer.toString(scrollViewLocation.bottom)); - if (!(x > scrollViewLocation.left && x < scrollViewLocation.right - && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { + if (!isScrollViewLocation) { Log.d("Outside Scrollview","True"); return false; } break; } - case MotionEvent.ACTION_UP: { -// long clickDuration = e.getEventTime() - e.getDownTime(); -// if(clickDuration < MAX_CLICK_DURATION) { -// if ((x > scrollViewLocation.left && x < scrollViewLocation.right -// && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { -// Log.d("Outside Scrollview","True"); -// -// return false; -// } -// } - break; - } case MotionEvent.ACTION_MOVE: { Log.d("ACTION MOVE","True"); - if ((x > scrollViewLocation.left && x < scrollViewLocation.right - && y > scrollViewLocation.top && y < scrollViewLocation.bottom)) { + if (isScrollViewLocation) { Log.d("Outside Scrollview","True"); if (!stayedWithinClickDistance && !(distance(pressedX, pressedY, e.getX(), e.getY()) > MAX_CLICK_DISTANCE)) { Log.d("scrolling","True"); From 896c4f7f243eeb3c54dd04751219afb264758b2b Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Fri, 9 Jun 2017 21:47:52 -0400 Subject: [PATCH 21/97] Potentially fix scroll/tap detection --- .../views/TouchInterceptFrameLayout.java | 126 +++++++----------- 1 file changed, 50 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 03ef27c7f..1565f7ed8 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -2,126 +2,100 @@ import android.content.Context; import android.graphics.Rect; -import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.annotation.RequiresApi; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; /** - * Created by lincoln on 6/8/17. - */ - -/** + * @author Lincoln (theduffmaster) + * * A custom FrameLayout view that intercepts touch events and decides whether to consume them or - * pass on the touch events to it's children + * pass on the touch events to its children. */ public class TouchInterceptFrameLayout extends FrameLayout { - private static Context c; - - private HorizontalScrollView scrollView; - private Rect scrollViewLocation = new Rect(); - private static final int MAX_CLICK_DISTANCE = 10; - private float pressedX; - private float pressedY; - private boolean stayedWithinClickDistance; - public TouchInterceptFrameLayout (@NonNull Context context) { + private HorizontalScrollView mScrollView; + private Rect scrollViewRect = new Rect(); + private float startX; + private boolean isTap; + + public TouchInterceptFrameLayout(@NonNull Context context) { super(context); - c = context; } - public TouchInterceptFrameLayout (@NonNull Context context, @Nullable AttributeSet attrs) { + public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - c = context; } - public TouchInterceptFrameLayout (@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - c = context; } - public void setScrollView(HorizontalScrollView view){ - scrollView = view; + public void setScrollView(HorizontalScrollView view) { + mScrollView = view; } /** - * This intercepts the touch event and, by returning false and onTouchEvent(), passes the touchevent to both itself and it's - * child views (by calling TouchEvent it passes it to itself). It also detects where the touch was placed - * so that if the touch is not in the scrollview the touch is not passed to the HorizontalScrollView, avoiding - * the child view swallowing up the long click. False is passed to still allow MenuItemClick to happen. - * However, if the action is ACTION_MOVE it cancels the touch event in itself and - * only gives it to it's children, which, in this case is a HorizontalScrollView. + * This intercepts the touch event and, by returning false and onTouchEvent(), passes the touchevent + * to both itself and its child views (by calling TouchEvent it passes it to itself). + * It also detects where the touch was placed so that if the touch is not in the scrollview, the + * touch is not passed to the HorizontalScrollView, avoiding the child view swallowing up the long + * click. False is passed to still allow MenuItemClick to happen. + * However, if the action is ACTION_MOVE, it cancels the touch event in itself and + * only gives it to its children, which, in this case is a HorizontalScrollView. + * * @param e the intercepted touch event * @return If this function returns true, the MotionEvent will be intercepted, * meaning it will be not be passed on to the child, but rather to the onTouchEvent of this View. */ - @RequiresApi(api = Build.VERSION_CODES.N) @Override public boolean onInterceptTouchEvent(MotionEvent e) { - Log.d("Touch Event Intercepted",e.toString()); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); - scrollView.getGlobalVisibleRect(scrollViewLocation); - boolean isScrollViewLocation = (x > scrollViewLocation.left && x < scrollViewLocation.right - && y > scrollViewLocation.top && y < scrollViewLocation.bottom); - pressedX = e.getX(); - pressedY = e.getY(); + mScrollView.getGlobalVisibleRect(scrollViewRect); + + boolean touchedScrollView = + x > scrollViewRect.left && x < scrollViewRect.right && + y > scrollViewRect.top && y < scrollViewRect.bottom; + switch (e.getAction()) { - case MotionEvent.ACTION_DOWN:{ - Log.d("ACTION_DOWN?","True"); - Log.d("Event X",Integer.toString(x)); - Log.d("Event Y",Integer.toString(y)); - Log.d("View Left",Integer.toString(scrollViewLocation.left)); - Log.d("View Right",Integer.toString(scrollViewLocation.right)); - Log.d("View Top",Integer.toString(scrollViewLocation.top)); - Log.d("View Bottom",Integer.toString(scrollViewLocation.bottom)); - if (!isScrollViewLocation) { - Log.d("Outside Scrollview","True"); - return false; + case MotionEvent.ACTION_DOWN: + if (!touchedScrollView) { + return false; } + startX = e.getX(); + onTouchEvent(e); + isTap = true; + break; - } - case MotionEvent.ACTION_MOVE: { - Log.d("ACTION MOVE","True"); - if (isScrollViewLocation) { - Log.d("Outside Scrollview","True"); - if (!stayedWithinClickDistance && !(distance(pressedX, pressedY, e.getX(), e.getY()) > MAX_CLICK_DISTANCE)) { - Log.d("scrolling","True"); - stayedWithinClickDistance = false; + + case MotionEvent.ACTION_MOVE: + if (touchedScrollView) { + float distance = Math.abs(e.getX() - startX); + + // Scrolling the view: cancel event to prevent long press + if (distance > MAX_CLICK_DISTANCE) { MotionEvent eCancel = e; eCancel.setAction(MotionEvent.ACTION_CANCEL); onTouchEvent(eCancel); - onTouchEvent(e); - return false; + isTap = false; } + } + break; - return false; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (touchedScrollView && isTap) { + onTouchEvent(e); } - MotionEvent eCancel = e; - eCancel.setAction(MotionEvent.ACTION_CANCEL); - onTouchEvent(eCancel); - } + break; } - Log.d("InterceptTouch Finished","True"); - onTouchEvent(e); - return false; - } - private static float distance(float x1, float y1, float x2, float y2) { - float dx = x1 - x2; - float dy = y1 - y2; - float distanceInPx = (float) Math.sqrt(dx * dx + dy * dy); - return pxToDp(distanceInPx); - } - - private static float pxToDp(float px) { - return px / c.getResources().getDisplayMetrics().density; + return false; } } From ebf0d0e5e59e8843df140e4538e78817e5eabe29 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 9 Jun 2017 22:05:06 -0400 Subject: [PATCH 22/97] Added case for devices that call ACTION_MOVE on clicks --- .../java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java | 2 -- .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 1 - 2 files changed, 3 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index a3654304f..0d0de988a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -6,7 +6,6 @@ import android.support.annotation.Nullable; import android.support.v4.util.Pair; import android.support.v7.app.AppCompatActivity; -import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.MotionEvent; @@ -252,7 +251,6 @@ protected boolean onSongMenuItemClick(MenuItem item) { @Override public void onClick(View v) { - Log.d("OnClick?","True"); if (isInQuickSelectMode()) { toggleChecked(getAdapterPosition()); } else { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 1565f7ed8..150c39621 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -88,7 +88,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } break; - case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (touchedScrollView && isTap) { onTouchEvent(e); From f35bd92cce33e96cb68832ce8414e2f6fc901871 Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Fri, 9 Jun 2017 22:36:56 -0400 Subject: [PATCH 23/97] Minor cleanups --- .gitignore | 2 -- .../adapter/base/MediaEntryViewHolder.java | 5 ++--- .../gramophone/adapter/song/SongAdapter.java | 17 +++++--------- .../ui/activities/AlbumDetailActivity.java | 2 +- app/src/main/res/drawable/rect_selector.xml | 6 ++--- .../main/res/layout/activity_album_detail.xml | 2 -- app/src/main/res/layout/item_list.xml | 22 +++++++++---------- app/src/main/res/values/colors.xml | 1 - build.gradle | 1 - gradle/wrapper/gradle-wrapper.properties | 2 +- 10 files changed, 23 insertions(+), 37 deletions(-) diff --git a/.gitignore b/.gitignore index fbff0d586..7574c77b0 100644 --- a/.gitignore +++ b/.gitignore @@ -40,5 +40,3 @@ captures/ # Mac .DS_Store - -*.gradle diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index 703051514..b0933a47b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -68,8 +68,8 @@ public MediaEntryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); - if(title_scrollview != null && itemView instanceof TouchInterceptFrameLayout){ - ((TouchInterceptFrameLayout ) itemView).setScrollView(title_scrollview); + if (title_scrollview != null && itemView instanceof TouchInterceptFrameLayout) { + ((TouchInterceptFrameLayout) itemView).setScrollView(title_scrollview); } itemView.setOnClickListener(this); @@ -89,6 +89,5 @@ public boolean onLongClick(View v) { @Override public void onClick(View v) { - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 0d0de988a..2f3c172d7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -110,19 +110,14 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); - - } if (holder.text != null) { holder.text.setText(getSongText(song)); } loadAlbumCover(song, holder); - } - - private void setColors(int color, ViewHolder holder) { if (holder.paletteColorContainer != null) { holder.paletteColorContainer.setBackgroundColor(color); @@ -202,12 +197,12 @@ public ViewHolder(@NonNull View itemView) { if (menu == null) { return; } - menu.setOnTouchListener(new View.OnTouchListener() - {public boolean onTouch(View v, MotionEvent ev) - { - menu.getParent().requestDisallowInterceptTouchEvent(true); - return false; - } + menu.setOnTouchListener(new View.OnTouchListener() { + public boolean onTouch(View v, MotionEvent ev) + { + menu.getParent().requestDisallowInterceptTouchEvent(true); + return false; + } }); menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) { @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index f53180979..6e94a37ba 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -328,7 +328,7 @@ public void setStatusbarColor(int color) { private void setAlbum(Album album) { this.album = album; loadAlbumCover(); - //allows album title's that are longer then their container to be scrolled horizontally + // Allows album titles that are longer then the container to be scrolled horizontally albumTitleView.setMovementMethod(new ScrollingMovementMethod()); albumTitleView.setText(album.getTitle()); adapter.swapDataSet(album.songs); diff --git a/app/src/main/res/drawable/rect_selector.xml b/app/src/main/res/drawable/rect_selector.xml index aa8ad0864..75e988c0b 100644 --- a/app/src/main/res/drawable/rect_selector.xml +++ b/app/src/main/res/drawable/rect_selector.xml @@ -1,9 +1,9 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 3a21aa348..3b313d792 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -33,7 +33,6 @@ android:layout_height="wrap_content" android:orientation="vertical"> - diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index b89390258..45eed1ecf 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,9 +1,9 @@ - @@ -24,9 +24,8 @@ android:id="@+id/empty_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@android:color/background_dark" android:alpha="0" - /> + android:background="@android:color/background_dark" /> + android:paddingStart="16dp"> + android:singleLine="true" + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> @@ -105,6 +102,7 @@ android:singleLine="true" android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textColor="?android:textColorSecondary" /> + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 431a7c648..b343490bf 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,7 +1,6 @@ #34000000 - #60000000 #607d8b #f5f5f5 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 6d2477f78..8ccd9c97b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,6 @@ buildscript { repositories { jcenter() - } dependencies { classpath 'com.android.tools.build:gradle:2.3.1' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6da6a4732..4c8eae3c4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Wed Jun 07 15:02:52 EDT 2017 +#Tue Apr 11 17:46:33 SGT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From df46c8ea3ef0be916f3718ab08acf353541667c0 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 02:21:48 -0400 Subject: [PATCH 24/97] Fixed weird behavior in PlayingQueue and on Vertical Scrolling. Added truncated text unless scrolled. Added proper documentation and error catching. --- .../adapter/base/MediaEntryViewHolder.java | 4 +- .../adapter/song/ArtistSongAdapter.java | 7 +- .../gramophone/adapter/song/SongAdapter.java | 6 + .../ui/activities/AlbumDetailActivity.java | 21 ++- .../player/card/CardPlayerFragment.java | 4 + .../player/flat/FlatPlayerFragment.java | 4 + .../views/TouchInterceptFrameLayout.java | 160 ++++++++++++++---- .../main/res/layout/activity_album_detail.xml | 33 +++- app/src/main/res/layout/item_list.xml | 6 +- app/src/main/res/values/strings.xml | 2 + 10 files changed, 193 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index b0933a47b..c735d547c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -68,8 +68,8 @@ public MediaEntryViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); - if (title_scrollview != null && itemView instanceof TouchInterceptFrameLayout) { - ((TouchInterceptFrameLayout) itemView).setScrollView(title_scrollview); + if (title_scrollview != null && title != null && itemView instanceof TouchInterceptFrameLayout) { + ((TouchInterceptFrameLayout) itemView).setScrollViews(title_scrollview,title); } itemView.setOnClickListener(this); diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java index c14b72020..bc8b4d8c5 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java @@ -11,6 +11,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.TextView; @@ -24,6 +25,7 @@ import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.util.NavigationUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import java.util.ArrayList; @@ -66,7 +68,8 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_list, parent, false); } - + final TouchInterceptFrameLayout container = (TouchInterceptFrameLayout) convertView.findViewById(R.id.container); + final HorizontalScrollView songTitleScrollView = (HorizontalScrollView) convertView.findViewById(R.id.title_scrollview); final TextView songTitle = (TextView) convertView.findViewById(R.id.title); final TextView songInfo = (TextView) convertView.findViewById(R.id.text); final ImageView albumArt = (ImageView) convertView.findViewById(R.id.image); @@ -84,6 +87,8 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa songTitle.setText(song.title); songInfo.setText(song.albumName); + container.setScrollViews(songTitleScrollView,songTitle); + container.setTruncateText(song.title); SongGlideRequest.Builder.from(Glide.with(activity), song) .checkIgnoreMediaStore(activity).build() diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 2f3c172d7..6b90b3924 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -28,6 +28,7 @@ import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.NavigationUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView; import java.util.ArrayList; @@ -110,7 +111,12 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); + + if (holder.title_scrollview != null && holder.itemView instanceof TouchInterceptFrameLayout) { + ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(getSongTitle(song)); + } } + if (holder.text != null) { holder.text.setText(getSongText(song)); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 6e94a37ba..5028d9024 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -10,11 +10,12 @@ import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; -import android.text.method.ScrollingMovementMethod; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.HorizontalScrollView; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import com.afollestad.materialcab.MaterialCab; @@ -46,6 +47,7 @@ import com.kabouzeid.gramophone.util.PhonographColorUtil; import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import butterknife.BindView; import butterknife.ButterKnife; @@ -63,6 +65,8 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements private Album album; + @BindView(R.id.container) + TouchInterceptFrameLayout container; @BindView(R.id.list) ObservableRecyclerView recyclerView; @BindView(R.id.image) @@ -70,7 +74,11 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.title) - TextView albumTitleView; + RelativeLayout albumTitleView; + @BindView(R.id.album_title) + TextView albumTitleTextView; + @BindView(R.id.title_scrollview) + HorizontalScrollView titleScrollView; @BindView(R.id.list_background) View songsBackgroundView; @BindView(R.id.status_bar) @@ -177,8 +185,7 @@ public void onColorReady(int color) { private void setColors(int color) { toolbarColor = color; albumTitleView.setBackgroundColor(color); - albumTitleView.setTextColor(MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(color))); - + albumTitleTextView.setTextColor(MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(color))); setNavigationbarColor(color); setTaskDescriptionColor(color); } @@ -328,9 +335,9 @@ public void setStatusbarColor(int color) { private void setAlbum(Album album) { this.album = album; loadAlbumCover(); - // Allows album titles that are longer then the container to be scrolled horizontally - albumTitleView.setMovementMethod(new ScrollingMovementMethod()); - albumTitleView.setText(album.getTitle()); + albumTitleTextView.setText(album.getTitle()); + container.setScrollViews(titleScrollView, albumTitleTextView); + container.setTruncateText(album.getTitle()); adapter.swapDataSet(album.songs); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java index 46ae480bf..d7ae90aea 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java @@ -48,6 +48,7 @@ import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.kabouzeid.gramophone.views.WidthFitSquareLayout; import com.sothree.slidinguppanel.SlidingUpPanelLayout; @@ -574,6 +575,9 @@ public void updateCurrentSong(Song song) { currentSong = song; currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); + TouchInterceptFrameLayout itemView = (TouchInterceptFrameLayout) currentSongViewHolder.itemView; + itemView.setScrollViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); + itemView.setTruncateText(song.title); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java index 1b07a2f64..50ca7ec3b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java @@ -46,6 +46,7 @@ import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.kabouzeid.gramophone.views.WidthFitSquareLayout; import com.sothree.slidinguppanel.SlidingUpPanelLayout; @@ -555,6 +556,9 @@ public void updateCurrentSong(Song song) { currentSong = song; currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); + TouchInterceptFrameLayout itemView = (TouchInterceptFrameLayout) currentSongViewHolder.itemView; + itemView.setScrollViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); + itemView.setTruncateText(song.title); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 150c39621..1473868e2 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -4,10 +4,15 @@ import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.text.TextUtils; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; +import android.widget.TextView; + +import com.kabouzeid.gramophone.R; /** * @author Lincoln (theduffmaster) @@ -17,27 +22,89 @@ */ public class TouchInterceptFrameLayout extends FrameLayout { - private static final int MAX_CLICK_DISTANCE = 10; + private static final int MAX_CLICK_DISTANCE = 5; + private static final int MAX_VERTICAL_DISTANCE = 5; + + private Context c; - private HorizontalScrollView mScrollView; + private String TAG; + private String NULL_VIEWS_EXCEPTION_MESSAGE; + + private HorizontalScrollView scrollView; + private TextView textView; private Rect scrollViewRect = new Rect(); private float startX; + private float startY; private boolean isTap; + private String songTruncated; + private String song; public TouchInterceptFrameLayout(@NonNull Context context) { super(context); + c= context; + TAG = c.getResources().getString(R.string.TOUCH_INTERCEPT_FRAME_LAYOUT_TAG); + NULL_VIEWS_EXCEPTION_MESSAGE = c.getResources().getString(R.string.NULL_VIEWS_EXCEPTION_MESSAGE); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); + c= context; + TAG = c.getResources().getString(R.string.TOUCH_INTERCEPT_FRAME_LAYOUT_TAG); + NULL_VIEWS_EXCEPTION_MESSAGE = c.getResources().getString(R.string.NULL_VIEWS_EXCEPTION_MESSAGE); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + c= context; + TAG = c.getResources().getString(R.string.TOUCH_INTERCEPT_FRAME_LAYOUT_TAG); + NULL_VIEWS_EXCEPTION_MESSAGE = c.getResources().getString(R.string.NULL_VIEWS_EXCEPTION_MESSAGE); + } + + /** + * Fetches the HorizontalScrollView contained by this FrameLayout and also gets the + * TextView that is contained within that HorizontalScrollView. + * Must be called before setTruncateText. + * Call this when you are assigning views in your layout. + * @param sv The HorizontalScrollView containing text that needs to be scrolled + * @param tv The TextView that needs to be scrolled (typically song or album title) + */ + public void setScrollViews(HorizontalScrollView sv, TextView tv) { + scrollView = sv; + textView = tv; } - public void setScrollView(HorizontalScrollView view) { - mScrollView = view; + /** + * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. + * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView + * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. + * Must be called after setScrollViews or it will throw a NullPointerException. + * Call this when setting the song title during view creation. + * + * If this is never called then the text will never be truncated and will remain + * cut off, still allowing the HorizontalScrollingView to scroll. + * @param s The string (song title or album title typically) contained by the text view. + */ + public void setTruncateText(String s){ + song = s; + try { + //runs after scrollview has been drawn + scrollView.post(new Runnable() { + @Override + public void run() { + String sT = TextUtils.ellipsize(song, + textView.getPaint(), + (float) scrollView.getWidth(), + TextUtils.TruncateAt.END).toString(); + songTruncated = sT; + if (!sT.isEmpty()) { + textView.setText(sT); + } + } + }); + }catch (NullPointerException exception){ + Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e(TAG, exception.toString()); + } } /** @@ -57,44 +124,69 @@ public void setScrollView(HorizontalScrollView view) { public boolean onInterceptTouchEvent(MotionEvent e) { int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); - mScrollView.getGlobalVisibleRect(scrollViewRect); + try { + scrollView.getGlobalVisibleRect(scrollViewRect); - boolean touchedScrollView = - x > scrollViewRect.left && x < scrollViewRect.right && - y > scrollViewRect.top && y < scrollViewRect.bottom; + boolean touchedScrollView = + x > scrollViewRect.left && x < scrollViewRect.right && + y > scrollViewRect.top && y < scrollViewRect.bottom; - switch (e.getAction()) { - case MotionEvent.ACTION_DOWN: - if (!touchedScrollView) { - return false; - } - startX = e.getX(); - onTouchEvent(e); - isTap = true; + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: + if (!touchedScrollView) return false; - break; + startX = e.getX(); + startY = e.getY(); + isTap = true; + onTouchEvent(e); - case MotionEvent.ACTION_MOVE: - if (touchedScrollView) { - float distance = Math.abs(e.getX() - startX); + if (!songTruncated.isEmpty()){ + textView.setText(song); + Log.e("E/TouchInterceptFL","songTruncated is empty or null. Did you remember " + + "to set the song string when setting the song name in your text view?"); + } - // Scrolling the view: cancel event to prevent long press - if (distance > MAX_CLICK_DISTANCE) { - MotionEvent eCancel = e; - eCancel.setAction(MotionEvent.ACTION_CANCEL); - onTouchEvent(eCancel); + break; + + case MotionEvent.ACTION_MOVE: + float distanceY = Math.abs(e.getY() - startY); + if (touchedScrollView) { + float distance = Math.abs(e.getX() - startX); + + // Scrolling the view: cancel event to prevent long press + if (distance > MAX_CLICK_DISTANCE) { + cancelPendingInputEvents(); + cancelLongPress(); + scrollView.cancelLongPress(); + scrollView.cancelPendingInputEvents(); + isTap = false; + } + } + // Scrolling vertically: cancel horizontal scrolling events + if (distanceY > MAX_VERTICAL_DISTANCE) { + cancelLongPress(); + cancelPendingInputEvents(); + scrollView.cancelLongPress(); + scrollView.cancelPendingInputEvents(); isTap = false; } - } - break; + break; - case MotionEvent.ACTION_UP: - if (touchedScrollView && isTap) { - onTouchEvent(e); - } - break; + case MotionEvent.ACTION_UP: + if (touchedScrollView) { + if (isTap) onTouchEvent(e); + if (!songTruncated.isEmpty()) textView.setText(songTruncated); + } + break; + } + return false; + + }catch (NullPointerException exception) { + Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e(TAG, exception.toString()); + onTouchEvent(e); + return false; } - - return false; } + } diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 3b313d792..94a088d42 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -1,6 +1,8 @@ - @@ -33,20 +35,37 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + > + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 45eed1ecf..55f7af556 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -2,6 +2,7 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 50f7c06eb..123726fbf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -298,4 +298,6 @@ @string/last_added @string/last_added Playlist is empty + Did you forget to call setScrollViews when creating your FrameLayout? Either textView or scrollView is null. + E/TouchInterceptFL From 0baa2e0702823b2b75633312eb09eb187824b7b7 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 04:26:17 -0400 Subject: [PATCH 25/97] Move truncating error log --- .../views/TouchInterceptFrameLayout.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 1473868e2..9519064c3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -131,21 +131,21 @@ public boolean onInterceptTouchEvent(MotionEvent e) { x > scrollViewRect.left && x < scrollViewRect.right && y > scrollViewRect.top && y < scrollViewRect.bottom; + boolean emptyTruncateText = songTruncated.isEmpty(); + boolean isTextTruncated = songTruncated.endsWith("…"); + switch (e.getAction()) { case MotionEvent.ACTION_DOWN: - if (!touchedScrollView) return false; + if (!touchedScrollView || (!emptyTruncateText && !isTextTruncated)){ + scrollView.cancelPendingInputEvents(); + return false; + } startX = e.getX(); startY = e.getY(); isTap = true; onTouchEvent(e); - if (!songTruncated.isEmpty()){ - textView.setText(song); - Log.e("E/TouchInterceptFL","songTruncated is empty or null. Did you remember " + - "to set the song string when setting the song name in your text view?"); - } - break; case MotionEvent.ACTION_MOVE: @@ -155,6 +155,12 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { + if (!emptyTruncateText){ + textView.setText(song); + }else{ + Log.e("E/TouchInterceptFL","songTruncated is empty or null. Did you remember " + + "to set the song string when setting the song name in your text view?"); + } cancelPendingInputEvents(); cancelLongPress(); scrollView.cancelLongPress(); @@ -175,7 +181,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_UP: if (touchedScrollView) { if (isTap) onTouchEvent(e); - if (!songTruncated.isEmpty()) textView.setText(songTruncated); + if ((!emptyTruncateText && !isTextTruncated)) textView.setText(songTruncated); } break; } From 0738982c6ec8ae8848f35d7481d839c430222b9f Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 04:28:26 -0400 Subject: [PATCH 26/97] See above commit --- .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 9519064c3..ae362c768 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -181,7 +181,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_UP: if (touchedScrollView) { if (isTap) onTouchEvent(e); - if ((!emptyTruncateText && !isTextTruncated)) textView.setText(songTruncated); + //uncomment if you want text to retrunucate + //if ((!emptyTruncateText && !isTextTruncated)) textView.setText(songTruncated); } break; } From ba6a88e751463a1432ba01a5199b96a0297790ac Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 04:34:04 -0400 Subject: [PATCH 27/97] Fixed more error reporting --- .../views/TouchInterceptFrameLayout.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index ae362c768..8892c152f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -136,7 +136,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { switch (e.getAction()) { case MotionEvent.ACTION_DOWN: - if (!touchedScrollView || (!emptyTruncateText && !isTextTruncated)){ + if (!touchedScrollView){ scrollView.cancelPendingInputEvents(); return false; } @@ -155,11 +155,13 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { - if (!emptyTruncateText){ - textView.setText(song); - }else{ - Log.e("E/TouchInterceptFL","songTruncated is empty or null. Did you remember " + - "to set the song string when setting the song name in your text view?"); + if (isTextTruncated) { + if (!emptyTruncateText) { + textView.setText(song); + } else { + Log.e("E/TouchInterceptFL", "songTruncated is empty or null. Did you remember " + + "to set the song string when setting the song name in your text view?"); + } } cancelPendingInputEvents(); cancelLongPress(); From 0c22e8efd5b1cc27545fed2572e8fb0cb0a811d6 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 13:32:18 -0400 Subject: [PATCH 28/97] Added Arkon's suggestions and added setTruncateText to SearchAdapter --- .../gramophone/adapter/SearchAdapter.java | 7 +++ .../adapter/base/MediaEntryViewHolder.java | 2 +- .../adapter/song/ArtistSongAdapter.java | 2 +- .../ui/activities/AlbumDetailActivity.java | 2 +- .../player/card/CardPlayerFragment.java | 2 +- .../player/flat/FlatPlayerFragment.java | 2 +- .../views/TouchInterceptFrameLayout.java | 60 +++++++++---------- 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java index b4490349c..4f6a2bc7e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java @@ -26,6 +26,7 @@ import com.kabouzeid.gramophone.util.ArtistSignatureUtil; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.NavigationUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import java.util.ArrayList; import java.util.List; @@ -76,6 +77,8 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { case ALBUM: final Album album = (Album) dataSet.get(position); holder.title.setText(album.getTitle()); + if(holder.itemView instanceof TouchInterceptFrameLayout) + ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(album.getTitle()); holder.text.setText(album.getArtistName()); SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) .checkIgnoreMediaStore(activity).build() @@ -84,6 +87,8 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { case ARTIST: final Artist artist = (Artist) dataSet.get(position); holder.title.setText(artist.getName()); + if(holder.itemView instanceof TouchInterceptFrameLayout) + ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(artist.getName()); holder.text.setText(MusicUtil.getArtistInfoString(activity, artist)); Glide.with(activity) .load(new ArtistImage(artist.getName(), false)) @@ -98,6 +103,8 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { case SONG: final Song song = (Song) dataSet.get(position); holder.title.setText(song.title); + if(holder.itemView instanceof TouchInterceptFrameLayout) + ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(song.title); holder.text.setText(song.albumName); break; default: diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index c735d547c..7ac0ef924 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -69,7 +69,7 @@ public MediaEntryViewHolder(View itemView) { ButterKnife.bind(this, itemView); if (title_scrollview != null && title != null && itemView instanceof TouchInterceptFrameLayout) { - ((TouchInterceptFrameLayout) itemView).setScrollViews(title_scrollview,title); + ((TouchInterceptFrameLayout) itemView).setViews(title_scrollview,title); } itemView.setOnClickListener(this); diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java index bc8b4d8c5..b2febf154 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java @@ -87,7 +87,7 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa songTitle.setText(song.title); songInfo.setText(song.albumName); - container.setScrollViews(songTitleScrollView,songTitle); + container.setViews(songTitleScrollView,songTitle); container.setTruncateText(song.title); SongGlideRequest.Builder.from(Glide.with(activity), song) diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 5028d9024..c88c7ca99 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -336,7 +336,7 @@ private void setAlbum(Album album) { this.album = album; loadAlbumCover(); albumTitleTextView.setText(album.getTitle()); - container.setScrollViews(titleScrollView, albumTitleTextView); + container.setViews(titleScrollView, albumTitleTextView); container.setTruncateText(album.getTitle()); adapter.swapDataSet(album.songs); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java index d7ae90aea..000fb1ad3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java @@ -576,7 +576,7 @@ public void updateCurrentSong(Song song) { currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); TouchInterceptFrameLayout itemView = (TouchInterceptFrameLayout) currentSongViewHolder.itemView; - itemView.setScrollViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); + itemView.setViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); itemView.setTruncateText(song.title); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java index 50ca7ec3b..e526144a7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java @@ -557,7 +557,7 @@ public void updateCurrentSong(Song song) { currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); TouchInterceptFrameLayout itemView = (TouchInterceptFrameLayout) currentSongViewHolder.itemView; - itemView.setScrollViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); + itemView.setViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); itemView.setTruncateText(song.title); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 8892c152f..c5c0315a9 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -27,8 +27,11 @@ public class TouchInterceptFrameLayout extends FrameLayout { private Context c; - private String TAG; - private String NULL_VIEWS_EXCEPTION_MESSAGE; + private String TAG = "E/TouchInterceptFL"; + private String NULL_VIEWS_EXCEPTION_MESSAGE = "Did you forget to call setViews" + "" + + "when creating your FrameLayout? Either textView or scrollView is null."; + private String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + + "to set the song string when setting the song name in your text view?"; private HorizontalScrollView scrollView; private TextView textView; @@ -68,7 +71,7 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe * @param sv The HorizontalScrollView containing text that needs to be scrolled * @param tv The TextView that needs to be scrolled (typically song or album title) */ - public void setScrollViews(HorizontalScrollView sv, TextView tv) { + public void setViews(HorizontalScrollView sv, TextView tv) { scrollView = sv; textView = tv; } @@ -77,7 +80,7 @@ public void setScrollViews(HorizontalScrollView sv, TextView tv) { * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. - * Must be called after setScrollViews or it will throw a NullPointerException. + * Must be called after setViews or it will throw a NullPointerException. * Call this when setting the song title during view creation. * * If this is never called then the text will never be truncated and will remain @@ -132,6 +135,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { y > scrollViewRect.top && y < scrollViewRect.bottom; boolean emptyTruncateText = songTruncated.isEmpty(); + if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); + boolean isTextTruncated = songTruncated.endsWith("…"); switch (e.getAction()) { @@ -150,33 +155,20 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_MOVE: float distanceY = Math.abs(e.getY() - startY); - if (touchedScrollView) { - float distance = Math.abs(e.getX() - startX); - - // Scrolling the view: cancel event to prevent long press - if (distance > MAX_CLICK_DISTANCE) { - if (isTextTruncated) { - if (!emptyTruncateText) { - textView.setText(song); - } else { - Log.e("E/TouchInterceptFL", "songTruncated is empty or null. Did you remember " + - "to set the song string when setting the song name in your text view?"); - } - } - cancelPendingInputEvents(); - cancelLongPress(); - scrollView.cancelLongPress(); - scrollView.cancelPendingInputEvents(); - isTap = false; - } - } + // Scrolling vertically: cancel horizontal scrolling events if (distanceY > MAX_VERTICAL_DISTANCE) { - cancelLongPress(); - cancelPendingInputEvents(); - scrollView.cancelLongPress(); - scrollView.cancelPendingInputEvents(); - isTap = false; + CancelClick(); + }else { + if (touchedScrollView) { + float distance = Math.abs(e.getX() - startX); + + // Scrolling the view: cancel event to prevent long press + if (distance > MAX_CLICK_DISTANCE) { + if (isTextTruncated && !emptyTruncateText) textView.setText(song); + CancelClick(); + } + } } break; @@ -184,7 +176,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (touchedScrollView) { if (isTap) onTouchEvent(e); //uncomment if you want text to retrunucate - //if ((!emptyTruncateText && !isTextTruncated)) textView.setText(songTruncated); + //if ((!emptyTruncateText && isTextTruncated)) textView.setText(songTruncated); } break; } @@ -198,4 +190,12 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } } + private void CancelClick(){ + cancelPendingInputEvents(); + cancelLongPress(); + scrollView.cancelLongPress(); + scrollView.cancelPendingInputEvents(); + isTap = false; + } + } From b0797a58dbb562def94c3cb18c49a42831e8b406 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 13:41:02 -0400 Subject: [PATCH 29/97] Removed retrieving string resources and added documentation for CanceClick --- .../views/TouchInterceptFrameLayout.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index c5c0315a9..31ed91134 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -12,8 +12,6 @@ import android.widget.HorizontalScrollView; import android.widget.TextView; -import com.kabouzeid.gramophone.R; - /** * @author Lincoln (theduffmaster) * @@ -44,23 +42,14 @@ public class TouchInterceptFrameLayout extends FrameLayout { public TouchInterceptFrameLayout(@NonNull Context context) { super(context); - c= context; - TAG = c.getResources().getString(R.string.TOUCH_INTERCEPT_FRAME_LAYOUT_TAG); - NULL_VIEWS_EXCEPTION_MESSAGE = c.getResources().getString(R.string.NULL_VIEWS_EXCEPTION_MESSAGE); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - c= context; - TAG = c.getResources().getString(R.string.TOUCH_INTERCEPT_FRAME_LAYOUT_TAG); - NULL_VIEWS_EXCEPTION_MESSAGE = c.getResources().getString(R.string.NULL_VIEWS_EXCEPTION_MESSAGE); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - c= context; - TAG = c.getResources().getString(R.string.TOUCH_INTERCEPT_FRAME_LAYOUT_TAG); - NULL_VIEWS_EXCEPTION_MESSAGE = c.getResources().getString(R.string.NULL_VIEWS_EXCEPTION_MESSAGE); } /** @@ -175,8 +164,10 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_UP: if (touchedScrollView) { if (isTap) onTouchEvent(e); - //uncomment if you want text to retrunucate - //if ((!emptyTruncateText && isTextTruncated)) textView.setText(songTruncated); + //uncomment if you want text to retrunucate on a click + //if ((!emptyTruncateText && isTextTruncated)) + // scrollView.smoothScrollTo(0,0); + // textView.setText(songTruncated); } break; } @@ -190,6 +181,11 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } } + /** + * Cancels any Long Presses and inpending clicks. Used to prevent views from + * acting on touches while vertically scrolling or any case where the user is not + * interacting with the item views + */ private void CancelClick(){ cancelPendingInputEvents(); cancelLongPress(); From 822421f4a309f6f990fdd326401a19d3cde66d70 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 11 Jun 2017 15:02:35 -0400 Subject: [PATCH 30/97] Removed Error Tag resource strings --- app/src/main/res/values/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 123726fbf..50f7c06eb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -298,6 +298,4 @@ @string/last_added @string/last_added Playlist is empty - Did you forget to call setScrollViews when creating your FrameLayout? Either textView or scrollView is null. - E/TouchInterceptFL From f1a9ad2a94598a29b9316c7fd53b66419c8aff21 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 12 Jun 2017 23:56:10 -0400 Subject: [PATCH 31/97] Revert back to tried and trusted method of ignoring long clicks --- .../adapter/artist/ArtistAdapter.java | 3 +++ .../views/TouchInterceptFrameLayout.java | 23 +++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java index b4f1fdc9d..6efa48cbb 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java @@ -31,6 +31,7 @@ import com.kabouzeid.gramophone.util.ArtistSignatureUtil; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.NavigationUtil; +import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView; import java.util.ArrayList; @@ -104,6 +105,8 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { } if (holder.title != null) { + if(holder.itemView instanceof TouchInterceptFrameLayout) + ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(artist.getName()); holder.title.setText(artist.getName()); } if (holder.text != null) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 31ed91134..05bb985b2 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -114,6 +114,7 @@ public void run() { */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { + Log.d("Move = ", e.toString()); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); try { @@ -144,20 +145,18 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_MOVE: float distanceY = Math.abs(e.getY() - startY); + if (touchedScrollView) { + float distance = Math.abs(e.getX() - startX); + // Scrolling the view: cancel event to prevent long press + if (distance > MAX_CLICK_DISTANCE) { + if((!emptyTruncateText && isTextTruncated)) textView.setText(song); + CancelClick(); + } + } // Scrolling vertically: cancel horizontal scrolling events if (distanceY > MAX_VERTICAL_DISTANCE) { CancelClick(); - }else { - if (touchedScrollView) { - float distance = Math.abs(e.getX() - startX); - - // Scrolling the view: cancel event to prevent long press - if (distance > MAX_CLICK_DISTANCE) { - if (isTextTruncated && !emptyTruncateText) textView.setText(song); - CancelClick(); - } - } } break; @@ -187,8 +186,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { * interacting with the item views */ private void CancelClick(){ - cancelPendingInputEvents(); - cancelLongPress(); + this.cancelPendingInputEvents(); + this.cancelLongPress(); scrollView.cancelLongPress(); scrollView.cancelPendingInputEvents(); isTap = false; From 25f80e8db77d2f08f54665b59a3dd911b557b618 Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 13 Jun 2017 00:23:35 -0400 Subject: [PATCH 32/97] Added get ACTION_MASK to get bit info on movement. Much improved touch detection. --- .../gramophone/views/TouchInterceptFrameLayout.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 05bb985b2..d5d28f154 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -114,7 +114,6 @@ public void run() { */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - Log.d("Move = ", e.toString()); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); try { @@ -129,7 +128,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { boolean isTextTruncated = songTruncated.endsWith("…"); - switch (e.getAction()) { + switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (!touchedScrollView){ scrollView.cancelPendingInputEvents(); @@ -159,7 +158,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { CancelClick(); } break; - + case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (touchedScrollView) { if (isTap) onTouchEvent(e); From 9eb947e3c7eb0cf1bfec2f1569f7c6ead6b70164 Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 13 Jun 2017 01:38:46 -0400 Subject: [PATCH 33/97] Touch passed to nested scroll supporting views on over scroll --- app/src/main/res/layout/activity_album_detail.xml | 3 ++- app/src/main/res/layout/item_list.xml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 94a088d42..5a6176d98 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -51,7 +51,8 @@ android:id="@+id/title_scrollview" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:scrollbars="none"> + android:scrollbars="none" + android:nestedScrollingEnabled="true"> + android:scrollbars="none" + android:nestedScrollingEnabled="true"> Date: Thu, 15 Jun 2017 03:06:52 -0400 Subject: [PATCH 34/97] removed unnecessary setting of variable --- .../gramophone/views/TouchInterceptFrameLayout.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index d5d28f154..620362935 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -83,13 +83,12 @@ public void setTruncateText(String s){ scrollView.post(new Runnable() { @Override public void run() { - String sT = TextUtils.ellipsize(song, + songTruncated = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), TextUtils.TruncateAt.END).toString(); - songTruncated = sT; - if (!sT.isEmpty()) { - textView.setText(sT); + if (!songTruncated.isEmpty()) { + textView.setText(songTruncated); } } }); From d3a1e362b70503887883412318c5978864e3fcd6 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 30 Jun 2017 20:56:28 -0400 Subject: [PATCH 35/97] toggle scrolling on and off with data binding --- .../adapter/base/MediaEntryViewHolder.java | 2 + .../helper/UseScrollableTitles.java | 29 +++ .../ui/activities/SettingsActivity.java | 21 ++ .../gramophone/util/PreferenceUtil.java | 12 ++ .../main/res/layout/activity_album_detail.xml | 57 +++++- app/src/main/res/layout/item_list.xml | 186 +++++++++++++----- app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/pref_expierimental.xml | 13 ++ 8 files changed, 272 insertions(+), 51 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java create mode 100644 app/src/main/res/xml/pref_expierimental.xml diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index 7ac0ef924..a981ffe41 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -90,4 +90,6 @@ public boolean onLongClick(View v) { @Override public void onClick(View v) { } + + } diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java b/app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java new file mode 100644 index 000000000..757c2a963 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java @@ -0,0 +1,29 @@ +package com.kabouzeid.gramophone.helper; + +import android.content.Context; +import android.databinding.BaseObservable; +import android.util.Log; + +import com.android.databinding.library.baseAdapters.BR; +import com.kabouzeid.gramophone.util.PreferenceUtil; + +/** + * Created by lincoln on 6/18/17. + */ + +public class UseScrollableTitles extends BaseObservable { + + private boolean useScrollableTitle; + + public boolean getUseScrollableTitles(Context context){ + Log.d("Scrollable?",Boolean.toString(useScrollableTitle)); + this.useScrollableTitle = PreferenceUtil.getInstance(context).classicNotification(); + return this.useScrollableTitle; + } + + public void setUseScrollableTitles(boolean useScrollableTitle) { + Log.d("Scrollable?",Boolean.toString(useScrollableTitle)); + this.useScrollableTitle = useScrollableTitle; + notifyPropertyChanged(BR.useScrollableTitle); + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java index b018768cf..3be35b896 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java @@ -16,6 +16,7 @@ import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.TwoStatePreference; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.MenuItem; import android.view.View; @@ -27,6 +28,7 @@ import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.appshortcuts.DynamicShortcutManager; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; +import com.kabouzeid.gramophone.helper.UseScrollableTitles; import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreference; import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreferenceDialog; import com.kabouzeid.gramophone.service.MusicService; @@ -45,6 +47,7 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia Toolbar toolbar; @BindView(R.id.status_bar) View statusBar; + private static UseScrollableTitles useScrollableTitles; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -69,6 +72,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { SettingsFragment frag = (SettingsFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame); if (frag != null) frag.invalidateSettings(); } + + useScrollableTitles = new UseScrollableTitles(); } @Override @@ -139,6 +144,7 @@ public void onCreatePreferences(Bundle bundle, String s) { addPreferencesFromResource(R.xml.pref_lockscreen); addPreferencesFromResource(R.xml.pref_audio); addPreferencesFromResource(R.xml.pref_playlists); + addPreferencesFromResource(R.xml.pref_expierimental); } @Nullable @@ -279,6 +285,21 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { }); } + final TwoStatePreference useScrollable = (TwoStatePreference) findPreference("scrollable_titles"); + useScrollable.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + //Save preference + PreferenceUtil.getInstance(getActivity()).setUseScrollableTitles((Boolean)newValue); + + useScrollableTitles.setUseScrollableTitles((Boolean)newValue); + + Log.d("Scrollable?",Boolean.toString((Boolean)newValue)); + + return true; + } + }); + final TwoStatePreference colorAppShortcuts = (TwoStatePreference) findPreference("should_color_app_shortcuts"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { colorAppShortcuts.setEnabled(false); diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java index a893218cf..5dc35ba1c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java @@ -54,6 +54,8 @@ public final class PreferenceUtil { public static final String LAST_ADDED_CUTOFF = "last_added_interval"; + public static final String SCROLLABLE_TITLES = "scrollable_titles"; + public static final String ALBUM_ART_ON_LOCKSCREEN = "album_art_on_lockscreen"; public static final String BLURRED_ALBUM_ART = "blurred_album_art"; @@ -162,6 +164,16 @@ public void setClassicNotification(final boolean value) { editor.apply(); } + public final boolean useScrollableTitles() { + return mPreferences.getBoolean(SCROLLABLE_TITLES, false); + } + + public void setUseScrollableTitles(final boolean value) { + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(SCROLLABLE_TITLES, value); + editor.apply(); + } + public void setColoredAppShortcuts(final boolean value) { final SharedPreferences.Editor editor = mPreferences.edit(); editor.putBoolean(COLORED_APP_SHORTCUTS, value); diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 5a6176d98..67454f833 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -1,6 +1,10 @@ + + + + + + android:orientation="vertical" + android:visibility="@{useScrollableTitle.getUseScrollableTitles(context) ? View.GONE : View.VISIBLE}"> + tools:ignore="DuplicateIds"> + + + + + + + + + + + + + + android:nestedScrollingEnabled="true" + tools:ignore="DuplicateIds"> + tools:ignore="DuplicateIds,UnusedAttribute" /> @@ -104,4 +148,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index eb45799ba..e6b5e1b91 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,5 +1,10 @@ - + + + + + + android:orientation="horizontal" + android:visibility="@{useScrollableTitle.getUseScrollableTitles(context) ? View.GONE : View.VISIBLE}" + tools:ignore="DuplicateIds"> - + android:paddingStart="16dp" + tools:ignore="DuplicateIds"> + tools:ignore="ContentDescription, DuplicateIds"/> + android:visibility="gone" + tools:ignore="DuplicateIds"/> @@ -77,58 +86,145 @@ android:paddingRight="0dp" android:paddingStart="16dp"> - - + android:singleLine="true" + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + tools:ignore="DuplicateIds"/> - + + + + + + + + + + + + + + + + + + + + + + android:scrollHorizontally="true" + android:ellipsize="end" + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + tools:ignore="DuplicateIds"/> - + - + - - - - - \ No newline at end of file + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9bb49665c..c4b17a474 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -125,6 +125,7 @@ Lockscreen Playlists Notification + Expierimental Colored navigation bar Colored app shortcuts Start page @@ -144,6 +145,7 @@ Colored playback controls Reduce volume on focus loss Last added playlist interval + Enable Title Scrolling No equalizer found. "Play a song first, then try again." Delete @@ -186,6 +188,7 @@ Colors the navigation bar in the primary color. Colors the app shortcuts in the primary color. Notifications, navigation etc. + Enables scrolling on the full title of album, artist and song titles that are too long for the view and have been truncated (cut off and ellipsis added). Enabling may result in a slightly poorer user expierience. "Couldn\u2019t download a matching album cover." Search your library… Rescanning media… diff --git a/app/src/main/res/xml/pref_expierimental.xml b/app/src/main/res/xml/pref_expierimental.xml new file mode 100644 index 000000000..c9ff8c6af --- /dev/null +++ b/app/src/main/res/xml/pref_expierimental.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file From 3c3fec96d3f8a56683d66b4ecd44ca4f4778cafc Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 30 Jun 2017 20:56:39 -0400 Subject: [PATCH 36/97] Revert "removed unnecessary setting of variable" This reverts commit e933d59cd5c0edea9a4e105ed627c0135c382120. --- .../gramophone/views/TouchInterceptFrameLayout.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 620362935..d5d28f154 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -83,12 +83,13 @@ public void setTruncateText(String s){ scrollView.post(new Runnable() { @Override public void run() { - songTruncated = TextUtils.ellipsize(song, + String sT = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), TextUtils.TruncateAt.END).toString(); - if (!songTruncated.isEmpty()) { - textView.setText(songTruncated); + songTruncated = sT; + if (!sT.isEmpty()) { + textView.setText(sT); } } }); From 3667521e0177f6b76975535c1a4ef6662687ce84 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 30 Jun 2017 20:58:14 -0400 Subject: [PATCH 37/97] Revert "Revert "removed unnecessary setting of variable"" This reverts commit 3c3fec96d3f8a56683d66b4ecd44ca4f4778cafc. --- .../gramophone/views/TouchInterceptFrameLayout.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index d5d28f154..620362935 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -83,13 +83,12 @@ public void setTruncateText(String s){ scrollView.post(new Runnable() { @Override public void run() { - String sT = TextUtils.ellipsize(song, + songTruncated = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), TextUtils.TruncateAt.END).toString(); - songTruncated = sT; - if (!sT.isEmpty()) { - textView.setText(sT); + if (!songTruncated.isEmpty()) { + textView.setText(songTruncated); } } }); From 63cd45d7ffdcfa635a0c7d06bbd18efb887d20f9 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 30 Jun 2017 20:58:56 -0400 Subject: [PATCH 38/97] Revert "toggle scrolling on and off with data binding" This reverts commit d3a1e362b70503887883412318c5978864e3fcd6. --- .../adapter/base/MediaEntryViewHolder.java | 2 - .../helper/UseScrollableTitles.java | 29 --- .../ui/activities/SettingsActivity.java | 21 -- .../gramophone/util/PreferenceUtil.java | 12 -- .../main/res/layout/activity_album_detail.xml | 57 +----- app/src/main/res/layout/item_list.xml | 186 +++++------------- app/src/main/res/values/strings.xml | 3 - app/src/main/res/xml/pref_expierimental.xml | 13 -- 8 files changed, 51 insertions(+), 272 deletions(-) delete mode 100644 app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java delete mode 100644 app/src/main/res/xml/pref_expierimental.xml diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index a981ffe41..7ac0ef924 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -90,6 +90,4 @@ public boolean onLongClick(View v) { @Override public void onClick(View v) { } - - } diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java b/app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java deleted file mode 100644 index 757c2a963..000000000 --- a/app/src/main/java/com/kabouzeid/gramophone/helper/UseScrollableTitles.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.kabouzeid.gramophone.helper; - -import android.content.Context; -import android.databinding.BaseObservable; -import android.util.Log; - -import com.android.databinding.library.baseAdapters.BR; -import com.kabouzeid.gramophone.util.PreferenceUtil; - -/** - * Created by lincoln on 6/18/17. - */ - -public class UseScrollableTitles extends BaseObservable { - - private boolean useScrollableTitle; - - public boolean getUseScrollableTitles(Context context){ - Log.d("Scrollable?",Boolean.toString(useScrollableTitle)); - this.useScrollableTitle = PreferenceUtil.getInstance(context).classicNotification(); - return this.useScrollableTitle; - } - - public void setUseScrollableTitles(boolean useScrollableTitle) { - Log.d("Scrollable?",Boolean.toString(useScrollableTitle)); - this.useScrollableTitle = useScrollableTitle; - notifyPropertyChanged(BR.useScrollableTitle); - } -} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java index 3be35b896..b018768cf 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java @@ -16,7 +16,6 @@ import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.TwoStatePreference; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.view.MenuItem; import android.view.View; @@ -28,7 +27,6 @@ import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.appshortcuts.DynamicShortcutManager; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; -import com.kabouzeid.gramophone.helper.UseScrollableTitles; import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreference; import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreferenceDialog; import com.kabouzeid.gramophone.service.MusicService; @@ -47,7 +45,6 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia Toolbar toolbar; @BindView(R.id.status_bar) View statusBar; - private static UseScrollableTitles useScrollableTitles; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -72,8 +69,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { SettingsFragment frag = (SettingsFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame); if (frag != null) frag.invalidateSettings(); } - - useScrollableTitles = new UseScrollableTitles(); } @Override @@ -144,7 +139,6 @@ public void onCreatePreferences(Bundle bundle, String s) { addPreferencesFromResource(R.xml.pref_lockscreen); addPreferencesFromResource(R.xml.pref_audio); addPreferencesFromResource(R.xml.pref_playlists); - addPreferencesFromResource(R.xml.pref_expierimental); } @Nullable @@ -285,21 +279,6 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { }); } - final TwoStatePreference useScrollable = (TwoStatePreference) findPreference("scrollable_titles"); - useScrollable.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - //Save preference - PreferenceUtil.getInstance(getActivity()).setUseScrollableTitles((Boolean)newValue); - - useScrollableTitles.setUseScrollableTitles((Boolean)newValue); - - Log.d("Scrollable?",Boolean.toString((Boolean)newValue)); - - return true; - } - }); - final TwoStatePreference colorAppShortcuts = (TwoStatePreference) findPreference("should_color_app_shortcuts"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { colorAppShortcuts.setEnabled(false); diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java index 5dc35ba1c..a893218cf 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java @@ -54,8 +54,6 @@ public final class PreferenceUtil { public static final String LAST_ADDED_CUTOFF = "last_added_interval"; - public static final String SCROLLABLE_TITLES = "scrollable_titles"; - public static final String ALBUM_ART_ON_LOCKSCREEN = "album_art_on_lockscreen"; public static final String BLURRED_ALBUM_ART = "blurred_album_art"; @@ -164,16 +162,6 @@ public void setClassicNotification(final boolean value) { editor.apply(); } - public final boolean useScrollableTitles() { - return mPreferences.getBoolean(SCROLLABLE_TITLES, false); - } - - public void setUseScrollableTitles(final boolean value) { - final SharedPreferences.Editor editor = mPreferences.edit(); - editor.putBoolean(SCROLLABLE_TITLES, value); - editor.apply(); - } - public void setColoredAppShortcuts(final boolean value) { final SharedPreferences.Editor editor = mPreferences.edit(); editor.putBoolean(COLORED_APP_SHORTCUTS, value); diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 67454f833..5a6176d98 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -1,10 +1,6 @@ - - - - - + android:orientation="vertical"> - - - - - - - - - - - - - + > + android:nestedScrollingEnabled="true"> + tools:ignore="UnusedAttribute" /> @@ -148,5 +104,4 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index e6b5e1b91..eb45799ba 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,10 +1,5 @@ - - - - - - + android:orientation="horizontal"> - + android:paddingStart="16dp"> + tools:ignore="ContentDescription" /> + android:visibility="gone" /> @@ -86,145 +77,58 @@ android:paddingRight="0dp" android:paddingStart="16dp"> - + + android:scrollHorizontally="true" + android:ellipsize="end" + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> - - - - - - - - - - - - - - - - - - - + + android:singleLine="true" + android:textAppearance="@style/TextAppearance.AppCompat.Body1" + android:textColor="?android:textColorSecondary" /> - + - + - - - - - - - - - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4b17a474..9bb49665c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -125,7 +125,6 @@ Lockscreen Playlists Notification - Expierimental Colored navigation bar Colored app shortcuts Start page @@ -145,7 +144,6 @@ Colored playback controls Reduce volume on focus loss Last added playlist interval - Enable Title Scrolling No equalizer found. "Play a song first, then try again." Delete @@ -188,7 +186,6 @@ Colors the navigation bar in the primary color. Colors the app shortcuts in the primary color. Notifications, navigation etc. - Enables scrolling on the full title of album, artist and song titles that are too long for the view and have been truncated (cut off and ellipsis added). Enabling may result in a slightly poorer user expierience. "Couldn\u2019t download a matching album cover." Search your library… Rescanning media… diff --git a/app/src/main/res/xml/pref_expierimental.xml b/app/src/main/res/xml/pref_expierimental.xml deleted file mode 100644 index c9ff8c6af..000000000 --- a/app/src/main/res/xml/pref_expierimental.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - \ No newline at end of file From f0bf36b2f8d5b5dfca81207563a88efdd99a0aa8 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 7 Jul 2017 02:26:25 -0400 Subject: [PATCH 39/97] Canceled child touches on list parent scrolling --- .../adapter/base/MediaEntryViewHolder.java | 4 +- .../adapter/song/ArtistSongAdapter.java | 5 +- .../gramophone/adapter/song/SongAdapter.java | 11 ++++ .../ui/activities/AlbumDetailActivity.java | 5 +- .../views/TouchInterceptFrameLayout.java | 63 +++++++++++++++++-- .../TouchInterceptHorizontalScrollView.java | 29 +++++++++ .../main/res/layout/activity_album_detail.xml | 4 +- app/src/main/res/layout/item_list.xml | 4 +- 8 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index 7ac0ef924..5361e6a9f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -5,13 +5,13 @@ import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.View; -import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; +import com.kabouzeid.gramophone.views.TouchInterceptHorizontalScrollView; import butterknife.BindView; import butterknife.ButterKnife; @@ -38,7 +38,7 @@ public class MediaEntryViewHolder extends RecyclerView.ViewHolder implements Vie @Nullable @BindView(R.id.title_scrollview) - public HorizontalScrollView title_scrollview; + public TouchInterceptHorizontalScrollView title_scrollview; @Nullable @BindView(R.id.text) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java index b2febf154..1388f6647 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java @@ -11,7 +11,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.TextView; @@ -26,6 +25,7 @@ import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; +import com.kabouzeid.gramophone.views.TouchInterceptHorizontalScrollView; import java.util.ArrayList; @@ -69,7 +69,7 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_list, parent, false); } final TouchInterceptFrameLayout container = (TouchInterceptFrameLayout) convertView.findViewById(R.id.container); - final HorizontalScrollView songTitleScrollView = (HorizontalScrollView) convertView.findViewById(R.id.title_scrollview); + final TouchInterceptHorizontalScrollView songTitleScrollView = (TouchInterceptHorizontalScrollView) convertView.findViewById(R.id.title_scrollview); final TextView songTitle = (TextView) convertView.findViewById(R.id.title); final TextView songInfo = (TextView) convertView.findViewById(R.id.text); final ImageView albumArt = (ImageView) convertView.findViewById(R.id.image); @@ -89,6 +89,7 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa songInfo.setText(song.albumName); container.setViews(songTitleScrollView,songTitle); container.setTruncateText(song.title); + container.setListParent(parent); SongGlideRequest.Builder.from(Glide.with(activity), song) .checkIgnoreMediaStore(activity).build() diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 6b90b3924..50e403696 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -6,6 +6,7 @@ import android.support.annotation.Nullable; import android.support.v4.util.Pair; import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.MotionEvent; @@ -48,6 +49,8 @@ public class SongAdapter extends AbsMultiSelectAdapter dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) { this(activity, dataSet, itemLayoutRes, usePalette, cabHolder, true); } @@ -62,6 +65,13 @@ public SongAdapter(AppCompatActivity activity, ArrayList dataSet, @LayoutR setHasStableIds(true); } + + @Override + public void onAttachedToRecyclerView(RecyclerView rV) { + super.onAttachedToRecyclerView(rV); + recyclerView = rV; + } + public void swapDataSet(ArrayList dataSet) { this.dataSet = dataSet; notifyDataSetChanged(); @@ -114,6 +124,7 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title_scrollview != null && holder.itemView instanceof TouchInterceptFrameLayout) { ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(getSongTitle(song)); + ((TouchInterceptFrameLayout) holder.itemView).setListParent(recyclerView); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index c88c7ca99..4a3dda89d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -13,7 +13,6 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; @@ -48,6 +47,7 @@ import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; +import com.kabouzeid.gramophone.views.TouchInterceptHorizontalScrollView; import butterknife.BindView; import butterknife.ButterKnife; @@ -78,7 +78,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements @BindView(R.id.album_title) TextView albumTitleTextView; @BindView(R.id.title_scrollview) - HorizontalScrollView titleScrollView; + TouchInterceptHorizontalScrollView titleScrollView; @BindView(R.id.list_background) View songsBackgroundView; @BindView(R.id.status_bar) @@ -338,6 +338,7 @@ private void setAlbum(Album album) { albumTitleTextView.setText(album.getTitle()); container.setViews(titleScrollView, albumTitleTextView); container.setTruncateText(album.getTitle()); + container.setListParent(recyclerView); adapter.swapDataSet(album.songs); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 620362935..f796d3f14 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -4,12 +4,15 @@ import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; +import android.view.View; +import android.widget.AbsListView; import android.widget.FrameLayout; -import android.widget.HorizontalScrollView; +import android.widget.ListView; import android.widget.TextView; /** @@ -23,20 +26,21 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final int MAX_CLICK_DISTANCE = 5; private static final int MAX_VERTICAL_DISTANCE = 5; - private Context c; - private String TAG = "E/TouchInterceptFL"; private String NULL_VIEWS_EXCEPTION_MESSAGE = "Did you forget to call setViews" + "" + "when creating your FrameLayout? Either textView or scrollView is null."; private String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + "to set the song string when setting the song name in your text view?"; - private HorizontalScrollView scrollView; + private TouchInterceptHorizontalScrollView scrollView; private TextView textView; + private Rect scrollViewRect = new Rect(); private float startX; + private float startY; private boolean isTap; + private String songTruncated; private String song; @@ -60,9 +64,55 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe * @param sv The HorizontalScrollView containing text that needs to be scrolled * @param tv The TextView that needs to be scrolled (typically song or album title) */ - public void setViews(HorizontalScrollView sv, TextView tv) { + public void setViews(TouchInterceptHorizontalScrollView sv, TextView tv) { scrollView = sv; textView = tv; + + } + + public void setListParent(View listParent){ + + if(listParent instanceof RecyclerView){ + ((RecyclerView) listParent).addOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + + if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { + scrollView.cancelPendingInputEvents(); + cancelPendingInputEvents(); + } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { + scrollView.cancelPendingInputEvents(); + cancelPendingInputEvents(); + } + } + }); + } + + if(listParent instanceof ListView){ + ((ListView) listParent).setOnScrollListener(new AbsListView.OnScrollListener(){ + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + } + public void onScrollStateChanged(AbsListView view, int newState) { + + if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { + scrollView.cancelPendingInputEvents(); + cancelPendingInputEvents(); + } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { + scrollView.cancelPendingInputEvents(); + cancelPendingInputEvents(); + } + } + }); + } + } /** @@ -113,6 +163,7 @@ public void run() { */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { + int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); try { @@ -155,6 +206,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling vertically: cancel horizontal scrolling events if (distanceY > MAX_VERTICAL_DISTANCE) { CancelClick(); + return true; } break; case MotionEvent.ACTION_CANCEL: @@ -190,5 +242,4 @@ private void CancelClick(){ scrollView.cancelPendingInputEvents(); isTap = false; } - } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java new file mode 100644 index 000000000..67b07ff3d --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -0,0 +1,29 @@ +package com.kabouzeid.gramophone.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.HorizontalScrollView; + +/** + * Created by lincoln on 7/3/17. + */ + +public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { + public TouchInterceptHorizontalScrollView(Context context) { + super(context); + } + + public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + return false; + } +} diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 5a6176d98..3cbbc90fd 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -47,7 +47,7 @@ android:paddingRight="72dp" > - - + diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index eb45799ba..6a0717262 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -77,7 +77,7 @@ android:paddingRight="0dp" android:paddingStart="16dp"> - - + Date: Fri, 7 Jul 2017 02:36:31 -0400 Subject: [PATCH 40/97] Don't need this anymore since we're interacting with the recycler view directly now --- .../gramophone/views/TouchInterceptFrameLayout.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index f796d3f14..b6d4dbd8e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -193,7 +193,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { break; case MotionEvent.ACTION_MOVE: - float distanceY = Math.abs(e.getY() - startY); if (touchedScrollView) { float distance = Math.abs(e.getX() - startX); @@ -203,11 +202,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { CancelClick(); } } - // Scrolling vertically: cancel horizontal scrolling events - if (distanceY > MAX_VERTICAL_DISTANCE) { - CancelClick(); - return true; - } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: From 84f80234a24503ba4a9756e4cdef312d91f7c875 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 7 Jul 2017 04:45:38 -0400 Subject: [PATCH 41/97] Retruncates text after scrolling with a 1000ms delay --- .../views/TouchInterceptFrameLayout.java | 40 +++++++--- .../TouchInterceptHorizontalScrollView.java | 77 ++++++++++++++++++- 2 files changed, 106 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index b6d4dbd8e..46e673479 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -1,7 +1,9 @@ package com.kabouzeid.gramophone.views; +import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Rect; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; @@ -15,6 +17,8 @@ import android.widget.ListView; import android.widget.TextView; + + /** * @author Lincoln (theduffmaster) * @@ -24,7 +28,7 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final int MAX_CLICK_DISTANCE = 5; - private static final int MAX_VERTICAL_DISTANCE = 5; + private static final int RETRUNCATE_DELAY = 500; private String TAG = "E/TouchInterceptFL"; private String NULL_VIEWS_EXCEPTION_MESSAGE = "Did you forget to call setViews" + "" + @@ -38,7 +42,6 @@ public class TouchInterceptFrameLayout extends FrameLayout { private Rect scrollViewRect = new Rect(); private float startX; - private float startY; private boolean isTap; private String songTruncated; @@ -139,6 +142,19 @@ public void run() { TextUtils.TruncateAt.END).toString(); if (!songTruncated.isEmpty()) { textView.setText(songTruncated); + + if(songTruncated.equals(song)) { + scrollView.setScrollingEnabled(false); + }else{ + scrollView.setScrollingEnabled(true); + scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() + { + @Override + public void onEndScroll() { + ReTruncateScrollText(); + } + }); + } } } }); @@ -186,7 +202,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } startX = e.getX(); - startY = e.getY(); isTap = true; onTouchEvent(e); @@ -207,10 +222,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_UP: if (touchedScrollView) { if (isTap) onTouchEvent(e); - //uncomment if you want text to retrunucate on a click - //if ((!emptyTruncateText && isTextTruncated)) - // scrollView.smoothScrollTo(0,0); - // textView.setText(songTruncated); } break; } @@ -230,10 +241,21 @@ public boolean onInterceptTouchEvent(MotionEvent e) { * interacting with the item views */ private void CancelClick(){ - this.cancelPendingInputEvents(); - this.cancelLongPress(); + cancelPendingInputEvents(); + cancelLongPress(); scrollView.cancelLongPress(); scrollView.cancelPendingInputEvents(); isTap = false; } + + private void ReTruncateScrollText(){ + ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + textView.setText(songTruncated); + } + }, RETRUNCATE_DELAY+100); + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 67b07ff3d..1522bda97 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -10,6 +10,36 @@ */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { + + public interface OnEndScrollListener { + public void onEndScroll(); + } + + private long lastScrollUpdate = -1; + private boolean cancel; + private int delay = 1000; + + private class ScrollStateHandler implements Runnable { + + @Override + public void run() { + if(!cancel) { + long currentTime = System.currentTimeMillis(); + if ((currentTime - lastScrollUpdate) > delay) { + lastScrollUpdate = -1; + if (onEndScrollListener != null) { + onEndScrollListener.onEndScroll(); + } + } else { + postDelayed(this, delay); + } + } + } + } + + private OnEndScrollListener onEndScrollListener; + + public TouchInterceptHorizontalScrollView(Context context) { super(context); } @@ -22,8 +52,51 @@ public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, i super(context, attrs, defStyleAttr); } + // true if we can scroll (not locked) + // false if we cannot scroll (locked) + private boolean mScrollable = true; + + public void setScrollingEnabled(boolean enabled) { + mScrollable = enabled; + } + + public boolean isScrollable() { + return mScrollable; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + cancel = true; + // if we can scroll pass the event to the superclass + if (mScrollable) return super.onTouchEvent(ev); + // only continue to handle the touch event if scrolling enabled + return mScrollable; // mScrollable is always false at this point + case MotionEvent.ACTION_UP: + cancel = false; + postDelayed(new ScrollStateHandler(), delay); + lastScrollUpdate = System.currentTimeMillis(); + default: + return super.onTouchEvent(ev); + } + } + @Override - public boolean onInterceptTouchEvent(MotionEvent e) { - return false; + public boolean onInterceptTouchEvent(MotionEvent ev) { + // Don't do anything with intercepted touch events if + // we are not scrollable + if (!mScrollable) return false; + else return super.onInterceptTouchEvent(ev); } + + public OnEndScrollListener getOnEndScrollListener() { + return onEndScrollListener; + } + + public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { + this.onEndScrollListener = mOnEndScrollListener; + } + + } From 25099c957439350ae0b7b89c1c5b5b3ef77fabbe Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 9 Jul 2017 01:53:49 -0400 Subject: [PATCH 42/97] Can now easily set everything from xml. Added options to set things programmatically. Made mini player scrollable. --- .../gramophone/adapter/SearchAdapter.java | 5 - .../adapter/artist/ArtistAdapter.java | 3 - .../adapter/base/MediaEntryViewHolder.java | 2 +- .../adapter/song/ArtistSongAdapter.java | 4 - .../gramophone/adapter/song/SongAdapter.java | 5 +- .../ui/activities/AlbumDetailActivity.java | 3 - .../player/card/CardPlayerFragment.java | 4 - .../player/flat/FlatPlayerFragment.java | 4 - .../views/TouchInterceptFrameLayout.java | 135 ++++++++++++++---- .../TouchInterceptHorizontalScrollView.java | 2 +- .../main/res/layout/activity_album_detail.xml | 13 +- .../main/res/layout/fragment_mini_player.xml | 37 +++-- app/src/main/res/layout/item_list.xml | 11 +- app/src/main/res/values/attrs.xml | 5 + 14 files changed, 162 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java index 4f6a2bc7e..bc1703a9a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java @@ -78,7 +78,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { final Album album = (Album) dataSet.get(position); holder.title.setText(album.getTitle()); if(holder.itemView instanceof TouchInterceptFrameLayout) - ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(album.getTitle()); holder.text.setText(album.getArtistName()); SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) .checkIgnoreMediaStore(activity).build() @@ -87,8 +86,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { case ARTIST: final Artist artist = (Artist) dataSet.get(position); holder.title.setText(artist.getName()); - if(holder.itemView instanceof TouchInterceptFrameLayout) - ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(artist.getName()); holder.text.setText(MusicUtil.getArtistInfoString(activity, artist)); Glide.with(activity) .load(new ArtistImage(artist.getName(), false)) @@ -103,8 +100,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { case SONG: final Song song = (Song) dataSet.get(position); holder.title.setText(song.title); - if(holder.itemView instanceof TouchInterceptFrameLayout) - ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(song.title); holder.text.setText(song.albumName); break; default: diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java index 6efa48cbb..b4f1fdc9d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/artist/ArtistAdapter.java @@ -31,7 +31,6 @@ import com.kabouzeid.gramophone.util.ArtistSignatureUtil; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.NavigationUtil; -import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView; import java.util.ArrayList; @@ -105,8 +104,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { } if (holder.title != null) { - if(holder.itemView instanceof TouchInterceptFrameLayout) - ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(artist.getName()); holder.title.setText(artist.getName()); } if (holder.text != null) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java index 5361e6a9f..f6e7999e6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/base/MediaEntryViewHolder.java @@ -69,7 +69,7 @@ public MediaEntryViewHolder(View itemView) { ButterKnife.bind(this, itemView); if (title_scrollview != null && title != null && itemView instanceof TouchInterceptFrameLayout) { - ((TouchInterceptFrameLayout) itemView).setViews(title_scrollview,title); + //((TouchInterceptFrameLayout) itemView).setViews(title_scrollview,title); } itemView.setOnClickListener(this); diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java index 1388f6647..166eb162c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java @@ -25,7 +25,6 @@ import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; -import com.kabouzeid.gramophone.views.TouchInterceptHorizontalScrollView; import java.util.ArrayList; @@ -69,7 +68,6 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_list, parent, false); } final TouchInterceptFrameLayout container = (TouchInterceptFrameLayout) convertView.findViewById(R.id.container); - final TouchInterceptHorizontalScrollView songTitleScrollView = (TouchInterceptHorizontalScrollView) convertView.findViewById(R.id.title_scrollview); final TextView songTitle = (TextView) convertView.findViewById(R.id.title); final TextView songInfo = (TextView) convertView.findViewById(R.id.text); final ImageView albumArt = (ImageView) convertView.findViewById(R.id.image); @@ -87,8 +85,6 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa songTitle.setText(song.title); songInfo.setText(song.albumName); - container.setViews(songTitleScrollView,songTitle); - container.setTruncateText(song.title); container.setListParent(parent); SongGlideRequest.Builder.from(Glide.with(activity), song) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 50e403696..473ec9458 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -122,10 +122,9 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); - if (holder.title_scrollview != null && holder.itemView instanceof TouchInterceptFrameLayout) { - ((TouchInterceptFrameLayout) holder.itemView).setTruncateText(getSongTitle(song)); + if (holder.itemView instanceof TouchInterceptFrameLayout) ((TouchInterceptFrameLayout) holder.itemView).setListParent(recyclerView); - } + } if (holder.text != null) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 4a3dda89d..e14b12652 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -336,9 +336,6 @@ private void setAlbum(Album album) { this.album = album; loadAlbumCover(); albumTitleTextView.setText(album.getTitle()); - container.setViews(titleScrollView, albumTitleTextView); - container.setTruncateText(album.getTitle()); - container.setListParent(recyclerView); adapter.swapDataSet(album.songs); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java index 000fb1ad3..46ae480bf 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java @@ -48,7 +48,6 @@ import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; -import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.kabouzeid.gramophone.views.WidthFitSquareLayout; import com.sothree.slidinguppanel.SlidingUpPanelLayout; @@ -575,9 +574,6 @@ public void updateCurrentSong(Song song) { currentSong = song; currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); - TouchInterceptFrameLayout itemView = (TouchInterceptFrameLayout) currentSongViewHolder.itemView; - itemView.setViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); - itemView.setTruncateText(song.title); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java index e526144a7..1b07a2f64 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java @@ -46,7 +46,6 @@ import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; -import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; import com.kabouzeid.gramophone.views.WidthFitSquareLayout; import com.sothree.slidinguppanel.SlidingUpPanelLayout; @@ -556,9 +555,6 @@ public void updateCurrentSong(Song song) { currentSong = song; currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); - TouchInterceptFrameLayout itemView = (TouchInterceptFrameLayout) currentSongViewHolder.itemView; - itemView.setViews(currentSongViewHolder.title_scrollview,currentSongViewHolder.title); - itemView.setTruncateText(song.title); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 46e673479..1240fe9bd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -2,12 +2,15 @@ import android.animation.ObjectAnimator; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Rect; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; +import android.text.Editable; import android.text.TextUtils; +import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -17,7 +20,7 @@ import android.widget.ListView; import android.widget.TextView; - +import com.kabouzeid.gramophone.R; /** * @author Lincoln (theduffmaster) @@ -35,28 +38,91 @@ public class TouchInterceptFrameLayout extends FrameLayout { "when creating your FrameLayout? Either textView or scrollView is null."; private String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + "to set the song string when setting the song name in your text view?"; - + private TouchInterceptHorizontalScrollView scrollView; private TextView textView; + private View listParent; + + private int scrollViewID; + private int textViewID; + private int listParentID; private Rect scrollViewRect = new Rect(); private float startX; private boolean isTap; + private boolean currentlySettingTextHere = false; private String songTruncated; private String song; + protected TextWatcher truncateTextWatcher = new TextWatcher() { + + @Override + public void afterTextChanged(Editable s) { + if(!currentlySettingTextHere){ + + TouchInterceptHorizontalScrollView sV = (TouchInterceptHorizontalScrollView) findViewById(scrollViewID); + if (sV != null) scrollView = sV; + TextView tV = (TextView) findViewById(textViewID); + if(tV != null) textView = tV; + View lP = (View) findViewById(listParentID); + if(lP != null) listParent = lP; + + setTruncateText(textView.getText().toString()); + } + currentlySettingTextHere = false; + + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + }; + public TouchInterceptFrameLayout(@NonNull Context context) { - super(context); + this(context, null); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TouchInterceptFrameLayout, defStyleAttr, 0); + scrollViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setTouchInterceptHorizontalScrollView, 0); + textViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setScrollableTextView, 0); + listParentID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setListParent, 0); + + Log.d("Pre Post","true"); + + this.post(new Runnable() { + @Override + public void run() { + Log.d("this Post","true"); + scrollView = (TouchInterceptHorizontalScrollView) findViewById(scrollViewID); + textView = (TextView) findViewById(textViewID); + View lP = (View) findViewById(listParentID); + if(lP != null) listParent = lP; + + textView.post(new Runnable() { + @Override + public void run() { + textView.addTextChangedListener(truncateTextWatcher); + setTruncateText(textView.getText().toString()); + } + }); + } + }); + } /** @@ -65,15 +131,27 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe * Must be called before setTruncateText. * Call this when you are assigning views in your layout. * @param sv The HorizontalScrollView containing text that needs to be scrolled + */ + public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScrollView sv) { + this.scrollView = sv; + } + + /** + * Fetches the HorizontalScrollView contained by this FrameLayout and also gets the + * TextView that is contained within that HorizontalScrollView. + * Must be called before setTruncateText. + * Call this when you are assigning views in your layout. * @param tv The TextView that needs to be scrolled (typically song or album title) */ - public void setViews(TouchInterceptHorizontalScrollView sv, TextView tv) { - scrollView = sv; - textView = tv; + public void setScrollableTextView(TextView tv) { + this.textView = tv; + } + public void setListParent(View lP){ + this.listParent = lP; } - public void setListParent(View listParent){ + public void initializeListParent(){ if(listParent instanceof RecyclerView){ ((RecyclerView) listParent).addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -88,11 +166,9 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { - scrollView.cancelPendingInputEvents(); - cancelPendingInputEvents(); + CancelClick(); } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { - scrollView.cancelPendingInputEvents(); - cancelPendingInputEvents(); + CancelClick(); } } }); @@ -106,16 +182,13 @@ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun public void onScrollStateChanged(AbsListView view, int newState) { if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { - scrollView.cancelPendingInputEvents(); - cancelPendingInputEvents(); + CancelClick(); } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { - scrollView.cancelPendingInputEvents(); - cancelPendingInputEvents(); + CancelClick(); } } }); } - } /** @@ -133,16 +206,18 @@ public void setTruncateText(String s){ song = s; try { //runs after scrollview has been drawn - scrollView.post(new Runnable() { + textView.post(new Runnable() { @Override public void run() { + Log.d("Truncate text",song); + song = textView.getText().toString(); songTruncated = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), TextUtils.TruncateAt.END).toString(); if (!songTruncated.isEmpty()) { - textView.setText(songTruncated); - + setText(songTruncated); + Log.d("Truncated text",songTruncated); if(songTruncated.equals(song)) { scrollView.setScrollingEnabled(false); }else{ @@ -155,6 +230,7 @@ public void onEndScroll() { } }); } + initializeListParent(); } } }); @@ -213,8 +289,10 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { - if((!emptyTruncateText && isTextTruncated)) textView.setText(song); + if((!emptyTruncateText && isTextTruncated)) setText(song); CancelClick(); + this.requestDisallowInterceptTouchEvent(true); + isTap = false; } } break; @@ -223,6 +301,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (touchedScrollView) { if (isTap) onTouchEvent(e); } + this.requestDisallowInterceptTouchEvent(false); break; } return false; @@ -241,21 +320,25 @@ public boolean onInterceptTouchEvent(MotionEvent e) { * interacting with the item views */ private void CancelClick(){ - cancelPendingInputEvents(); - cancelLongPress(); + this.cancelPendingInputEvents(); + this.cancelLongPress(); scrollView.cancelLongPress(); scrollView.cancelPendingInputEvents(); - isTap = false; } - private void ReTruncateScrollText(){ + public void ReTruncateScrollText(){ ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { - textView.setText(songTruncated); + setText(songTruncated); } }, RETRUNCATE_DELAY+100); } + + private void setText(String text){ + currentlySettingTextHere = true; + textView.setText(text); + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 1522bda97..d6a6a993e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -12,7 +12,7 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { public interface OnEndScrollListener { - public void onEndScroll(); + void onEndScroll(); } private long lastScrollUpdate = -1; diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 3cbbc90fd..cba870af3 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -2,9 +2,13 @@ + android:layout_height="match_parent" + app:setTouchInterceptHorizontalScrollView="@+id/title_scrollview" + app:setScrollableTextView="@+id/album_title" + app:setListParent="@+id/list" > + android:orientation="vertical" > + android:paddingRight="72dp" > + android:nestedScrollingEnabled="true" > - + tools:ignore="UnusedAttribute" + app:setTouchInterceptHorizontalScrollView="@+id/title_scrollview" + app:setScrollableTextView="@+id/mini_player_title" > - + android:gravity="center_vertical" > + + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 6a0717262..d57f12afe 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,12 +1,15 @@ - + tools:ignore="UnusedAttribute" + app:setTouchInterceptHorizontalScrollView="@+id/title_scrollview" + app:setScrollableTextView="@+id/title" > + android:paddingStart="16dp" > + android:nestedScrollingEnabled="true" > + + + + + \ No newline at end of file From 6057efa97e745c37c4a13b56d084667f3686cbc4 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 9 Jul 2017 15:23:01 -0400 Subject: [PATCH 43/97] SearchAdapter Fix --- .../gramophone/adapter/SearchAdapter.java | 11 +++++++- .../views/TouchInterceptFrameLayout.java | 25 ++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java index bc1703a9a..40f3f3fd5 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java @@ -44,6 +44,8 @@ public class SearchAdapter extends RecyclerView.Adapter dataSet; + private RecyclerView recyclerView; + public SearchAdapter(@NonNull AppCompatActivity activity, @NonNull List dataSet) { this.activity = activity; this.dataSet = dataSet; @@ -62,6 +64,12 @@ public int getItemViewType(int position) { return HEADER; } + @Override + public void onAttachedToRecyclerView(RecyclerView rV) { + super.onAttachedToRecyclerView(rV); + recyclerView = rV; + } + @NonNull @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @@ -73,11 +81,12 @@ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @SuppressWarnings("ConstantConditions") @Override public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { + if(holder.itemView instanceof TouchInterceptFrameLayout) + ((TouchInterceptFrameLayout) holder.itemView).setListParent(recyclerView); switch (getItemViewType(position)) { case ALBUM: final Album album = (Album) dataSet.get(position); holder.title.setText(album.getTitle()); - if(holder.itemView instanceof TouchInterceptFrameLayout) holder.text.setText(album.getArtistName()); SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) .checkIgnoreMediaStore(activity).build() diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 1240fe9bd..11855a5e9 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -42,6 +42,7 @@ public class TouchInterceptFrameLayout extends FrameLayout { private TouchInterceptHorizontalScrollView scrollView; private TextView textView; private View listParent; + private TouchInterceptFrameLayout frameLayout; private int scrollViewID; private int textViewID; @@ -66,7 +67,7 @@ public void afterTextChanged(Editable s) { if (sV != null) scrollView = sV; TextView tV = (TextView) findViewById(textViewID); if(tV != null) textView = tV; - View lP = (View) findViewById(listParentID); + View lP = findViewById(listParentID); if(lP != null) listParent = lP; setTruncateText(textView.getText().toString()); @@ -101,16 +102,14 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe scrollViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setTouchInterceptHorizontalScrollView, 0); textViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setScrollableTextView, 0); listParentID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setListParent, 0); - - Log.d("Pre Post","true"); + frameLayout = this; this.post(new Runnable() { @Override public void run() { - Log.d("this Post","true"); scrollView = (TouchInterceptHorizontalScrollView) findViewById(scrollViewID); textView = (TextView) findViewById(textViewID); - View lP = (View) findViewById(listParentID); + View lP = findViewById(listParentID); if(lP != null) listParent = lP; textView.post(new Runnable() { @@ -209,19 +208,21 @@ public void setTruncateText(String s){ textView.post(new Runnable() { @Override public void run() { - Log.d("Truncate text",song); song = textView.getText().toString(); songTruncated = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), TextUtils.TruncateAt.END).toString(); + if (!songTruncated.isEmpty()) { setText(songTruncated); - Log.d("Truncated text",songTruncated); + if(songTruncated.equals(song)) { scrollView.setScrollingEnabled(false); + }else{ scrollView.setScrollingEnabled(true); + scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() { @Override @@ -240,6 +241,11 @@ public void onEndScroll() { } } + private void setText(String text){ + currentlySettingTextHere = true; + textView.setText(text); + } + /** * This intercepts the touch event and, by returning false and onTouchEvent(), passes the touchevent * to both itself and its child views (by calling TouchEvent it passes it to itself). @@ -336,9 +342,4 @@ public void run() { } }, RETRUNCATE_DELAY+100); } - - private void setText(String text){ - currentlySettingTextHere = true; - textView.setText(text); - } } From 885a6067a83065355dbc6a3613c4c668f396eed3 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 9 Jul 2017 19:06:50 -0400 Subject: [PATCH 44/97] Added correct scroll state int for recycler view --- .../gramophone/views/TouchInterceptFrameLayout.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 11855a5e9..cd57940a6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -164,9 +164,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); - if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { - CancelClick(); - } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { CancelClick(); } } @@ -297,7 +295,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (distance > MAX_CLICK_DISTANCE) { if((!emptyTruncateText && isTextTruncated)) setText(song); CancelClick(); - this.requestDisallowInterceptTouchEvent(true); + isTap = false; } } From 6a3cbec300e0eb8e25c7f946c37292d7fecc84e1 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 9 Jul 2017 23:04:16 -0400 Subject: [PATCH 45/97] Added documentation --- .../views/TouchInterceptFrameLayout.java | 71 ++++++++++++++++--- .../TouchInterceptHorizontalScrollView.java | 41 +++++++++-- app/src/main/res/values/attrs.xml | 11 +++ 3 files changed, 106 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index cd57940a6..c72513d6c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -26,7 +26,12 @@ * @author Lincoln (theduffmaster) * * A custom FrameLayout view that intercepts touch events and decides whether to consume them or - * pass on the touch events to its children. + * pass on the touch events to a TouchInterceptHorizontalScrollview which contains a TextView. + * In order for this to work properly the child views, + * a TouchInterceptHorizontalScrollView and a TextView, must be set via xml using the + * setTouchInterceptHorizontalScrollView and setScrollableTextView xml attributes. If this view is ever + * scrolled or interacts with a ListParent that is a ListView or a RecyclerView, then that ListParent + * must be set programmatically or via the designated XML attribute. */ public class TouchInterceptFrameLayout extends FrameLayout { @@ -34,8 +39,17 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final int RETRUNCATE_DELAY = 500; private String TAG = "E/TouchInterceptFL"; - private String NULL_VIEWS_EXCEPTION_MESSAGE = "Did you forget to call setViews" + "" + - "when creating your FrameLayout? Either textView or scrollView is null."; + private String XML_VIEW_IDS_NOT_SET = "It appears as if the IDs for the TouchInterceptHorizontalScrollView and its" + + "child scrollable TextView have not been set. If you have not already, you must set " + + "them using setTouchInterceptHorizontalScrollView and setScrollableTextView via XML"; + private String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you" + + "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + + "via XML? Did you set it to something null?"; + private String NULL_LIST_PARENT = "The ListParent, aka the parent ListView or RecyclerView is null." + + "It is highly reccomended you set the ListParent either programmatically or via XML" + + "if you're TouchInterceptFrameLayout is associated with any type of ListParent. If your" + + "TouchInterceptFrameLayout does not interact with any type of ListParent no need to set it" + + "and ignore this message."; private String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + "to set the song string when setting the song name in your text view?"; @@ -57,6 +71,11 @@ public class TouchInterceptFrameLayout extends FrameLayout { private String songTruncated; private String song; + /** + * A TextWatcher used to monitor when the contents of this view has changed + * since if this view is in a list it will be recycled. This ensures instances are current + * and when the text changes it will be truncated. + */ protected TextWatcher truncateTextWatcher = new TextWatcher() { @Override @@ -99,8 +118,17 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TouchInterceptFrameLayout, defStyleAttr, 0); + //Must be the ID of a child TouchInterceptHorizontalScrollView scrollViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setTouchInterceptHorizontalScrollView, 0); + //Must be the ID of a TextView that is the child of the above referenced TouchInterceptHorizontalScrollView textViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setScrollableTextView, 0); + + if(scrollViewID == 0 | textViewID == 0){ + Log.e(TAG,XML_VIEW_IDS_NOT_SET); + Log.e("ScrollViewID = ", Integer.toString(scrollViewID)); + Log.d("TextViewID = ", Integer.toString(textViewID)); + } + listParentID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setListParent, 0); frameLayout = this; @@ -125,10 +153,7 @@ public void run() { } /** - * Fetches the HorizontalScrollView contained by this FrameLayout and also gets the - * TextView that is contained within that HorizontalScrollView. - * Must be called before setTruncateText. - * Call this when you are assigning views in your layout. + * Sets the TouchInterceptHorizontalScrollView contained by this FrameLayout * @param sv The HorizontalScrollView containing text that needs to be scrolled */ public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScrollView sv) { @@ -136,22 +161,29 @@ public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScroll } /** - * Fetches the HorizontalScrollView contained by this FrameLayout and also gets the - * TextView that is contained within that HorizontalScrollView. - * Must be called before setTruncateText. - * Call this when you are assigning views in your layout. + * Sets the TextView that is contained within that TouchInterceptHorizontalScrollView. * @param tv The TextView that needs to be scrolled (typically song or album title) */ public void setScrollableTextView(TextView tv) { this.textView = tv; } + /** + * Sets the List Parent programmatically + * @param lP Must be either a type of RecyclerView or a type of ListView + */ public void setListParent(View lP){ this.listParent = lP; } + /** + * Gets the ListParent (the parent ListView or RecyclerView) that has been + * set via xml or programmatically and sets a Scroll Listener. When scrolling + * clicks are cancelled to prevent any interference with scrolling. + */ public void initializeListParent(){ + try{ if(listParent instanceof RecyclerView){ ((RecyclerView) listParent).addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -186,6 +218,11 @@ public void onScrollStateChanged(AbsListView view, int newState) { } }); } + }catch (NullPointerException exception){ + Log.w(TAG, NULL_LIST_PARENT); + Log.w(TAG, "listParent = " + listParent.toString()); + Log.w(TAG, exception.toString()); + } } /** @@ -235,10 +272,17 @@ public void onEndScroll() { }); }catch (NullPointerException exception){ Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); + Log.e(TAG, "TextView = " + textView); Log.e(TAG, exception.toString()); } } + /** + * Used to set the text and indicate that the TextView text is being + * set in this CustomView class and not somewhere else. + * @param text The text to set the TextView to + */ private void setText(String text){ currentlySettingTextHere = true; textView.setText(text); @@ -312,6 +356,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { }catch (NullPointerException exception) { Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); + Log.e(TAG, "TextView = " + textView); Log.e(TAG, exception.toString()); onTouchEvent(e); return false; @@ -330,6 +376,9 @@ private void CancelClick(){ scrollView.cancelPendingInputEvents(); } + /** + * Retruncates the text with a fancy scroll to beginning animation + */ public void ReTruncateScrollText(){ ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); final Handler handler = new Handler(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index d6a6a993e..79843a57b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -9,18 +9,30 @@ * Created by lincoln on 7/3/17. */ +/** + * A custom HorizontalScrollView that is only useful as the child of a TouchInterceptFrameLayout. + * This allows for the TouchInterceptFrameLayout to disable and enable scrolling in addition to + * being able to know when a user is and is not interacting with the scrolling view. + */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { + /** + * Listens for when a user has stopped interacting with the scroll view + */ public interface OnEndScrollListener { + // Triggered when a user has stopped interacting with the scroll view void onEndScroll(); } private long lastScrollUpdate = -1; + private boolean cancel; + + //The delay before triggering onEndScroll() private int delay = 1000; private class ScrollStateHandler implements Runnable { - + //Runs when the user has not touched the scroll view for 1 second @Override public void run() { if(!cancel) { @@ -52,14 +64,22 @@ public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, i super(context, attrs, defStyleAttr); } - // true if we can scroll (not locked) - // false if we cannot scroll (locked) + // "true" if we can scroll (not locked) + // "false" if we cannot scroll (locked) private boolean mScrollable = true; + /** + * Disables and enables the ScrollView + * @param enabled set to "true" to enable, "false" to disable + */ public void setScrollingEnabled(boolean enabled) { mScrollable = enabled; } + /** + * Returns whether the ScrollView is enabled or disabled + * @return Returns "true" if enabled, "false" if disabled + */ public boolean isScrollable() { return mScrollable; } @@ -69,13 +89,14 @@ public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: cancel = true; - // if we can scroll pass the event to the superclass + // If we can scroll pass the event to the superclass if (mScrollable) return super.onTouchEvent(ev); - // only continue to handle the touch event if scrolling enabled + // Only continue to handle the touch event if scrolling enabled return mScrollable; // mScrollable is always false at this point case MotionEvent.ACTION_UP: cancel = false; - postDelayed(new ScrollStateHandler(), delay); + // The user is done interacting with the scroll view + postDelayed(new ScrollStateHandler(), delay); lastScrollUpdate = System.currentTimeMillis(); default: return super.onTouchEvent(ev); @@ -90,10 +111,18 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { else return super.onInterceptTouchEvent(ev); } + /** + * Fetches the OnEndScrollListener + * @return Returns the OnEndScrollListener + */ public OnEndScrollListener getOnEndScrollListener() { return onEndScrollListener; } + /** + * Sets an OnEndScrollListener. Only one can be set at a time. + * @param mOnEndScrollListener The OnEndScrollListener to be set + */ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.onEndScrollListener = mOnEndScrollListener; } diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index c1619753a..02f02b890 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -11,9 +11,20 @@ + + + + + From 194837f3d4f22085633a93586334ed00651a6297 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 9 Jul 2017 23:25:36 -0400 Subject: [PATCH 46/97] Code cleanup --- .../com/kabouzeid/gramophone/adapter/song/SongAdapter.java | 7 +++---- app/src/main/res/layout/fragment_mini_player.xml | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 473ec9458..d51d8e01c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -109,6 +109,9 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { boolean isChecked = isChecked(song); holder.itemView.setActivated(isChecked); + if (holder.itemView instanceof TouchInterceptFrameLayout) + ((TouchInterceptFrameLayout) holder.itemView).setListParent(recyclerView); + if (holder.getAdapterPosition() == getItemCount() - 1) { if (holder.shortSeparator != null) { holder.shortSeparator.setVisibility(View.GONE); @@ -121,10 +124,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); - - if (holder.itemView instanceof TouchInterceptFrameLayout) - ((TouchInterceptFrameLayout) holder.itemView).setListParent(recyclerView); - } if (holder.text != null) { diff --git a/app/src/main/res/layout/fragment_mini_player.xml b/app/src/main/res/layout/fragment_mini_player.xml index 9fc18c0f4..cf93c9e85 100644 --- a/app/src/main/res/layout/fragment_mini_player.xml +++ b/app/src/main/res/layout/fragment_mini_player.xml @@ -53,6 +53,7 @@ android:ellipsize="end" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" tools:ignore="UnusedAttribute" + android:fontFamily="sans-serif" android:singleLine="true" /> From 1d42670b8282758e4bbe8ec6a9bde0f1b493edb9 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 10 Jul 2017 21:53:46 -0400 Subject: [PATCH 47/97] Added CanScroll() boolean to fix truncating on text that does not need to be truncated --- .../views/TouchInterceptFrameLayout.java | 49 ++++++++++--------- .../TouchInterceptHorizontalScrollView.java | 16 ++++++ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index c72513d6c..3bcb6f3af 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -243,31 +243,34 @@ public void setTruncateText(String s){ textView.post(new Runnable() { @Override public void run() { - song = textView.getText().toString(); - songTruncated = TextUtils.ellipsize(song, - textView.getPaint(), - (float) scrollView.getWidth(), - TextUtils.TruncateAt.END).toString(); - - if (!songTruncated.isEmpty()) { - setText(songTruncated); - - if(songTruncated.equals(song)) { - scrollView.setScrollingEnabled(false); - - }else{ - scrollView.setScrollingEnabled(true); - - scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() - { - @Override - public void onEndScroll() { - ReTruncateScrollText(); - } - }); + if (scrollView.canScroll()) { + song = textView.getText().toString(); + songTruncated = TextUtils.ellipsize(song, + textView.getPaint(), + (float) scrollView.getWidth(), + TextUtils.TruncateAt.END).toString(); + + if (!songTruncated.isEmpty()) { + setText(songTruncated); + + if (songTruncated.equals(song)) { + scrollView.setScrollingEnabled(false); + + } else { + scrollView.setScrollingEnabled(true); + + scrollView.setOnEndScrollListener( + new TouchInterceptHorizontalScrollView.OnEndScrollListener() { + @Override + public void onEndScroll() { + ReTruncateScrollText(); + } + }); + } + initializeListParent(); } - initializeListParent(); } + } }); }catch (NullPointerException exception){ diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 79843a57b..069b54417 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -3,8 +3,12 @@ import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; +import android.view.View; import android.widget.HorizontalScrollView; +import static android.R.attr.paddingBottom; +import static android.R.attr.paddingTop; + /** * Created by lincoln on 7/3/17. */ @@ -84,6 +88,18 @@ public boolean isScrollable() { return mScrollable; } + /** + * @return Returns true this ScrollView can be scrolled + */ + public boolean canScroll() { + View child = getChildAt(0); + if (child != null) { + int childHeight = child.getHeight(); + return getHeight() < childHeight + paddingTop + paddingBottom; + } + return false; + } + @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { From f85f927601e7cfdef0171cf303a01b235531c72d Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 10 Jul 2017 23:02:29 -0400 Subject: [PATCH 48/97] Implemented safer way to test CanScroll --- .../views/TouchInterceptHorizontalScrollView.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 069b54417..af7d16170 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -3,12 +3,8 @@ import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; -import android.view.View; import android.widget.HorizontalScrollView; -import static android.R.attr.paddingBottom; -import static android.R.attr.paddingTop; - /** * Created by lincoln on 7/3/17. */ @@ -92,12 +88,11 @@ public boolean isScrollable() { * @return Returns true this ScrollView can be scrolled */ public boolean canScroll() { - View child = getChildAt(0); - if (child != null) { - int childHeight = child.getHeight(); - return getHeight() < childHeight + paddingTop + paddingBottom; + if(canScrollHorizontally(1) || canScrollHorizontally(-1)){ + return true; + }else{ + return false; } - return false; } @Override From 096786c7e504eebd6c7878e2f30f4b10802a84b1 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 10 Jul 2017 23:38:01 -0400 Subject: [PATCH 49/97] Code cleanup --- .../ui/activities/AlbumDetailActivity.java | 3 -- .../views/TouchInterceptFrameLayout.java | 36 ++++++++----------- .../TouchInterceptHorizontalScrollView.java | 30 +++++++--------- 3 files changed, 28 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index e14b12652..d0fa5cd59 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -47,7 +47,6 @@ import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; -import com.kabouzeid.gramophone.views.TouchInterceptHorizontalScrollView; import butterknife.BindView; import butterknife.ButterKnife; @@ -77,8 +76,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements RelativeLayout albumTitleView; @BindView(R.id.album_title) TextView albumTitleTextView; - @BindView(R.id.title_scrollview) - TouchInterceptHorizontalScrollView titleScrollView; @BindView(R.id.list_background) View songsBackgroundView; @BindView(R.id.status_bar) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 3bcb6f3af..685ca7f89 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -36,40 +36,39 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final int MAX_CLICK_DISTANCE = 5; - private static final int RETRUNCATE_DELAY = 500; + private static final int RETRUNCATE_DELAY = 600; - private String TAG = "E/TouchInterceptFL"; - private String XML_VIEW_IDS_NOT_SET = "It appears as if the IDs for the TouchInterceptHorizontalScrollView and its" + + private static final String TAG = "E/TouchInterceptFL"; + private static final String XML_VIEW_IDS_NOT_SET = "It appears as if the IDs for the TouchInterceptHorizontalScrollView and its" + "child scrollable TextView have not been set. If you have not already, you must set " + "them using setTouchInterceptHorizontalScrollView and setScrollableTextView via XML"; - private String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you" + + private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you" + "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + "via XML? Did you set it to something null?"; - private String NULL_LIST_PARENT = "The ListParent, aka the parent ListView or RecyclerView is null." + + private static final String NULL_LIST_PARENT = "The ListParent, aka the parent ListView or RecyclerView is null." + "It is highly reccomended you set the ListParent either programmatically or via XML" + "if you're TouchInterceptFrameLayout is associated with any type of ListParent. If your" + "TouchInterceptFrameLayout does not interact with any type of ListParent no need to set it" + "and ignore this message."; - private String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + + private static final String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + "to set the song string when setting the song name in your text view?"; - private TouchInterceptHorizontalScrollView scrollView; - private TextView textView; - private View listParent; - private TouchInterceptFrameLayout frameLayout; - private int scrollViewID; private int textViewID; private int listParentID; + private TouchInterceptHorizontalScrollView scrollView; + private TextView textView; + private View listParent; + private Rect scrollViewRect = new Rect(); private float startX; private boolean isTap; private boolean currentlySettingTextHere = false; - private String songTruncated; private String song; + private String songTruncated; /** * A TextWatcher used to monitor when the contents of this view has changed @@ -96,14 +95,10 @@ public void afterTextChanged(Editable s) { } @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } + public void onTextChanged(CharSequence s, int start, int before, int count) {} }; public TouchInterceptFrameLayout(@NonNull Context context) { @@ -130,7 +125,6 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe } listParentID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setListParent, 0); - frameLayout = this; this.post(new Runnable() { @Override @@ -380,7 +374,7 @@ private void CancelClick(){ } /** - * Retruncates the text with a fancy scroll to beginning animation + * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time */ public void ReTruncateScrollText(){ ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); @@ -390,6 +384,6 @@ public void ReTruncateScrollText(){ public void run() { setText(songTruncated); } - }, RETRUNCATE_DELAY+100); + }, RETRUNCATE_DELAY); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index af7d16170..2bfff1b63 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -16,6 +16,14 @@ */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { + //The delay before triggering onEndScroll() + public static final int ON_END_SCROLL_DELAY = 1000; + + private long lastScrollUpdate = -1; + private boolean cancel; + + private OnEndScrollListener onEndScrollListener; + /** * Listens for when a user has stopped interacting with the scroll view */ @@ -24,34 +32,24 @@ public interface OnEndScrollListener { void onEndScroll(); } - private long lastScrollUpdate = -1; - - private boolean cancel; - - //The delay before triggering onEndScroll() - private int delay = 1000; - private class ScrollStateHandler implements Runnable { //Runs when the user has not touched the scroll view for 1 second @Override public void run() { if(!cancel) { long currentTime = System.currentTimeMillis(); - if ((currentTime - lastScrollUpdate) > delay) { + if ((currentTime - lastScrollUpdate) > ON_END_SCROLL_DELAY) { lastScrollUpdate = -1; if (onEndScrollListener != null) { onEndScrollListener.onEndScroll(); } } else { - postDelayed(this, delay); + postDelayed(this, ON_END_SCROLL_DELAY); } } } } - private OnEndScrollListener onEndScrollListener; - - public TouchInterceptHorizontalScrollView(Context context) { super(context); } @@ -85,7 +83,7 @@ public boolean isScrollable() { } /** - * @return Returns true this ScrollView can be scrolled + * @return Returns true if this ScrollView can be scrolled */ public boolean canScroll() { if(canScrollHorizontally(1) || canScrollHorizontally(-1)){ @@ -107,7 +105,7 @@ public boolean onTouchEvent(MotionEvent ev) { case MotionEvent.ACTION_UP: cancel = false; // The user is done interacting with the scroll view - postDelayed(new ScrollStateHandler(), delay); + postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); lastScrollUpdate = System.currentTimeMillis(); default: return super.onTouchEvent(ev); @@ -123,8 +121,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { } /** - * Fetches the OnEndScrollListener - * @return Returns the OnEndScrollListener + * @return Returns the set OnEndScrollListener */ public OnEndScrollListener getOnEndScrollListener() { return onEndScrollListener; @@ -138,5 +135,4 @@ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.onEndScrollListener = mOnEndScrollListener; } - } From 19a02bc7410a312017e2258cfe19a0ef75ec601a Mon Sep 17 00:00:00 2001 From: Duffman Date: Thu, 13 Jul 2017 13:38:45 -0400 Subject: [PATCH 50/97] Fix inconsistent dragging on playing queue sliding panel --- .../views/TouchInterceptFrameLayout.java | 6 ++++- .../TouchInterceptHorizontalScrollView.java | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 685ca7f89..8866d5f65 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -184,6 +184,7 @@ public void initializeListParent(){ @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); + scrollView.slidingPanelSetTouchEnabled(true); } @Override @@ -200,7 +201,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if(listParent instanceof ListView){ ((ListView) listParent).setOnScrollListener(new AbsListView.OnScrollListener(){ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - + scrollView.slidingPanelSetTouchEnabled(true); } public void onScrollStateChanged(AbsListView view, int newState) { @@ -317,6 +318,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: + scrollView.slidingPanelSetTouchEnabled(true); if (!touchedScrollView){ scrollView.cancelPendingInputEvents(); return false; @@ -343,6 +345,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: + scrollView.slidingPanelSetTouchEnabled(true); if (touchedScrollView) { if (isTap) onTouchEvent(e); } @@ -378,6 +381,7 @@ private void CancelClick(){ */ public void ReTruncateScrollText(){ ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); + scrollView.slidingPanelSetTouchEnabled(true); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 2bfff1b63..627b4d70d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -1,10 +1,14 @@ package com.kabouzeid.gramophone.views; +import android.app.Activity; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.HorizontalScrollView; +import com.kabouzeid.gramophone.R; +import com.sothree.slidinguppanel.SlidingUpPanelLayout; + /** * Created by lincoln on 7/3/17. */ @@ -21,9 +25,12 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private long lastScrollUpdate = -1; private boolean cancel; + private boolean touched; private OnEndScrollListener onEndScrollListener; + private SlidingUpPanelLayout queue; + /** * Listens for when a user has stopped interacting with the scroll view */ @@ -98,11 +105,14 @@ public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: cancel = true; + touched = true; // If we can scroll pass the event to the superclass if (mScrollable) return super.onTouchEvent(ev); // Only continue to handle the touch event if scrolling enabled return mScrollable; // mScrollable is always false at this point case MotionEvent.ACTION_UP: + slidingPanelSetTouchEnabled(true); + touched = false; cancel = false; // The user is done interacting with the scroll view postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); @@ -114,6 +124,9 @@ public boolean onTouchEvent(MotionEvent ev) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if(ev.getAction() == MotionEvent.ACTION_DOWN){ + slidingPanelSetTouchEnabled(true); + } // Don't do anything with intercepted touch events if // we are not scrollable if (!mScrollable) return false; @@ -135,4 +148,18 @@ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.onEndScrollListener = mOnEndScrollListener; } + @Override + protected void onScrollChanged(int x, int y, int oldX, int oldY) { + super.onScrollChanged(x, y, oldX, oldY); + if(touched) slidingPanelSetTouchEnabled(false); + } + + /** + * Enables and disables Sliding Panel dragging for the playing queue sliding panel + * @param enable Set true to enable dragging, false to disable + */ + public void slidingPanelSetTouchEnabled(boolean enable){ + queue = (SlidingUpPanelLayout) ((Activity)getContext()).findViewById(R.id.player_sliding_layout); + if(queue != null) queue.setTouchEnabled(enable); + } } From 0f99fd739d0d3f430686e95e01d0ce3ba175e6de Mon Sep 17 00:00:00 2001 From: Duffman Date: Thu, 13 Jul 2017 22:36:09 -0400 Subject: [PATCH 51/97] Possibly fixed long press getting canceled --- .../views/TouchInterceptFrameLayout.java | 15 ++++++--------- .../views/TouchInterceptHorizontalScrollView.java | 12 ++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 8866d5f65..7f74d59b4 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -175,7 +175,7 @@ public void setListParent(View lP){ * set via xml or programmatically and sets a Scroll Listener. When scrolling * clicks are cancelled to prevent any interference with scrolling. */ - public void initializeListParent(){ + public void InitializeListParent(){ try{ if(listParent instanceof RecyclerView){ @@ -258,11 +258,11 @@ public void run() { new TouchInterceptHorizontalScrollView.OnEndScrollListener() { @Override public void onEndScroll() { - ReTruncateScrollText(); + reTruncateScrollText(); } }); } - initializeListParent(); + InitializeListParent(); } } @@ -337,8 +337,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { if((!emptyTruncateText && isTextTruncated)) setText(song); - CancelClick(); - isTap = false; } } @@ -365,9 +363,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } /** - * Cancels any Long Presses and inpending clicks. Used to prevent views from - * acting on touches while vertically scrolling or any case where the user is not - * interacting with the item views + *Cancels any Long Presses and inpending clicks. Used to prevent views from + * stealing touches while the user is scrolling something. */ private void CancelClick(){ this.cancelPendingInputEvents(); @@ -379,7 +376,7 @@ private void CancelClick(){ /** * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time */ - public void ReTruncateScrollText(){ + public void reTruncateScrollText(){ ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); scrollView.slidingPanelSetTouchEnabled(true); final Handler handler = new Handler(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 627b4d70d..d6f82ebd7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -152,6 +152,7 @@ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if(touched) slidingPanelSetTouchEnabled(false); + CancelClick(); } /** @@ -162,4 +163,15 @@ public void slidingPanelSetTouchEnabled(boolean enable){ queue = (SlidingUpPanelLayout) ((Activity)getContext()).findViewById(R.id.player_sliding_layout); if(queue != null) queue.setTouchEnabled(enable); } + + /** + * Cancels any Long Presses and inpending clicks. Used to prevent views from + * stealing touches while the user is scrolling something. + */ + public void CancelClick(){ + getRootView().cancelLongPress(); + getRootView().cancelPendingInputEvents(); + this.cancelLongPress(); + this.cancelPendingInputEvents(); + } } From c96bc958a9ec369c16c674168d63164bff0e12b9 Mon Sep 17 00:00:00 2001 From: Duffman Date: Thu, 13 Jul 2017 22:49:44 -0400 Subject: [PATCH 52/97] Removed mini player scrolling ability --- .../main/res/layout/fragment_mini_player.xml | 37 ++++--------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/app/src/main/res/layout/fragment_mini_player.xml b/app/src/main/res/layout/fragment_mini_player.xml index cf93c9e85..fe6792c3a 100644 --- a/app/src/main/res/layout/fragment_mini_player.xml +++ b/app/src/main/res/layout/fragment_mini_player.xml @@ -1,5 +1,5 @@ - + tools:ignore="UnusedAttribute"> - - - - - - - - - + android:gravity="center_vertical" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> - \ No newline at end of file + \ No newline at end of file From fbbb5e94645a5a2e9cfcb02b90c5ca85eb7928c2 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 14 Jul 2017 00:31:03 -0400 Subject: [PATCH 53/97] Fixed long click not clicking --- .../views/TouchInterceptFrameLayout.java | 116 ++++++++++-------- 1 file changed, 67 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 7f74d59b4..94dab484b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -42,7 +42,7 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final String XML_VIEW_IDS_NOT_SET = "It appears as if the IDs for the TouchInterceptHorizontalScrollView and its" + "child scrollable TextView have not been set. If you have not already, you must set " + "them using setTouchInterceptHorizontalScrollView and setScrollableTextView via XML"; - private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you" + + private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you " + "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + "via XML? Did you set it to something null?"; private static final String NULL_LIST_PARENT = "The ListParent, aka the parent ListView or RecyclerView is null." + @@ -175,7 +175,7 @@ public void setListParent(View lP){ * set via xml or programmatically and sets a Scroll Listener. When scrolling * clicks are cancelled to prevent any interference with scrolling. */ - public void InitializeListParent(){ + public void initializeListParent(){ try{ if(listParent instanceof RecyclerView){ @@ -245,7 +245,7 @@ public void run() { (float) scrollView.getWidth(), TextUtils.TruncateAt.END).toString(); - if (!songTruncated.isEmpty()) { + if (songTruncated != null && !songTruncated.isEmpty()) { setText(songTruncated); if (songTruncated.equals(song)) { @@ -262,7 +262,9 @@ public void onEndScroll() { } }); } - InitializeListParent(); + initializeListParent(); + }else{ + scrollView.setScrollingEnabled(false); } } @@ -270,6 +272,7 @@ public void onEndScroll() { }); }catch (NullPointerException exception){ Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e("Method: ","setTruncateText()"); Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); Log.e(TAG, "TextView = " + textView); Log.e(TAG, exception.toString()); @@ -302,61 +305,76 @@ private void setText(String text){ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - int x = Math.round(e.getRawX()); - int y = Math.round(e.getRawY()); - try { - scrollView.getGlobalVisibleRect(scrollViewRect); + if(scrollView.isScrollable()) { - boolean touchedScrollView = - x > scrollViewRect.left && x < scrollViewRect.right && - y > scrollViewRect.top && y < scrollViewRect.bottom; + boolean emptyTruncateText; + boolean isTextTruncated; - boolean emptyTruncateText = songTruncated.isEmpty(); - if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); + int x = Math.round(e.getRawX()); + int y = Math.round(e.getRawY()); + try { + scrollView.getGlobalVisibleRect(scrollViewRect); - boolean isTextTruncated = songTruncated.endsWith("…"); + boolean touchedScrollView = + x > scrollViewRect.left && x < scrollViewRect.right && + y > scrollViewRect.top && y < scrollViewRect.bottom; - switch (e.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - scrollView.slidingPanelSetTouchEnabled(true); - if (!touchedScrollView){ - scrollView.cancelPendingInputEvents(); - return false; - } + if (songTruncated != null){ + emptyTruncateText = songTruncated.isEmpty(); + isTextTruncated = songTruncated.endsWith("…"); + if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); + }else{ + emptyTruncateText = true; + isTextTruncated = false; + Log.e(TAG, EMPTY_TRUNCATE_STRING); + } - startX = e.getX(); - isTap = true; - onTouchEvent(e); + switch (e.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + scrollView.slidingPanelSetTouchEnabled(true); + if (!touchedScrollView) { + scrollView.cancelPendingInputEvents(); + return false; + } - break; + startX = e.getX(); + isTap = true; + onTouchEvent(e); - case MotionEvent.ACTION_MOVE: - if (touchedScrollView) { - float distance = Math.abs(e.getX() - startX); + break; - // Scrolling the view: cancel event to prevent long press - if (distance > MAX_CLICK_DISTANCE) { - if((!emptyTruncateText && isTextTruncated)) setText(song); - isTap = false; + case MotionEvent.ACTION_MOVE: + if (touchedScrollView) { + float distance = Math.abs(e.getX() - startX); + + // Scrolling the view: cancel event to prevent long press + if (distance > MAX_CLICK_DISTANCE) { + if ((!emptyTruncateText && isTextTruncated)) setText(song); + isTap = false; + } } - } - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - scrollView.slidingPanelSetTouchEnabled(true); - if (touchedScrollView) { - if (isTap) onTouchEvent(e); - } - this.requestDisallowInterceptTouchEvent(false); - break; + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + scrollView.slidingPanelSetTouchEnabled(true); + if (touchedScrollView) { + if (isTap) onTouchEvent(e); + } + this.requestDisallowInterceptTouchEvent(false); + break; + } + return false; + + } catch (NullPointerException exception) { + Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e("Method: ","onInterceptTouchEvent()"); + Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); + Log.e(TAG, "TextView = " + textView); + Log.e(TAG, exception.toString()); + onTouchEvent(e); + return false; } - return false; - - }catch (NullPointerException exception) { - Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); - Log.e(TAG, "TextView = " + textView); - Log.e(TAG, exception.toString()); + }else{ onTouchEvent(e); return false; } From fc612058b7fd048c52261ee76a405b249fad5b11 Mon Sep 17 00:00:00 2001 From: Duffman Date: Fri, 21 Jul 2017 17:12:00 -0400 Subject: [PATCH 54/97] TextView intercepts settext and makes sure it doesn't blink but the implementation is flawed --- .../views/TouchInterceptFrameLayout.java | 48 +++--- .../TouchInterceptHorizontalScrollView.java | 16 +- .../views/TouchInterceptTextView.java | 137 ++++++++++++++++++ .../main/res/layout/activity_album_detail.xml | 2 +- app/src/main/res/layout/item_list.xml | 2 +- 5 files changed, 176 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 94dab484b..c8fb4aedc 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -18,7 +18,6 @@ import android.widget.AbsListView; import android.widget.FrameLayout; import android.widget.ListView; -import android.widget.TextView; import com.kabouzeid.gramophone.R; @@ -58,7 +57,7 @@ public class TouchInterceptFrameLayout extends FrameLayout { private int listParentID; private TouchInterceptHorizontalScrollView scrollView; - private TextView textView; + private TouchInterceptTextView textView; private View listParent; private Rect scrollViewRect = new Rect(); @@ -81,14 +80,14 @@ public class TouchInterceptFrameLayout extends FrameLayout { public void afterTextChanged(Editable s) { if(!currentlySettingTextHere){ - TouchInterceptHorizontalScrollView sV = (TouchInterceptHorizontalScrollView) findViewById(scrollViewID); + TouchInterceptHorizontalScrollView sV = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); if (sV != null) scrollView = sV; - TextView tV = (TextView) findViewById(textViewID); + TouchInterceptTextView tV = (TouchInterceptTextView) findViewWithTag("TITV"); if(tV != null) textView = tV; View lP = findViewById(listParentID); if(lP != null) listParent = lP; - setTruncateText(textView.getText().toString()); + //setTruncateText(textView.getText().toString()); } currentlySettingTextHere = false; @@ -103,34 +102,27 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {} public TouchInterceptFrameLayout(@NonNull Context context) { this(context, null); + setTag("TIFL"); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); + setTag("TIFL"); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + setTag("TIFL"); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TouchInterceptFrameLayout, defStyleAttr, 0); - //Must be the ID of a child TouchInterceptHorizontalScrollView - scrollViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setTouchInterceptHorizontalScrollView, 0); - //Must be the ID of a TextView that is the child of the above referenced TouchInterceptHorizontalScrollView - textViewID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setScrollableTextView, 0); - - if(scrollViewID == 0 | textViewID == 0){ - Log.e(TAG,XML_VIEW_IDS_NOT_SET); - Log.e("ScrollViewID = ", Integer.toString(scrollViewID)); - Log.d("TextViewID = ", Integer.toString(textViewID)); - } listParentID = a.getResourceId(R.styleable.TouchInterceptFrameLayout_setListParent, 0); this.post(new Runnable() { @Override public void run() { - scrollView = (TouchInterceptHorizontalScrollView) findViewById(scrollViewID); - textView = (TextView) findViewById(textViewID); + scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); + textView = (TouchInterceptTextView) findViewWithTag("TITV"); View lP = findViewById(listParentID); if(lP != null) listParent = lP; @@ -158,7 +150,7 @@ public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScroll * Sets the TextView that is contained within that TouchInterceptHorizontalScrollView. * @param tv The TextView that needs to be scrolled (typically song or album title) */ - public void setScrollableTextView(TextView tv) { + public void setScrollableTextView(TouchInterceptTextView tv) { this.textView = tv; } @@ -215,7 +207,7 @@ public void onScrollStateChanged(AbsListView view, int newState) { } }catch (NullPointerException exception){ Log.w(TAG, NULL_LIST_PARENT); - Log.w(TAG, "listParent = " + listParent.toString()); + System.out.println(TAG + " listParent = " + listParent.toString()); Log.w(TAG, exception.toString()); } } @@ -234,6 +226,8 @@ public void onScrollStateChanged(AbsListView view, int newState) { public void setTruncateText(String s){ song = s; try { + scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); + textView = (TouchInterceptTextView) findViewWithTag("TITV"); //runs after scrollview has been drawn textView.post(new Runnable() { @Override @@ -243,7 +237,7 @@ public void run() { songTruncated = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), - TextUtils.TruncateAt.END).toString(); + TextUtils.TruncateAt.END).toString() + "\u202F"; if (songTruncated != null && !songTruncated.isEmpty()) { setText(songTruncated); @@ -266,6 +260,8 @@ public void onEndScroll() { }else{ scrollView.setScrollingEnabled(false); } + }else{ + scrollView.setScrollingEnabled(false); } } @@ -273,8 +269,8 @@ public void onEndScroll() { }catch (NullPointerException exception){ Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); Log.e("Method: ","setTruncateText()"); - Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); - Log.e(TAG, "TextView = " + textView); + System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + scrollView.toString()); + System.out.println(TAG + " TouchInterceptTextView = " + textView); Log.e(TAG, exception.toString()); } } @@ -321,7 +317,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (songTruncated != null){ emptyTruncateText = songTruncated.isEmpty(); - isTextTruncated = songTruncated.endsWith("…"); + isTextTruncated = songTruncated.endsWith("…\u202F"); if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); }else{ emptyTruncateText = true; @@ -349,7 +345,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { - if ((!emptyTruncateText && isTextTruncated)) setText(song); + if ((!emptyTruncateText && isTextTruncated)) setText(song+"\uFEFF"); isTap = false; } } @@ -368,8 +364,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } catch (NullPointerException exception) { Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); Log.e("Method: ","onInterceptTouchEvent()"); - Log.e(TAG, "TouchInterceptHorizontalScrollView = " + scrollView.toString()); - Log.e(TAG, "TextView = " + textView); + System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + scrollView.toString()); + System.out.println(TAG + " TouchInterceptTextView = " + textView); Log.e(TAG, exception.toString()); onTouchEvent(e); return false; diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index d6f82ebd7..e5aa8666a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -4,6 +4,7 @@ import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; +import android.view.ViewGroup; import android.widget.HorizontalScrollView; import com.kabouzeid.gramophone.R; @@ -59,10 +60,12 @@ public void run() { public TouchInterceptHorizontalScrollView(Context context) { super(context); + setTag("TIHS"); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); + setTag("TIHS"); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { @@ -129,7 +132,10 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { } // Don't do anything with intercepted touch events if // we are not scrollable - if (!mScrollable) return false; + if (!mScrollable){ + onTouchEvent(ev); + return false; + } else return super.onInterceptTouchEvent(ev); } @@ -174,4 +180,12 @@ public void CancelClick(){ this.cancelLongPress(); this.cancelPendingInputEvents(); } + + public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { + return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); + } + + public TouchInterceptTextView getTouchInterceptTextView(){ + return (TouchInterceptTextView) ((ViewGroup)this).getChildAt(0); + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java new file mode 100644 index 000000000..a44e1ee45 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -0,0 +1,137 @@ +package com.kabouzeid.gramophone.views; + +import android.animation.ObjectAnimator; +import android.content.Context; +import android.os.Handler; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatTextView; +import android.text.TextUtils; +import android.util.AttributeSet; + +import java.util.concurrent.Semaphore; + +/** + * Created by lincoln on 7/16/17. + */ + +public class TouchInterceptTextView extends AppCompatTextView { + private static final int RETRUNCATE_DELAY = 600; + + private static final String TAG = "E/TouchInterceptFL"; + private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you " + + "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + + "via XML? Did you set it to something null?"; + + private TouchInterceptFrameLayout touchInterceptFrameLayout; + private TouchInterceptHorizontalScrollView scrollView; + + private String song; + private String songTruncated; + + private static boolean truncateText; + + private final Semaphore semaphore = new Semaphore(0); + + public TouchInterceptTextView(Context context) { + super(context); + setTag("TITV"); + } + + public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + setTag("TITV"); + setLongClickable(true); + } + + public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setTag("TITV"); + setLongClickable(true); + } + + public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { + return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); + } + + public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { + return (TouchInterceptHorizontalScrollView) this.getParent(); + } + + @Override + public void setText(CharSequence text, BufferType type) { + String content= text.toString(); + try { + if (!isTextTruncated(text.toString()) && + !content.endsWith("\uFEFF") && + isTextTruncated(getText().toString())) { + song = content; + songTruncated = TextUtils.ellipsize(content, + getPaint(), + (float) getWidth(), + TextUtils.TruncateAt.END).toString() + "\u202F"; + super.setText(songTruncated, BufferType.NORMAL); + setTruncateText(song); + }else{ + super.setText(content, BufferType.NORMAL); + setTruncateText(content); + } + } catch (NullPointerException e){ + e.printStackTrace(); + super.setText(content, BufferType.NORMAL); + setTruncateText(content); + } + } + + public void setTruncateText(final String content){ + post(new Runnable() { + @Override + public void run() { + getTouchInterceptFrameLayout().setTruncateText(content); + } + }); + } + + /** + * Sets the TouchIntercept frame layout that is the RootView of the layout. + * Must be a TouchInterceptFrameLayout + * + * @param fL The FrameLayout to be set. + */ + public void setTouchInterceptFrameLayout(TouchInterceptFrameLayout fL) { + this.touchInterceptFrameLayout = fL; + } + + /** + * Sets the TouchInterceptHorizontalScrollView contained by this FrameLayout + * + * @param sv The HorizontalScrollView containing text that needs to be scrolled + */ + public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScrollView sv) { + this.scrollView = sv; + } + + public boolean isTextTruncated(String text) { + if (text.endsWith("…\u202F")) return true; + else return false; + } + + public void unTruncateText(){ + truncateText = false; + setText(song); + } + + /** + * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time + */ + public void reTruncateScrollText() { + ObjectAnimator.ofInt(getTouchInterceptHorizontalScrollView(), "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); + getTouchInterceptHorizontalScrollView().slidingPanelSetTouchEnabled(true); + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + setText(songTruncated); + } + }, RETRUNCATE_DELAY); + } +} diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index cba870af3..858ee2ea6 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -57,7 +57,7 @@ android:scrollbars="none" android:nestedScrollingEnabled="true" > - - Date: Sun, 23 Jul 2017 03:08:53 -0400 Subject: [PATCH 55/97] Commit before programmatically create scrollviews --- .../views/TouchInterceptFrameLayout.java | 34 ++- .../TouchInterceptHorizontalScrollView.java | 2 + .../views/TouchInterceptTextView.java | 250 ++++++++++++++++-- .../main/res/layout/activity_album_detail.xml | 10 +- app/src/main/res/layout/item_list.xml | 10 +- 5 files changed, 246 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index c8fb4aedc..3703e0a4f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -130,7 +130,6 @@ public void run() { @Override public void run() { textView.addTextChangedListener(truncateTextWatcher); - setTruncateText(textView.getText().toString()); } }); } @@ -162,6 +161,10 @@ public void setListParent(View lP){ this.listParent = lP; } + public View getListParent(){ + return listParent; + } + /** * Gets the ListParent (the parent ListView or RecyclerView) that has been * set via xml or programmatically and sets a Scroll Listener. When scrolling @@ -223,8 +226,9 @@ public void onScrollStateChanged(AbsListView view, int newState) { * cut off, still allowing the HorizontalScrollingView to scroll. * @param s The string (song title or album title typically) contained by the text view. */ - public void setTruncateText(String s){ + public void setTruncateText(String s, String sT){ song = s; + songTruncated = sT; try { scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); textView = (TouchInterceptTextView) findViewWithTag("TITV"); @@ -233,7 +237,6 @@ public void setTruncateText(String s){ @Override public void run() { if (scrollView.canScroll()) { - song = textView.getText().toString(); songTruncated = TextUtils.ellipsize(song, textView.getPaint(), (float) scrollView.getWidth(), @@ -285,6 +288,11 @@ private void setText(String text){ textView.setText(text); } + public boolean isTextTruncated(String text) { + if (text.endsWith("…\u202F")) return true; + else return false; + } + /** * This intercepts the touch event and, by returning false and onTouchEvent(), passes the touchevent * to both itself and its child views (by calling TouchEvent it passes it to itself). @@ -315,15 +323,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { x > scrollViewRect.left && x < scrollViewRect.right && y > scrollViewRect.top && y < scrollViewRect.bottom; - if (songTruncated != null){ - emptyTruncateText = songTruncated.isEmpty(); - isTextTruncated = songTruncated.endsWith("…\u202F"); - if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); - }else{ - emptyTruncateText = true; - isTextTruncated = false; - Log.e(TAG, EMPTY_TRUNCATE_STRING); - } +// if (songTruncated != null){ +// emptyTruncateText = songTruncated.isEmpty(); +// isTextTruncated = songTruncated.endsWith("…\u202F"); +// if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); +// }else{ +// emptyTruncateText = true; +// isTextTruncated = false; +// Log.e(TAG, EMPTY_TRUNCATE_STRING); +// } switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: @@ -345,7 +353,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { - if ((!emptyTruncateText && isTextTruncated)) setText(song+"\uFEFF"); + textView.unTruncateText(); isTap = false; } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index e5aa8666a..9d920e275 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -61,11 +61,13 @@ public void run() { public TouchInterceptHorizontalScrollView(Context context) { super(context); setTag("TIHS"); + setHorizontalScrollBarEnabled(false); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); setTag("TIHS"); + setHorizontalScrollBarEnabled(false); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index a44e1ee45..b66b1dd8c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -5,8 +5,13 @@ import android.os.Handler; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; +import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.AbsListView; +import android.widget.ListView; import java.util.concurrent.Semaphore; @@ -21,6 +26,11 @@ public class TouchInterceptTextView extends AppCompatTextView { private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you " + "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + "via XML? Did you set it to something null?"; + private static final String NULL_LIST_PARENT = "The ListParent, aka the parent ListView or RecyclerView is null." + + "It is highly reccomended you set the ListParent either programmatically or via XML" + + "if you're TouchInterceptFrameLayout is associated with any type of ListParent. If your" + + "TouchInterceptFrameLayout does not interact with any type of ListParent no need to set it" + + "and ignore this message."; private TouchInterceptFrameLayout touchInterceptFrameLayout; private TouchInterceptHorizontalScrollView scrollView; @@ -35,18 +45,51 @@ public class TouchInterceptTextView extends AppCompatTextView { public TouchInterceptTextView(Context context) { super(context); setTag("TITV"); + Log.d("Initiate", "1"); + + final TouchInterceptTextView tV = this; + post(new Runnable() { + @Override + public void run() { + final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); + song = getText().toString(); + if(sV.canScroll()) { + System.out.println("Width: " + Integer.toString(sV.getWidth())); + setText(getText().toString()); + }else{ + setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); + } + } + }); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setTag("TITV"); setLongClickable(true); + Log.d("Initiate", "2"); + + final TouchInterceptTextView tV = this; + post(new Runnable() { + @Override + public void run() { + final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); + song = getText().toString(); + if(sV.canScroll()) { + System.out.println("Width: " + Integer.toString(sV.getWidth())); + setText(getText().toString()); + }else{ + setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); + } + } + }); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setTag("TITV"); setLongClickable(true); + Log.d("Initiate", "3"); } public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { @@ -54,41 +97,178 @@ public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { } public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { - return (TouchInterceptHorizontalScrollView) this.getParent(); + return (TouchInterceptHorizontalScrollView) getParent(); } +// @Override +// public void setText(CharSequence text, BufferType type) { +// final String content= text.toString(); +// System.out.println("Width: "+Integer.toString(getWidth())); +// System.out.println("Current text: "+getText().toString()); +// System.out.println("Content: "+content); +// try { +// if(getWidth() > 0) { +// if (!getText().toString().endsWith("\u202F") && +// !content.endsWith("\uFEFF")) { +// song = content; +// songTruncated = TextUtils.ellipsize(content, +// getPaint(), +// (float) getTouchInterceptHorizontalScrollView().getWidth(), +// TextUtils.TruncateAt.END).toString() + "\u202F"; +// super.setText(songTruncated, BufferType.NORMAL); +// +// System.out.println("Set Song Truncated: "+songTruncated); +// +// setTruncateText(song, songTruncated); +// } else { +// super.setText(content, BufferType.NORMAL); +// } +// }else{ +// super.setText(content, BufferType.NORMAL); +// post(new Runnable() { +// @Override +// public void run() { +// song = content; +// System.out.println("Reset content: "+ song); +// if(getWidth() > 0) setText(content); +// } +// }); +// } +// } catch (NullPointerException e){ +// e.printStackTrace(); +// super.setText(content, BufferType.NORMAL); +// } +// super.setText(text, BufferType.NORMAL); +// } + @Override public void setText(CharSequence text, BufferType type) { - String content= text.toString(); - try { - if (!isTextTruncated(text.toString()) && - !content.endsWith("\uFEFF") && - isTextTruncated(getText().toString())) { - song = content; - songTruncated = TextUtils.ellipsize(content, + String content = text.toString(); + song = content; + final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); + if(sV != null && !content.endsWith("\uFEFF") && sV.canScroll()){ + System.out.println("Width: " + Integer.toString(sV.getWidth())); + content = TextUtils.ellipsize(content, getPaint(), - (float) getWidth(), + (float) sV.getWidth(), TextUtils.TruncateAt.END).toString() + "\u202F"; - super.setText(songTruncated, BufferType.NORMAL); - setTruncateText(song); + setTruncateText(song, content, getTouchInterceptFrameLayout(), sV, this); }else{ - super.setText(content, BufferType.NORMAL); - setTruncateText(content); + setTruncateText(content,content, getTouchInterceptFrameLayout(), sV, this); + } - } catch (NullPointerException e){ - e.printStackTrace(); - super.setText(content, BufferType.NORMAL); - setTruncateText(content); + super.setText(content, BufferType.NORMAL); + } + + /** + * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. + * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView + * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. + * Must be called after setViews or it will throw a NullPointerException. + * Call this when setting the song title during view creation. + * + * If this is never called then the text will never be truncated and will remain + * cut off, still allowing the HorizontalScrollingView to scroll. + * @param s The string (song title or album title typically) contained by the text view. + */ + public void setTruncateText(final String s, final String sT, + final TouchInterceptFrameLayout fL, + final TouchInterceptHorizontalScrollView sV, + final TouchInterceptTextView tV){ + try { + + post(new Runnable() { + @Override + public void run() { + song = s; + songTruncated = sT; + + System.out.println("Song Truncated: "+ sT); + + if (isTextTruncated(sT)) { + + Log.d("is Song Truncated","true"); + + if (s.equals(sT)) { + sV.setScrollingEnabled(false); + + } else { + sV.setScrollingEnabled(true); + + sV.setOnEndScrollListener( + new TouchInterceptHorizontalScrollView.OnEndScrollListener() { + @Override + public void onEndScroll() { + reTruncateScrollText(sT,sV,tV); + } + }); + } + initializeListParent(fL, sV); + }else{ + sV.setScrollingEnabled(false); + } + + } + }); + }catch (NullPointerException exception){ + Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e("Method: ","setTruncateText()"); + System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + sV.toString()); + System.out.println(TAG + " TouchInterceptTextView = " + this.toString()); + Log.e(TAG, exception.toString()); } } - public void setTruncateText(final String content){ - post(new Runnable() { - @Override - public void run() { - getTouchInterceptFrameLayout().setTruncateText(content); + /** + * Gets the ListParent (the parent ListView or RecyclerView) that has been + * set via xml or programmatically and sets a Scroll Listener. When scrolling + * clicks are cancelled to prevent any interference with scrolling. + */ + public void initializeListParent(final TouchInterceptFrameLayout fL, final TouchInterceptHorizontalScrollView sV){ + + final View listParent = fL.getListParent(); + + try{ + if(listParent instanceof RecyclerView){ + ((RecyclerView) listParent).addOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + sV.slidingPanelSetTouchEnabled(true); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + CancelClick(fL, sV); + } + } + }); } - }); + + if(listParent instanceof ListView){ + ((ListView) listParent).setOnScrollListener(new AbsListView.OnScrollListener(){ + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + sV.slidingPanelSetTouchEnabled(true); + } + public void onScrollStateChanged(AbsListView view, int newState) { + + if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { + CancelClick(fL, sV); + } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { + CancelClick(fL, sV); + } + } + }); + } + }catch (NullPointerException exception){ + Log.w(TAG, NULL_LIST_PARENT); + System.out.println(TAG + " listParent = " + listParent.toString()); + Log.w(TAG, exception.toString()); + } } /** @@ -116,22 +296,34 @@ public boolean isTextTruncated(String text) { } public void unTruncateText(){ - truncateText = false; - setText(song); + setText(song + "\uFEFF"); } /** * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time */ - public void reTruncateScrollText() { - ObjectAnimator.ofInt(getTouchInterceptHorizontalScrollView(), "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); - getTouchInterceptHorizontalScrollView().slidingPanelSetTouchEnabled(true); + public void reTruncateScrollText(final String truncatedString, + final TouchInterceptHorizontalScrollView sV, + final TouchInterceptTextView tV) { + ObjectAnimator.ofInt(sV, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); + sV.slidingPanelSetTouchEnabled(true); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { - setText(songTruncated); + tV.setText(truncatedString); } }, RETRUNCATE_DELAY); } + + /** + *Cancels any Long Presses and inpending clicks. Used to prevent views from + * stealing touches while the user is scrolling something. + */ + private void CancelClick(TouchInterceptFrameLayout fL, TouchInterceptHorizontalScrollView sV){ + fL.cancelPendingInputEvents(); + fL.cancelLongPress(); + sV.cancelLongPress(); + sV.cancelPendingInputEvents(); + } } diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 858ee2ea6..4e2a9191a 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -50,13 +50,6 @@ android:paddingLeft="72dp" android:paddingRight="72dp" > - - - - - - - - Date: Sun, 23 Jul 2017 23:23:09 -0400 Subject: [PATCH 56/97] Setting text through onMeasure is successful --- .../views/TouchInterceptTextView.java | 127 +++++++++++------- .../main/res/layout/activity_album_detail.xml | 22 +-- app/src/main/res/layout/item_list.xml | 10 +- 3 files changed, 97 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index b66b1dd8c..7c0e400b3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -2,6 +2,7 @@ import android.animation.ObjectAnimator; import android.content.Context; +import android.graphics.Paint; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; @@ -40,6 +41,8 @@ public class TouchInterceptTextView extends AppCompatTextView { private static boolean truncateText; + private int textBoundsWidth; + private final Semaphore semaphore = new Semaphore(0); public TouchInterceptTextView(Context context) { @@ -47,20 +50,20 @@ public TouchInterceptTextView(Context context) { setTag("TITV"); Log.d("Initiate", "1"); - final TouchInterceptTextView tV = this; - post(new Runnable() { - @Override - public void run() { - final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); - song = getText().toString(); - if(sV.canScroll()) { - System.out.println("Width: " + Integer.toString(sV.getWidth())); - setText(getText().toString()); - }else{ - setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); - } - } - }); +// final TouchInterceptTextView tV = this; +// post(new Runnable() { +// @Override +// public void run() { +// final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); +// song = getText().toString(); +// if(sV.canScroll()) { +// System.out.println("Width: " + Integer.toString(sV.getWidth())); +// setText(getText().toString()); +// }else{ +// if(sV != null) setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); +// } +// } +// }); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { @@ -69,20 +72,20 @@ public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { setLongClickable(true); Log.d("Initiate", "2"); - final TouchInterceptTextView tV = this; - post(new Runnable() { - @Override - public void run() { - final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); - song = getText().toString(); - if(sV.canScroll()) { - System.out.println("Width: " + Integer.toString(sV.getWidth())); - setText(getText().toString()); - }else{ - setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); - } - } - }); +// final TouchInterceptTextView tV = this; +// post(new Runnable() { +// @Override +// public void run() { +// final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); +// song = getText().toString(); +// if(sV.canScroll()) { +// System.out.println("Width: " + Integer.toString(sV.getWidth())); +// setText(getText().toString()); +// }else{ +// if(sV != null) setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); +// } +// } +// }); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { @@ -144,22 +147,45 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( @Override public void setText(CharSequence text, BufferType type) { String content = text.toString(); - song = content; - final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); - if(sV != null && !content.endsWith("\uFEFF") && sV.canScroll()){ - System.out.println("Width: " + Integer.toString(sV.getWidth())); - content = TextUtils.ellipsize(content, - getPaint(), - (float) sV.getWidth(), - TextUtils.TruncateAt.END).toString() + "\u202F"; - setTruncateText(song, content, getTouchInterceptFrameLayout(), sV, this); - }else{ - setTruncateText(content,content, getTouchInterceptFrameLayout(), sV, this); - - } + //song = content; +// System.out.println("Width: " + Integer.toString(getWidth())); +// final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); +// if(sV != null && !content.endsWith("\uFEFF") && sV.canScroll()){ +// content = TextUtils.ellipsize(content, +// getPaint(), +// (float) sV.getWidth(), +// TextUtils.TruncateAt.END).toString() + "\u202F"; +// setTruncateText(song, content, getTouchInterceptFrameLayout(), sV, this); +// }else{ +// if(sV != null) setTruncateText(content,content, getTouchInterceptFrameLayout(), sV, this); +// +// } super.setText(content, BufferType.NORMAL); } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + textBoundsWidth = MeasureSpec.getSize(widthMeasureSpec); + + String currentText = getText().toString(); + Paint paint = getPaint(); + + if(!currentText.endsWith("\uFEFF") && (getWidth() == 0 | textBoundsWidth < paint.measureText(currentText)) ) { + String truncatedText = TextUtils.ellipsize(currentText, + getPaint(), + (float) textBoundsWidth, + TextUtils.TruncateAt.END).toString() + "\u202F"; + setText(truncatedText); + setTruncateText(currentText,truncatedText); + }else{ + setText(currentText); + setTruncateText(currentText,currentText); + } + + } + /** * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView @@ -171,18 +197,17 @@ public void setText(CharSequence text, BufferType type) { * cut off, still allowing the HorizontalScrollingView to scroll. * @param s The string (song title or album title typically) contained by the text view. */ - public void setTruncateText(final String s, final String sT, - final TouchInterceptFrameLayout fL, - final TouchInterceptHorizontalScrollView sV, - final TouchInterceptTextView tV){ + public void setTruncateText(final String s, final String sT){ try { post(new Runnable() { @Override public void run() { - song = s; + if(!s.endsWith("\u202F")) song = s; songTruncated = sT; + final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); + System.out.println("Song Truncated: "+ sT); if (isTextTruncated(sT)) { @@ -199,11 +224,11 @@ public void run() { new TouchInterceptHorizontalScrollView.OnEndScrollListener() { @Override public void onEndScroll() { - reTruncateScrollText(sT,sV,tV); + reTruncateScrollText(sT, sV, TouchInterceptTextView.this); } }); } - initializeListParent(fL, sV); + initializeListParent(getTouchInterceptFrameLayout(), sV); }else{ sV.setScrollingEnabled(false); } @@ -213,7 +238,7 @@ public void onEndScroll() { }catch (NullPointerException exception){ Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); Log.e("Method: ","setTruncateText()"); - System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + sV.toString()); + System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + getTouchInterceptHorizontalScrollView().toString()); System.out.println(TAG + " TouchInterceptTextView = " + this.toString()); Log.e(TAG, exception.toString()); } @@ -296,7 +321,9 @@ public boolean isTextTruncated(String text) { } public void unTruncateText(){ - setText(song + "\uFEFF"); + String untrunucatedText = song + "\uFEFF"; + Log.d("Untruncated song", untrunucatedText); + setText(untrunucatedText); } /** diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 4e2a9191a..2efc717b0 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -50,16 +50,20 @@ android:paddingLeft="72dp" android:paddingRight="72dp" > - + android:layout_height="wrap_content" > + + + + diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 510bbf1a7..59512da0f 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -80,16 +80,20 @@ android:paddingRight="0dp" android:paddingStart="16dp" > + + + + Date: Mon, 24 Jul 2017 02:05:59 -0400 Subject: [PATCH 57/97] Optimized and fixed flashing, scroll not sticking. Just need to prevent background from being changed --- .../TouchInterceptHorizontalScrollView.java | 16 ++- .../views/TouchInterceptTextView.java | 114 ++---------------- 2 files changed, 21 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 9d920e275..72b75b57c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -72,6 +72,8 @@ public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + setTag("TIHS"); + setHorizontalScrollBarEnabled(false); } // "true" if we can scroll (not locked) @@ -109,8 +111,8 @@ public boolean canScroll() { public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: - cancel = true; touched = true; + cancel = true; // If we can scroll pass the event to the superclass if (mScrollable) return super.onTouchEvent(ev); // Only continue to handle the touch event if scrolling enabled @@ -133,12 +135,13 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { slidingPanelSetTouchEnabled(true); } // Don't do anything with intercepted touch events if - // we are not scrollable - if (!mScrollable){ + // not scrollable + if(!mScrollable){ onTouchEvent(ev); return false; } - else return super.onInterceptTouchEvent(ev); + else + return super.onInterceptTouchEvent(ev); } /** @@ -159,6 +162,7 @@ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { @Override protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); + cancel = true; if(touched) slidingPanelSetTouchEnabled(false); CancelClick(); } @@ -183,11 +187,11 @@ public void CancelClick(){ this.cancelPendingInputEvents(); } - public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { + public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); } public TouchInterceptTextView getTouchInterceptTextView(){ return (TouchInterceptTextView) ((ViewGroup)this).getChildAt(0); } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index 7c0e400b3..de2845846 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -48,51 +48,21 @@ public class TouchInterceptTextView extends AppCompatTextView { public TouchInterceptTextView(Context context) { super(context); setTag("TITV"); - Log.d("Initiate", "1"); - -// final TouchInterceptTextView tV = this; -// post(new Runnable() { -// @Override -// public void run() { -// final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); -// song = getText().toString(); -// if(sV.canScroll()) { -// System.out.println("Width: " + Integer.toString(sV.getWidth())); -// setText(getText().toString()); -// }else{ -// if(sV != null) setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); -// } -// } -// }); + setLongClickable(true); + } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setTag("TITV"); setLongClickable(true); - Log.d("Initiate", "2"); - -// final TouchInterceptTextView tV = this; -// post(new Runnable() { -// @Override -// public void run() { -// final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); -// song = getText().toString(); -// if(sV.canScroll()) { -// System.out.println("Width: " + Integer.toString(sV.getWidth())); -// setText(getText().toString()); -// }else{ -// if(sV != null) setTruncateText(song,song,getTouchInterceptFrameLayout(), sV, tV); -// } -// } -// }); + } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setTag("TITV"); setLongClickable(true); - Log.d("Initiate", "3"); } public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { @@ -103,66 +73,6 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( return (TouchInterceptHorizontalScrollView) getParent(); } -// @Override -// public void setText(CharSequence text, BufferType type) { -// final String content= text.toString(); -// System.out.println("Width: "+Integer.toString(getWidth())); -// System.out.println("Current text: "+getText().toString()); -// System.out.println("Content: "+content); -// try { -// if(getWidth() > 0) { -// if (!getText().toString().endsWith("\u202F") && -// !content.endsWith("\uFEFF")) { -// song = content; -// songTruncated = TextUtils.ellipsize(content, -// getPaint(), -// (float) getTouchInterceptHorizontalScrollView().getWidth(), -// TextUtils.TruncateAt.END).toString() + "\u202F"; -// super.setText(songTruncated, BufferType.NORMAL); -// -// System.out.println("Set Song Truncated: "+songTruncated); -// -// setTruncateText(song, songTruncated); -// } else { -// super.setText(content, BufferType.NORMAL); -// } -// }else{ -// super.setText(content, BufferType.NORMAL); -// post(new Runnable() { -// @Override -// public void run() { -// song = content; -// System.out.println("Reset content: "+ song); -// if(getWidth() > 0) setText(content); -// } -// }); -// } -// } catch (NullPointerException e){ -// e.printStackTrace(); -// super.setText(content, BufferType.NORMAL); -// } -// super.setText(text, BufferType.NORMAL); -// } - - @Override - public void setText(CharSequence text, BufferType type) { - String content = text.toString(); - //song = content; -// System.out.println("Width: " + Integer.toString(getWidth())); -// final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); -// if(sV != null && !content.endsWith("\uFEFF") && sV.canScroll()){ -// content = TextUtils.ellipsize(content, -// getPaint(), -// (float) sV.getWidth(), -// TextUtils.TruncateAt.END).toString() + "\u202F"; -// setTruncateText(song, content, getTouchInterceptFrameLayout(), sV, this); -// }else{ -// if(sV != null) setTruncateText(content,content, getTouchInterceptFrameLayout(), sV, this); -// -// } - super.setText(content, BufferType.NORMAL); - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @@ -172,16 +82,19 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) String currentText = getText().toString(); Paint paint = getPaint(); + if(!currentText.endsWith("\u202F") && + !currentText.endsWith("\uFEFF")) song = currentText; + if(!currentText.endsWith("\uFEFF") && (getWidth() == 0 | textBoundsWidth < paint.measureText(currentText)) ) { String truncatedText = TextUtils.ellipsize(currentText, getPaint(), (float) textBoundsWidth, TextUtils.TruncateAt.END).toString() + "\u202F"; setText(truncatedText); - setTruncateText(currentText,truncatedText); + setTruncateText(song,truncatedText); }else{ setText(currentText); - setTruncateText(currentText,currentText); + setTruncateText(song,currentText); } } @@ -198,8 +111,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) * @param s The string (song title or album title typically) contained by the text view. */ public void setTruncateText(final String s, final String sT){ - try { + try { post(new Runnable() { @Override public void run() { @@ -208,13 +121,9 @@ public void run() { final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); - System.out.println("Song Truncated: "+ sT); - if (isTextTruncated(sT)) { - Log.d("is Song Truncated","true"); - - if (s.equals(sT)) { + if (s == sT && !sT.endsWith("\uFEFF")) { sV.setScrollingEnabled(false); } else { @@ -230,7 +139,7 @@ public void onEndScroll() { } initializeListParent(getTouchInterceptFrameLayout(), sV); }else{ - sV.setScrollingEnabled(false); + if(!sT.endsWith("\uFEFF")) sV.setScrollingEnabled(false); } } @@ -322,7 +231,6 @@ public boolean isTextTruncated(String text) { public void unTruncateText(){ String untrunucatedText = song + "\uFEFF"; - Log.d("Untruncated song", untrunucatedText); setText(untrunucatedText); } From af7b37b280ffaa7eca8b856c0e6229dd5dc4759c Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 24 Jul 2017 03:48:12 -0400 Subject: [PATCH 58/97] Fixed not retruncating and not untruncating --- .../views/TouchInterceptFrameLayout.java | 12 +--- .../TouchInterceptHorizontalScrollView.java | 56 +++++++++++++++---- .../views/TouchInterceptTextView.java | 4 +- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 3703e0a4f..97388b1e5 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -323,16 +323,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { x > scrollViewRect.left && x < scrollViewRect.right && y > scrollViewRect.top && y < scrollViewRect.bottom; -// if (songTruncated != null){ -// emptyTruncateText = songTruncated.isEmpty(); -// isTextTruncated = songTruncated.endsWith("…\u202F"); -// if(emptyTruncateText) Log.e(TAG, EMPTY_TRUNCATE_STRING); -// }else{ -// emptyTruncateText = true; -// isTextTruncated = false; -// Log.e(TAG, EMPTY_TRUNCATE_STRING); -// } - switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: scrollView.slidingPanelSetTouchEnabled(true); @@ -353,8 +343,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { - textView.unTruncateText(); isTap = false; + CancelClick(); } } break; diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 72b75b57c..d84813abd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -25,7 +25,13 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { public static final int ON_END_SCROLL_DELAY = 1000; private long lastScrollUpdate = -1; + private int lastStopX; + + private boolean mIsFling; + private boolean cancel; + private boolean cancelCheck; + private boolean unTruncate; private boolean touched; private OnEndScrollListener onEndScrollListener; @@ -45,6 +51,7 @@ private class ScrollStateHandler implements Runnable { @Override public void run() { if(!cancel) { + cancelCheck = true; long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > ON_END_SCROLL_DELAY) { lastScrollUpdate = -1; @@ -108,40 +115,47 @@ public boolean canScroll() { } @Override - public boolean onTouchEvent(MotionEvent ev) { - switch (ev.getAction()) { + public boolean onTouchEvent(MotionEvent e) { + switch (e.getAction()) { case MotionEvent.ACTION_DOWN: touched = true; cancel = true; // If we can scroll pass the event to the superclass - if (mScrollable) return super.onTouchEvent(ev); + if (mScrollable) return super.onTouchEvent(e); // Only continue to handle the touch event if scrolling enabled return mScrollable; // mScrollable is always false at this point + case MotionEvent.ACTION_MOVE: + if(unTruncate = true) { + getTouchInterceptTextView().unTruncateText(); + unTruncate = false; + } case MotionEvent.ACTION_UP: slidingPanelSetTouchEnabled(true); touched = false; - cancel = false; // The user is done interacting with the scroll view + cancel = false; postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); lastScrollUpdate = System.currentTimeMillis(); + unTruncate = true; default: - return super.onTouchEvent(ev); + return super.onTouchEvent(e); } } @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if(ev.getAction() == MotionEvent.ACTION_DOWN){ + public boolean onInterceptTouchEvent(MotionEvent e) { + + if(e.getAction() == MotionEvent.ACTION_DOWN){ slidingPanelSetTouchEnabled(true); } // Don't do anything with intercepted touch events if // not scrollable if(!mScrollable){ - onTouchEvent(ev); + onTouchEvent(e); return false; } else - return super.onInterceptTouchEvent(ev); + return super.onInterceptTouchEvent(e); } /** @@ -159,12 +173,34 @@ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { this.onEndScrollListener = mOnEndScrollListener; } + @Override + public void fling(int velocityY) { + super.fling(velocityY); + mIsFling = true; + } + @Override protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - cancel = true; + if(touched) slidingPanelSetTouchEnabled(false); CancelClick(); + + if(cancelCheck) cancel = true; + + if (mIsFling) { + if (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0) { + slidingPanelSetTouchEnabled(true); + touched = false; + // The user is done interacting with the scroll view + cancel = false; + postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); + lastScrollUpdate = System.currentTimeMillis(); + mIsFling = false; + cancelCheck = false; + unTruncate = true; + } + } } /** diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index de2845846..7d5dd9695 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -49,6 +49,7 @@ public TouchInterceptTextView(Context context) { super(context); setTag("TITV"); setLongClickable(true); + setSingleLine(); } @@ -56,13 +57,12 @@ public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setTag("TITV"); setLongClickable(true); + setSingleLine(); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - setTag("TITV"); - setLongClickable(true); } public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { From c2964fbf36ed659421f3f3d8d8fedad2001fda42 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 24 Jul 2017 14:45:46 -0400 Subject: [PATCH 59/97] Fixed over scroll and background setting --- .../views/TouchInterceptFrameLayout.java | 17 ++++++++--------- .../TouchInterceptHorizontalScrollView.java | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 97388b1e5..85c861a32 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -309,20 +309,18 @@ public boolean isTextTruncated(String text) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { - if(scrollView.isScrollable()) { - - boolean emptyTruncateText; - boolean isTextTruncated; - int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); try { + scrollView.getGlobalVisibleRect(scrollViewRect); boolean touchedScrollView = x > scrollViewRect.left && x < scrollViewRect.right && y > scrollViewRect.top && y < scrollViewRect.bottom; + if(scrollView.isScrollable()) { + switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: scrollView.slidingPanelSetTouchEnabled(true); @@ -359,6 +357,11 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } return false; + }else{ + if(touchedScrollView) onTouchEvent(e); + return false; + } + } catch (NullPointerException exception) { Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); Log.e("Method: ","onInterceptTouchEvent()"); @@ -368,10 +371,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { onTouchEvent(e); return false; } - }else{ - onTouchEvent(e); - return false; - } } /** diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index d84813abd..ca059af49 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.content.Context; +import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewGroup; @@ -145,9 +146,26 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { + if(e.getAction() == MotionEvent.ACTION_DOWN){ slidingPanelSetTouchEnabled(true); } + + int x = Math.round(e.getRawX()); + int y = Math.round(e.getRawY()); + + Rect scrollViewRect = new Rect(); + + getGlobalVisibleRect(scrollViewRect); + + boolean touchedScrollView = + x > scrollViewRect.left && x < scrollViewRect.right && + y > scrollViewRect.top && y < scrollViewRect.bottom; + + if(!touchedScrollView){ + return false; + } + // Don't do anything with intercepted touch events if // not scrollable if(!mScrollable){ From 3398136193a2ad38fb7738ec8fa156afd9d2fbef Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 24 Jul 2017 15:22:40 -0400 Subject: [PATCH 60/97] Cleaned up code --- .../views/TouchInterceptFrameLayout.java | 227 +----------------- .../TouchInterceptHorizontalScrollView.java | 13 +- .../views/TouchInterceptTextView.java | 39 ++- .../main/res/layout/activity_album_detail.xml | 5 +- 4 files changed, 34 insertions(+), 250 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 85c861a32..ff6341b07 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -1,23 +1,15 @@ package com.kabouzeid.gramophone.views; -import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; -import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.text.Editable; -import android.text.TextUtils; -import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; -import android.widget.AbsListView; import android.widget.FrameLayout; -import android.widget.ListView; import com.kabouzeid.gramophone.R; @@ -52,53 +44,15 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final String EMPTY_TRUNCATE_STRING = "songTruncated is empty or null. Did you remember " + "to set the song string when setting the song name in your text view?"; - private int scrollViewID; - private int textViewID; private int listParentID; private TouchInterceptHorizontalScrollView scrollView; - private TouchInterceptTextView textView; private View listParent; private Rect scrollViewRect = new Rect(); private float startX; private boolean isTap; - private boolean currentlySettingTextHere = false; - - private String song; - private String songTruncated; - - /** - * A TextWatcher used to monitor when the contents of this view has changed - * since if this view is in a list it will be recycled. This ensures instances are current - * and when the text changes it will be truncated. - */ - protected TextWatcher truncateTextWatcher = new TextWatcher() { - - @Override - public void afterTextChanged(Editable s) { - if(!currentlySettingTextHere){ - - TouchInterceptHorizontalScrollView sV = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); - if (sV != null) scrollView = sV; - TouchInterceptTextView tV = (TouchInterceptTextView) findViewWithTag("TITV"); - if(tV != null) textView = tV; - View lP = findViewById(listParentID); - if(lP != null) listParent = lP; - - //setTruncateText(textView.getText().toString()); - } - currentlySettingTextHere = false; - - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - }; public TouchInterceptFrameLayout(@NonNull Context context) { this(context, null); @@ -121,38 +75,13 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe this.post(new Runnable() { @Override public void run() { - scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); - textView = (TouchInterceptTextView) findViewWithTag("TITV"); View lP = findViewById(listParentID); - if(lP != null) listParent = lP; - - textView.post(new Runnable() { - @Override - public void run() { - textView.addTextChangedListener(truncateTextWatcher); - } - }); + if (lP != null) listParent = lP; } }); } - /** - * Sets the TouchInterceptHorizontalScrollView contained by this FrameLayout - * @param sv The HorizontalScrollView containing text that needs to be scrolled - */ - public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScrollView sv) { - this.scrollView = sv; - } - - /** - * Sets the TextView that is contained within that TouchInterceptHorizontalScrollView. - * @param tv The TextView that needs to be scrolled (typically song or album title) - */ - public void setScrollableTextView(TouchInterceptTextView tv) { - this.textView = tv; - } - /** * Sets the List Parent programmatically * @param lP Must be either a type of RecyclerView or a type of ListView @@ -162,135 +91,13 @@ public void setListParent(View lP){ } public View getListParent(){ - return listParent; + if(listParent == null) + return findViewById(listParentID); + else return listParent; } - /** - * Gets the ListParent (the parent ListView or RecyclerView) that has been - * set via xml or programmatically and sets a Scroll Listener. When scrolling - * clicks are cancelled to prevent any interference with scrolling. - */ - public void initializeListParent(){ - - try{ - if(listParent instanceof RecyclerView){ - ((RecyclerView) listParent).addOnScrollListener(new RecyclerView.OnScrollListener() { - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - scrollView.slidingPanelSetTouchEnabled(true); - } - - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - CancelClick(); - } - } - }); - } - - if(listParent instanceof ListView){ - ((ListView) listParent).setOnScrollListener(new AbsListView.OnScrollListener(){ - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - scrollView.slidingPanelSetTouchEnabled(true); - } - public void onScrollStateChanged(AbsListView view, int newState) { - - if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) { - CancelClick(); - } else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { - CancelClick(); - } - } - }); - } - }catch (NullPointerException exception){ - Log.w(TAG, NULL_LIST_PARENT); - System.out.println(TAG + " listParent = " + listParent.toString()); - Log.w(TAG, exception.toString()); - } - } - - /** - * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. - * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView - * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. - * Must be called after setViews or it will throw a NullPointerException. - * Call this when setting the song title during view creation. - * - * If this is never called then the text will never be truncated and will remain - * cut off, still allowing the HorizontalScrollingView to scroll. - * @param s The string (song title or album title typically) contained by the text view. - */ - public void setTruncateText(String s, String sT){ - song = s; - songTruncated = sT; - try { - scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); - textView = (TouchInterceptTextView) findViewWithTag("TITV"); - //runs after scrollview has been drawn - textView.post(new Runnable() { - @Override - public void run() { - if (scrollView.canScroll()) { - songTruncated = TextUtils.ellipsize(song, - textView.getPaint(), - (float) scrollView.getWidth(), - TextUtils.TruncateAt.END).toString() + "\u202F"; - - if (songTruncated != null && !songTruncated.isEmpty()) { - setText(songTruncated); - - if (songTruncated.equals(song)) { - scrollView.setScrollingEnabled(false); - - } else { - scrollView.setScrollingEnabled(true); - - scrollView.setOnEndScrollListener( - new TouchInterceptHorizontalScrollView.OnEndScrollListener() { - @Override - public void onEndScroll() { - reTruncateScrollText(); - } - }); - } - initializeListParent(); - }else{ - scrollView.setScrollingEnabled(false); - } - }else{ - scrollView.setScrollingEnabled(false); - } - - } - }); - }catch (NullPointerException exception){ - Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e("Method: ","setTruncateText()"); - System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + scrollView.toString()); - System.out.println(TAG + " TouchInterceptTextView = " + textView); - Log.e(TAG, exception.toString()); - } - } - - /** - * Used to set the text and indicate that the TextView text is being - * set in this CustomView class and not somewhere else. - * @param text The text to set the TextView to - */ - private void setText(String text){ - currentlySettingTextHere = true; - textView.setText(text); - } - - public boolean isTextTruncated(String text) { - if (text.endsWith("…\u202F")) return true; - else return false; + public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { + return (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); } /** @@ -311,6 +118,9 @@ public boolean onInterceptTouchEvent(MotionEvent e) { int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); + + scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); + try { scrollView.getGlobalVisibleRect(scrollViewRect); @@ -365,8 +175,8 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } catch (NullPointerException exception) { Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); Log.e("Method: ","onInterceptTouchEvent()"); - System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + scrollView.toString()); - System.out.println(TAG + " TouchInterceptTextView = " + textView); + System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + findViewWithTag("TIHS").toString()); + System.out.println(TAG + " TouchInterceptTextView = " + findViewWithTag("TITV").toString()); Log.e(TAG, exception.toString()); onTouchEvent(e); return false; @@ -383,19 +193,4 @@ private void CancelClick(){ scrollView.cancelLongPress(); scrollView.cancelPendingInputEvents(); } - - /** - * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time - */ - public void reTruncateScrollText(){ - ObjectAnimator.ofInt(scrollView, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); - scrollView.slidingPanelSetTouchEnabled(true); - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override - public void run() { - setText(songTruncated); - } - }, RETRUNCATE_DELAY); - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index ca059af49..7ab07fe64 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -26,7 +26,6 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { public static final int ON_END_SCROLL_DELAY = 1000; private long lastScrollUpdate = -1; - private int lastStopX; private boolean mIsFling; @@ -80,8 +79,6 @@ public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - setTag("TIHS"); - setHorizontalScrollBarEnabled(false); } // "true" if we can scroll (not locked) @@ -118,6 +115,7 @@ public boolean canScroll() { @Override public boolean onTouchEvent(MotionEvent e) { switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: touched = true; cancel = true; @@ -125,11 +123,13 @@ public boolean onTouchEvent(MotionEvent e) { if (mScrollable) return super.onTouchEvent(e); // Only continue to handle the touch event if scrolling enabled return mScrollable; // mScrollable is always false at this point + case MotionEvent.ACTION_MOVE: if(unTruncate = true) { getTouchInterceptTextView().unTruncateText(); unTruncate = false; } + case MotionEvent.ACTION_UP: slidingPanelSetTouchEnabled(true); touched = false; @@ -147,9 +147,8 @@ public boolean onTouchEvent(MotionEvent e) { public boolean onInterceptTouchEvent(MotionEvent e) { - if(e.getAction() == MotionEvent.ACTION_DOWN){ - slidingPanelSetTouchEnabled(true); - } + if(e.getAction() == MotionEvent.ACTION_DOWN) slidingPanelSetTouchEnabled(true); + int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -201,7 +200,7 @@ public void fling(int velocityY) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - if(touched) slidingPanelSetTouchEnabled(false); + if(touched | mIsFling) slidingPanelSetTouchEnabled(false); CancelClick(); if(cancelCheck) cancel = true; diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index 7d5dd9695..5fbeca93b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -2,7 +2,6 @@ import android.animation.ObjectAnimator; import android.content.Context; -import android.graphics.Paint; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; @@ -39,8 +38,6 @@ public class TouchInterceptTextView extends AppCompatTextView { private String song; private String songTruncated; - private static boolean truncateText; - private int textBoundsWidth; private final Semaphore semaphore = new Semaphore(0); @@ -49,6 +46,7 @@ public TouchInterceptTextView(Context context) { super(context); setTag("TITV"); setLongClickable(true); + setClickable(true); setSingleLine(); } @@ -57,6 +55,7 @@ public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setTag("TITV"); setLongClickable(true); + setClickable(true); setSingleLine(); } @@ -80,12 +79,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) textBoundsWidth = MeasureSpec.getSize(widthMeasureSpec); String currentText = getText().toString(); - Paint paint = getPaint(); + Boolean isUntruncatedSong = currentText.endsWith("\uFEFF"); if(!currentText.endsWith("\u202F") && - !currentText.endsWith("\uFEFF")) song = currentText; + !isUntruncatedSong) song = currentText; - if(!currentText.endsWith("\uFEFF") && (getWidth() == 0 | textBoundsWidth < paint.measureText(currentText)) ) { + if(!isUntruncatedSong && + (getWidth() == 0 | textBoundsWidth < getPaint().measureText(currentText)) ) { String truncatedText = TextUtils.ellipsize(currentText, getPaint(), (float) textBoundsWidth, @@ -205,25 +205,6 @@ public void onScrollStateChanged(AbsListView view, int newState) { } } - /** - * Sets the TouchIntercept frame layout that is the RootView of the layout. - * Must be a TouchInterceptFrameLayout - * - * @param fL The FrameLayout to be set. - */ - public void setTouchInterceptFrameLayout(TouchInterceptFrameLayout fL) { - this.touchInterceptFrameLayout = fL; - } - - /** - * Sets the TouchInterceptHorizontalScrollView contained by this FrameLayout - * - * @param sv The HorizontalScrollView containing text that needs to be scrolled - */ - public void setTouchInterceptHorizontalScrollView(TouchInterceptHorizontalScrollView sv) { - this.scrollView = sv; - } - public boolean isTextTruncated(String text) { if (text.endsWith("…\u202F")) return true; else return false; @@ -234,6 +215,14 @@ public void unTruncateText(){ setText(untrunucatedText); } + public String getSongTruncated(){ + return this.songTruncated; + } + + public String getUntruncatedSong(){ + return this.song; + } + /** * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time */ diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 2efc717b0..239ca9bf4 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -37,7 +37,8 @@ + android:orientation="vertical" + > + android:paddingRight="72dp"> Date: Mon, 24 Jul 2017 15:24:41 -0400 Subject: [PATCH 61/97] fixed not retrunucating --- .../gramophone/views/TouchInterceptHorizontalScrollView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 7ab07fe64..7a1bc101f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -51,11 +51,11 @@ private class ScrollStateHandler implements Runnable { @Override public void run() { if(!cancel) { - cancelCheck = true; long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > ON_END_SCROLL_DELAY) { lastScrollUpdate = -1; if (onEndScrollListener != null) { + cancelCheck = true; onEndScrollListener.onEndScroll(); } } else { From 5cf52b5c2b30859b4688f0524c28031ed5842f7c Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 24 Jul 2017 15:34:40 -0400 Subject: [PATCH 62/97] Resolved conflict --- .../ui/activities/AlbumDetailActivity.java | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 65eeda5ac..6eb100736 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -17,7 +17,6 @@ import android.view.MenuItem; import android.view.View; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -55,15 +54,9 @@ import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.util.PhonographColorUtil; import com.kabouzeid.gramophone.util.Util; -<<<<<<< HEAD -import com.kabouzeid.gramophone.util.ViewUtil; -import com.kabouzeid.gramophone.views.TouchInterceptFrameLayout; -======= - -import java.util.Locale; import java.util.ArrayList; ->>>>>>> kabouzeid/master +import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; @@ -84,8 +77,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements private Album album; - @BindView(R.id.container) - TouchInterceptFrameLayout container; @BindView(R.id.list) ObservableRecyclerView recyclerView; @BindView(R.id.image) @@ -93,7 +84,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.title) - RelativeLayout albumTitleView; + TextView albumTitleView; @BindView(R.id.album_title) TextView albumTitleTextView; @BindView(R.id.list_background) @@ -431,16 +422,13 @@ public void setStatusbarColor(int color) { private void setAlbum(Album album) { this.album = album; loadAlbumCover(); -<<<<<<< HEAD - albumTitleTextView.setText(album.getTitle()); -======= if (Util.isAllowedToDownloadMetadata(this)) { loadWiki(); } albumTitleView.setText(album.getTitle()); ->>>>>>> kabouzeid/master + adapter.swapDataSet(album.songs); } From b7ef464c4ab9afc3df0ac84e5a3c209b20ab2df9 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 24 Jul 2017 15:38:55 -0400 Subject: [PATCH 63/97] Resolved further conflicts --- .../gramophone/ui/activities/AlbumDetailActivity.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 6eb100736..d4f68d2f6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -17,6 +17,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -84,7 +85,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.title) - TextView albumTitleView; + RelativeLayout albumTitleView; @BindView(R.id.album_title) TextView albumTitleTextView; @BindView(R.id.list_background) @@ -427,7 +428,7 @@ private void setAlbum(Album album) { loadWiki(); } - albumTitleView.setText(album.getTitle()); + albumTitleTextView.setText(album.getTitle()); adapter.swapDataSet(album.songs); } From cafa6226fb0371120f37e355ccb5973e50ab3d30 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 24 Jul 2017 16:28:05 -0400 Subject: [PATCH 64/97] Add to single row list item --- .../views/TouchInterceptTextView.java | 1 + .../main/res/layout/activity_album_detail.xml | 2 -- app/src/main/res/layout/item_list.xml | 4 +-- .../main/res/layout/item_list_single_row.xml | 28 ++++++++++++++----- app/src/main/res/values/attrs.xml | 7 ----- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index 5fbeca93b..1e5043646 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -137,6 +137,7 @@ public void onEndScroll() { } }); } + //Seems like it doesn't do much initializeListParent(getTouchInterceptFrameLayout(), sV); }else{ if(!sT.endsWith("\uFEFF")) sV.setScrollingEnabled(false); diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 239ca9bf4..83452553c 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -6,8 +6,6 @@ android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" - app:setTouchInterceptHorizontalScrollView="@+id/title_scrollview" - app:setScrollableTextView="@+id/album_title" app:setListParent="@+id/list" > + tools:ignore="UnusedAttribute" > - - + > + + + + + + + + + - \ No newline at end of file + \ 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 02f02b890..f29e69596 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -14,13 +14,6 @@ - - - - - - - - - \ No newline at end of file From 6b72b350b3fb7383c3902e3e713e9f3e3be01ac3 Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 25 Jul 2017 00:02:20 -0400 Subject: [PATCH 73/97] Added documentation --- .../views/TouchInterceptFrameLayout.java | 13 ++- .../TouchInterceptHorizontalScrollView.java | 21 +++- .../views/TouchInterceptTextView.java | 100 +++++++++++++----- 3 files changed, 97 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 7b1a19a7f..de26d4cd7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -24,8 +24,11 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final int MAX_CLICK_DISTANCE = 5; + //Tag used so other views can find this one private static final String touchInterceptFrameLayoutViewTag = "TIFL"; + private static final String touchInterceptHorizontalScrollViewTag = "TIHS"; + private static final String TAG = "E/TouchInterceptFL"; private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you " + "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + @@ -40,7 +43,7 @@ public class TouchInterceptFrameLayout extends FrameLayout { public TouchInterceptFrameLayout(@NonNull Context context) { this(context, null); - setTag("TIFL"); + setTag(touchInterceptFrameLayoutViewTag); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { @@ -50,12 +53,14 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - setTag(touchInterceptFrameLayoutViewTag); } + /** + * @return Returns the TouchInterceptHorizontalScrollview in this layout + */ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { - return (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); + return (TouchInterceptHorizontalScrollView) findViewWithTag(touchInterceptHorizontalScrollViewTag); } /** @@ -77,7 +82,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); - scrollView = (TouchInterceptHorizontalScrollView) findViewWithTag("TIHS"); + scrollView = getTouchInterceptHorizontalScrollView(); try { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 5d2ea97d0..690601134 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -11,13 +11,13 @@ import com.sothree.slidinguppanel.SlidingUpPanelLayout; /** - * Created by lincoln on 7/3/17. - */ - -/** + * @author Created by lincoln on 7/3/17. + * * A custom HorizontalScrollView that is only useful as the child of a TouchInterceptFrameLayout. * This allows for the TouchInterceptFrameLayout to disable and enable scrolling in addition to * being able to know when a user is and is not interacting with the scrolling view. + * + * Must have a TouchInterceptTextView as it's child. It can only have one child. */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { @@ -25,6 +25,7 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { public static final int ON_END_SCROLL_DELAY = 1000; private static final int MAX_CLICK_DISTANCE = 5; + //Tag used so other views can find this one private static final String touchInterceptHorizontalScrollViewTag = "TIHS"; private float startX; @@ -34,9 +35,16 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private boolean mIsFling; + //Whether user is interacting with this again and to cancel text retruncate private boolean cancel; + + private boolean cancelCheck; + + //Whether to untruncate the text in the TouchInterceptTextView private boolean unTruncate; + + //Whether this was touched private boolean touched; private OnEndScrollListener onEndScrollListener; @@ -130,7 +138,7 @@ public boolean onTouchEvent(MotionEvent e) { float distance = Math.abs(e.getX() - startX); - // Scrolling the view: cancel event to prevent long press + // Currently crolling so untruncate text if(unTruncate && distance > MAX_CLICK_DISTANCE) { getTouchInterceptTextView().unTruncateText(); unTruncate = false; @@ -250,6 +258,9 @@ public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); } + /** + * @return Returns the child TouchInterceptTextView + */ public TouchInterceptTextView getTouchInterceptTextView(){ return (TouchInterceptTextView) this.getChildAt(0); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index cdd31f582..ec71eb2ec 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -10,12 +10,18 @@ import android.util.Log; /** - * Created by lincoln on 7/16/17. + * @author Created by lincoln on 7/16/17. + * + * TextView that automatically does exactly what android:ellipsize="end" does, except this works in a TouchInterceptHorizontalScrollViews. + * Truncates the string so it doesn't get cuttoff in the TouchInterceptHorizontalScrollView + * and puts an ellipsis at the end of it. + * Must be used within a TouchInterceptHorizontalScrollview or it won't work */ public class TouchInterceptTextView extends AppCompatTextView { private static final int RETRUNCATE_DELAY = 600; + //Tag used so other views can find this one private static final String touchInterceptTextViewTag = "TITV"; private static final String TAG = "E/TouchInterceptFL"; @@ -23,39 +29,54 @@ public class TouchInterceptTextView extends AppCompatTextView { "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + "via XML? Did you set it to something null?"; - private String song; - private String songTruncated; + private String title; + private String titleTruncated; public TouchInterceptTextView(Context context) { super(context); setTag(touchInterceptTextViewTag); + //Have to set this enorder to enable long clicking when touching the text setLongClickable(true); + //Blocks clicks from passing through this view setClickable(true); + //Can't use maxlines, have to use this. Typical Android BS setSingleLine(); - } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setTag(touchInterceptTextViewTag); + //Have to set this enorder to enable long clicking when touching the text setLongClickable(true); + //Blocks clicks from passing through this view setClickable(true); + //Can't use maxlines, have to use this. Typical Android BS setSingleLine(); - } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } + /** + * @return Returns the TouchInterceptFrameLayout in this layout + */ public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); } + /** + * @return Returns the parent TouchInterceptHorizontalScrollview + */ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { return (TouchInterceptHorizontalScrollView) getParent(); } + /** + * The text undergoes truncation here. onMeasure is immediately called after setText + * and has a reference to the parent bounds. The parents bounds are used for setting the + * length of the truncate text ensuring that the text does not get cut off + */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -65,42 +86,50 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Boolean isUntruncatedSong = currentText.endsWith("\uFEFF"); if(!currentText.endsWith("\u202F") && - !isUntruncatedSong) song = currentText; + !isUntruncatedSong) title = currentText; if(!isUntruncatedSong && (getWidth() == 0 | textBoundsWidth < getPaint().measureText(currentText)) ) { + + /** + * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. + * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView + * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. + */ String truncatedText = TextUtils.ellipsize(currentText, getPaint(), (float) textBoundsWidth, - TextUtils.TruncateAt.END).toString() + "\u202F"; + TextUtils.TruncateAt.END).toString() + + //The \u202F charachter is an invisible charachter used as a marker for whether + //a string has undergone truncation or not + + "\u202F"; + setText(truncatedText); - setTruncateText(song,truncatedText); + initiateTruncateText(title,truncatedText); }else{ setText(currentText); - setTruncateText(song,currentText); + initiateTruncateText(title,currentText); } } /** - * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. - * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView - * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. - * Must be called after setViews or it will throw a NullPointerException. - * Call this when setting the song title during view creation. - * - * If this is never called then the text will never be truncated and will remain - * cut off, still allowing the HorizontalScrollingView to scroll. - * @param s The string (song title or album title typically) contained by the text view. + * Takes the string that's undergone truncation and based on whether it's been truncated or not + * set whether it should be scrollable or not and what to do when the user finishes scrolling + * @param s The string before truncation + * @param sT The string after truncation */ - public void setTruncateText(final String s, final String sT){ + public void initiateTruncateText(final String s, final String sT){ try { post(new Runnable() { @Override public void run() { - if(!s.endsWith("\u202F")) song = s; - songTruncated = sT; + //The \u202F charachter is an invisible charachter used as a marker for whether + //a string has undergone truncation or not + if(!s.endsWith("\u202F")) title = s; + titleTruncated = sT; final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); @@ -129,28 +158,43 @@ public void onEndScroll() { }); }catch (NullPointerException exception){ Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e("Method: ","setTruncateText()"); + Log.e("Method: ","initiateTruncateText()"); System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + getTouchInterceptHorizontalScrollView().toString()); System.out.println(TAG + " TouchInterceptTextView = " + this.toString()); Log.e(TAG, exception.toString()); } } + /** + * @param text The string to check + * @return Returns whether the text has been truncated or not + */ public boolean isTextTruncated(String text) { - return (text.endsWith("…\u202F")); + return text.endsWith("…\u202F"); } + /** + * Untruncates the text in this textview and sets it + */ public void unTruncateText(){ - String untrunucatedText = song + "\uFEFF"; + //The \uEFF charachter is an invisible charachter used as a marker for whether + //a string is the untruncated song to be set + String untrunucatedText = title + "\uFEFF"; setText(untrunucatedText); } - public String getSongTruncated(){ - return this.songTruncated; + /** + * @return Returns the text in this textview truncated + */ + public String getTruncatedTitle(){ + return this.titleTruncated; } - public String getUntruncatedSong(){ - return this.song; + /** + * @return Returns the text in this textview untruncated + */ + public String getUntruncatedTitle(){ + return this.title; } /** From d286e8f403fbe57d7ba8796b95630af18f8d2695 Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 25 Jul 2017 15:25:16 -0400 Subject: [PATCH 74/97] Fixed illegal unicode in comments --- .../com/kabouzeid/gramophone/views/TouchInterceptTextView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index ec71eb2ec..60886d89e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -177,7 +177,7 @@ public boolean isTextTruncated(String text) { * Untruncates the text in this textview and sets it */ public void unTruncateText(){ - //The \uEFF charachter is an invisible charachter used as a marker for whether + //The uEFF unicode charachter is an invisible charachter used as a marker for whether //a string is the untruncated song to be set String untrunucatedText = title + "\uFEFF"; setText(untrunucatedText); From 9c276723b2d69bd1512b966d83526951c67a39af Mon Sep 17 00:00:00 2001 From: Duffman Date: Thu, 27 Jul 2017 23:19:43 -0400 Subject: [PATCH 75/97] Added further documentation --- .../gramophone/views/TouchInterceptFrameLayout.java | 9 +++------ app/src/main/res/layout/activity_album_detail.xml | 8 +++++--- app/src/main/res/layout/activity_artist_detail.xml | 7 ++++++- app/src/main/res/layout/item_list.xml | 3 +++ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index de26d4cd7..6f8593705 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -13,12 +13,9 @@ * @author Lincoln (theduffmaster) * * A custom FrameLayout view that intercepts touch events and decides whether to consume them or - * pass on the touch events to a TouchInterceptHorizontalScrollview which contains a TextView. - * In order for this to work properly the child views, - * a TouchInterceptHorizontalScrollView and a TextView, must be set via xml using the - * setTouchInterceptHorizontalScrollView and setScrollableTextView xml attributes. If this view is ever - * scrolled or interacts with a ListParent that is a ListView or a RecyclerView, then that ListParent - * must be set programmatically or via the designated XML attribute. + * pass on the touch events to a TouchInterceptHorizontalScrollview which contains a TouchInterceptTextView. + * This only needs to be used if the layout that the TouchHorizontalScrollView and the TouchInterceptTextView + * are in is clickable in any way. */ public class TouchInterceptFrameLayout extends FrameLayout { diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 6bbb0cc3b..b5da25dc1 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -1,8 +1,8 @@ - + @@ -48,11 +48,13 @@ android:paddingLeft="72dp" android:paddingRight="72dp"> + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_artist_detail.xml b/app/src/main/res/layout/activity_artist_detail.xml index 386eb9fc2..f606254f1 100644 --- a/app/src/main/res/layout/activity_artist_detail.xml +++ b/app/src/main/res/layout/activity_artist_detail.xml @@ -1,4 +1,7 @@ - + + @@ -43,11 +46,13 @@ android:paddingLeft="72dp" android:paddingRight="72dp"> + + + + + Date: Fri, 28 Jul 2017 00:46:56 -0400 Subject: [PATCH 76/97] Formatting fixes --- app/build.gradle | 3 +- .../gramophone/adapter/SearchAdapter.java | 1 - .../adapter/song/ArtistSongAdapter.java | 1 + .../adapter/song/PlayingQueueAdapter.java | 2 +- .../gramophone/adapter/song/SongAdapter.java | 3 +- .../views/TouchInterceptFrameLayout.java | 59 +++++----- .../TouchInterceptHorizontalScrollView.java | 106 +++++++++--------- .../views/TouchInterceptTextView.java | 37 +++--- .../main/res/drawable-v21/rect_selector.xml | 1 - .../main/res/layout/activity_album_detail.xml | 12 +- .../res/layout/activity_artist_detail.xml | 19 ++-- app/src/main/res/layout/item_list.xml | 13 +-- .../main/res/layout/item_list_single_row.xml | 5 +- app/src/main/res/values/colors.xml | 1 + 14 files changed, 123 insertions(+), 140 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d1139953c..922e68653 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,5 +119,4 @@ dependencies { compile 'com.jakewharton:butterknife:8.6.0' annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0' - -} \ No newline at end of file +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java index c935fc819..b4490349c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/SearchAdapter.java @@ -72,7 +72,6 @@ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @SuppressWarnings("ConstantConditions") @Override public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { - switch (getItemViewType(position)) { case ALBUM: final Album album = (Album) dataSet.get(position); diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java index 850011d47..c14b72020 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/ArtistSongAdapter.java @@ -66,6 +66,7 @@ public View getView(final int position, @Nullable View convertView, ViewGroup pa if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_list, parent, false); } + final TextView songTitle = (TextView) convertView.findViewById(R.id.title); final TextView songInfo = (TextView) convertView.findViewById(R.id.text); final ImageView albumArt = (ImageView) convertView.findViewById(R.id.image); diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java index 4b63782ae..1ee58b3e7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/PlayingQueueAdapter.java @@ -41,7 +41,7 @@ protected SongAdapter.ViewHolder createViewHolder(View view) { } @Override - public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) { + public void onBindViewHolder(@NonNull SongAdapter.ViewHolder holder, int position) { super.onBindViewHolder(holder, position); if (holder.imageText != null) { holder.imageText.setText(String.valueOf(position - current)); diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index 7104966f5..dc5249d69 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -199,8 +199,7 @@ public ViewHolder(@NonNull View itemView) { return; } menu.setOnTouchListener(new View.OnTouchListener() { - public boolean onTouch(View v, MotionEvent ev) - { + public boolean onTouch(View v, MotionEvent ev) { menu.getParent().requestDisallowInterceptTouchEvent(true); return false; } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 6f8593705..e3496e85a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -21,9 +21,8 @@ public class TouchInterceptFrameLayout extends FrameLayout { private static final int MAX_CLICK_DISTANCE = 5; - //Tag used so other views can find this one + // Tag used so other views can find this one private static final String touchInterceptFrameLayoutViewTag = "TIFL"; - private static final String touchInterceptHorizontalScrollViewTag = "TIHS"; private static final String TAG = "E/TouchInterceptFL"; @@ -50,7 +49,6 @@ public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSe public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - } /** @@ -75,22 +73,19 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - - int x = Math.round(e.getRawX()); - int y = Math.round(e.getRawY()); + int x = Math.round(e.getRawX()); + int y = Math.round(e.getRawY()); scrollView = getTouchInterceptHorizontalScrollView(); - try { + try { + scrollView.getGlobalVisibleRect(scrollViewRect); - scrollView.getGlobalVisibleRect(scrollViewRect); - - boolean touchedScrollView = - x > scrollViewRect.left && x < scrollViewRect.right && - y > scrollViewRect.top && y < scrollViewRect.bottom; - - if(scrollView.isScrollable()) { + boolean touchedScrollView = + x > scrollViewRect.left && x < scrollViewRect.right && + y > scrollViewRect.top && y < scrollViewRect.bottom; + if (scrollView.isScrollable()) { switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: scrollView.slidingPanelSetTouchEnabled(true); @@ -116,38 +111,40 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } } break; + case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: scrollView.slidingPanelSetTouchEnabled(true); - if (touchedScrollView) { - if (isTap) onTouchEvent(e); + if (touchedScrollView && isTap) { + onTouchEvent(e); } this.requestDisallowInterceptTouchEvent(false); break; } - return false; - }else{ - if(touchedScrollView) onTouchEvent(e); return false; - } - - } catch (NullPointerException exception) { - Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e("Method: ","onInterceptTouchEvent()"); - System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + findViewWithTag("TIHS").toString()); - System.out.println(TAG + " TouchInterceptTextView = " + findViewWithTag("TITV").toString()); - Log.e(TAG, exception.toString()); - onTouchEvent(e); + } else { + if (touchedScrollView) { + onTouchEvent(e); + } return false; } + } catch (NullPointerException ex) { + Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); + Log.e(TAG, "Method: onInterceptTouchEvent()"); + Log.e(TAG, "TouchInterceptHorizontalScrollView = " + findViewWithTag("TIHS").toString()); + Log.e(TAG, "TouchInterceptTextView = " + findViewWithTag("TITV").toString()); + ex.printStackTrace(); + onTouchEvent(e); + return false; + } } /** - *Cancels any Long Presses and inpending clicks. Used to prevent views from - * stealing touches while the user is scrolling something. + * Cancels any long presses and pending clicks. Used to prevent views from stealing touches + * while the user is scrolling something. */ - private void CancelClick(){ + private void CancelClick() { this.cancelPendingInputEvents(); this.cancelLongPress(); scrollView.cancelLongPress(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 690601134..a843de55a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -21,11 +21,11 @@ */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { - //The delay before triggering onEndScroll() + // The delay before triggering onEndScroll() public static final int ON_END_SCROLL_DELAY = 1000; private static final int MAX_CLICK_DISTANCE = 5; - //Tag used so other views can find this one + // Tag used so other views can find this one private static final String touchInterceptHorizontalScrollViewTag = "TIHS"; private float startX; @@ -35,48 +35,23 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private boolean mIsFling; - //Whether user is interacting with this again and to cancel text retruncate + // Whether user is interacting with this again and to cancel text retruncate private boolean cancel; - - private boolean cancelCheck; - //Whether to untruncate the text in the TouchInterceptTextView + // Whether to untruncate the text in the TouchInterceptTextView private boolean unTruncate; - //Whether this was touched + // Whether this was touched private boolean touched; private OnEndScrollListener onEndScrollListener; private SlidingUpPanelLayout queue; - /** - * Listens for when a user has stopped interacting with the scroll view - */ - public interface OnEndScrollListener { - // Triggered when a user has stopped interacting with the scroll view - void onEndScroll(); - } - - private class ScrollStateHandler implements Runnable { - //Runs when the user has not touched the scroll view for 1 second - @Override - public void run() { - if(!cancel) { - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastScrollUpdate) > ON_END_SCROLL_DELAY) { - lastScrollUpdate = -1; - if (onEndScrollListener != null) { - cancelCheck = true; - onEndScrollListener.onEndScroll(); - } - } else { - postDelayed(this, ON_END_SCROLL_DELAY); - } - } - } - } + // "true" if we can scroll (not locked) + // "false" if we cannot scroll (locked) + private boolean mScrollable = true; public TouchInterceptHorizontalScrollView(Context context) { super(context); @@ -94,12 +69,9 @@ public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, i super(context, attrs, defStyleAttr); } - // "true" if we can scroll (not locked) - // "false" if we cannot scroll (locked) - private boolean mScrollable = true; - /** * Disables and enables the ScrollView + * * @param enabled set to "true" to enable, "false" to disable */ public void setScrollingEnabled(boolean enabled) { @@ -108,6 +80,7 @@ public void setScrollingEnabled(boolean enabled) { /** * Returns whether the ScrollView is enabled or disabled + * * @return Returns "true" if enabled, "false" if disabled */ public boolean isScrollable() { @@ -139,7 +112,7 @@ public boolean onTouchEvent(MotionEvent e) { float distance = Math.abs(e.getX() - startX); // Currently crolling so untruncate text - if(unTruncate && distance > MAX_CLICK_DISTANCE) { + if (unTruncate && distance > MAX_CLICK_DISTANCE) { getTouchInterceptTextView().unTruncateText(); unTruncate = false; } @@ -159,10 +132,7 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { - - - if(e.getAction() == MotionEvent.ACTION_DOWN) slidingPanelSetTouchEnabled(true); - + if (e.getAction() == MotionEvent.ACTION_DOWN) slidingPanelSetTouchEnabled(true); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -175,17 +145,16 @@ public boolean onInterceptTouchEvent(MotionEvent e) { x > scrollViewRect.left && x < scrollViewRect.right && y > scrollViewRect.top && y < scrollViewRect.bottom; - if(!touchedScrollView){ + if (!touchedScrollView) { return false; } // Don't do anything with intercepted touch events if // not scrollable - if(!mScrollable){ + if (!mScrollable) { onTouchEvent(e); return false; - } - else + } else return super.onInterceptTouchEvent(e); } @@ -198,6 +167,7 @@ public OnEndScrollListener getOnEndScrollListener() { /** * Sets an OnEndScrollListener. Only one can be set at a time. + * * @param mOnEndScrollListener The OnEndScrollListener to be set */ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { @@ -214,10 +184,10 @@ public void fling(int velocityX) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - if(touched | mIsFling) slidingPanelSetTouchEnabled(false); + if (touched | mIsFling) slidingPanelSetTouchEnabled(false); CancelClick(); - if(cancelCheck) cancel = true; + if (cancelCheck) cancel = true; if (mIsFling) { if (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0) { @@ -236,32 +206,60 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) { /** * Enables and disables Sliding Panel dragging for the playing queue sliding panel + * * @param enable Set true to enable dragging, false to disable */ - public void slidingPanelSetTouchEnabled(boolean enable){ - queue = (SlidingUpPanelLayout) ((Activity)getContext()).findViewById(R.id.player_sliding_layout); - if(queue != null) queue.setTouchEnabled(enable); + public void slidingPanelSetTouchEnabled(boolean enable) { + queue = (SlidingUpPanelLayout) ((Activity) getContext()).findViewById(R.id.player_sliding_layout); + if (queue != null) queue.setTouchEnabled(enable); } /** * Cancels any Long Presses and inpending clicks. Used to prevent views from * stealing touches while the user is scrolling something. */ - public void CancelClick(){ + public void CancelClick() { getRootView().cancelLongPress(); getRootView().cancelPendingInputEvents(); this.cancelLongPress(); this.cancelPendingInputEvents(); } - public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { + public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); } /** * @return Returns the child TouchInterceptTextView */ - public TouchInterceptTextView getTouchInterceptTextView(){ + public TouchInterceptTextView getTouchInterceptTextView() { return (TouchInterceptTextView) this.getChildAt(0); } + + /** + * Listens for when a user has stopped interacting with the scroll view + */ + public interface OnEndScrollListener { + // Triggered when a user has stopped interacting with the scroll view + void onEndScroll(); + } + + private class ScrollStateHandler implements Runnable { + // Runs when the user has not touched the scroll view for 1 second + @Override + public void run() { + if (!cancel) { + long currentTime = System.currentTimeMillis(); + if ((currentTime - lastScrollUpdate) > ON_END_SCROLL_DELAY) { + lastScrollUpdate = -1; + if (onEndScrollListener != null) { + cancelCheck = true; + onEndScrollListener.onEndScroll(); + } + } else { + postDelayed(this, ON_END_SCROLL_DELAY); + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index 60886d89e..b537dade3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -21,7 +21,7 @@ public class TouchInterceptTextView extends AppCompatTextView { private static final int RETRUNCATE_DELAY = 600; - //Tag used so other views can find this one + // Tag used so other views can find this one private static final String touchInterceptTextViewTag = "TITV"; private static final String TAG = "E/TouchInterceptFL"; @@ -85,11 +85,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { String currentText = getText().toString(); Boolean isUntruncatedSong = currentText.endsWith("\uFEFF"); - if(!currentText.endsWith("\u202F") && + if (!currentText.endsWith("\u202F") && !isUntruncatedSong) title = currentText; - if(!isUntruncatedSong && - (getWidth() == 0 | textBoundsWidth < getPaint().measureText(currentText)) ) { + if (!isUntruncatedSong && + (getWidth() == 0 | textBoundsWidth < getPaint().measureText(currentText))) { /** * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. @@ -106,10 +106,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + "\u202F"; setText(truncatedText); - initiateTruncateText(title,truncatedText); - }else{ + initiateTruncateText(title, truncatedText); + } else { setText(currentText); - initiateTruncateText(title,currentText); + initiateTruncateText(title, currentText); } } @@ -117,10 +117,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * Takes the string that's undergone truncation and based on whether it's been truncated or not * set whether it should be scrollable or not and what to do when the user finishes scrolling - * @param s The string before truncation + * + * @param s The string before truncation * @param sT The string after truncation */ - public void initiateTruncateText(final String s, final String sT){ + public void initiateTruncateText(final String s, final String sT) { try { post(new Runnable() { @@ -128,7 +129,7 @@ public void initiateTruncateText(final String s, final String sT){ public void run() { //The \u202F charachter is an invisible charachter used as a marker for whether //a string has undergone truncation or not - if(!s.endsWith("\u202F")) title = s; + if (!s.endsWith("\u202F")) title = s; titleTruncated = sT; final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); @@ -150,15 +151,15 @@ public void onEndScroll() { }); } - }else{ - if(!sT.endsWith("\uFEFF")) sV.setScrollingEnabled(false); + } else { + if (!sT.endsWith("\uFEFF")) sV.setScrollingEnabled(false); } } }); - }catch (NullPointerException exception){ + } catch (NullPointerException exception) { Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e("Method: ","initiateTruncateText()"); + Log.e("Method: ", "initiateTruncateText()"); System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + getTouchInterceptHorizontalScrollView().toString()); System.out.println(TAG + " TouchInterceptTextView = " + this.toString()); Log.e(TAG, exception.toString()); @@ -176,7 +177,7 @@ public boolean isTextTruncated(String text) { /** * Untruncates the text in this textview and sets it */ - public void unTruncateText(){ + public void unTruncateText() { //The uEFF unicode charachter is an invisible charachter used as a marker for whether //a string is the untruncated song to be set String untrunucatedText = title + "\uFEFF"; @@ -186,14 +187,14 @@ public void unTruncateText(){ /** * @return Returns the text in this textview truncated */ - public String getTruncatedTitle(){ + public String getTruncatedTitle() { return this.titleTruncated; } /** * @return Returns the text in this textview untruncated */ - public String getUntruncatedTitle(){ + public String getUntruncatedTitle() { return this.title; } @@ -202,7 +203,7 @@ public String getUntruncatedTitle(){ */ public void reTruncateScrollText(final String truncatedString, final TouchInterceptHorizontalScrollView sV, - final TouchInterceptTextView tV) { + final TouchInterceptTextView tV) { ObjectAnimator.ofInt(sV, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); sV.slidingPanelSetTouchEnabled(true); final Handler handler = new Handler(); diff --git a/app/src/main/res/drawable-v21/rect_selector.xml b/app/src/main/res/drawable-v21/rect_selector.xml index 8f1539345..089543849 100644 --- a/app/src/main/res/drawable-v21/rect_selector.xml +++ b/app/src/main/res/drawable-v21/rect_selector.xml @@ -10,7 +10,6 @@ android:drawable="@color/ripple_material_light" android:state_activated="true" /> - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index b5da25dc1..7a683859b 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -1,7 +1,6 @@ - - + + android:orientation="vertical"> - + android:layout_height="wrap_content"> - - - + @@ -35,6 +34,11 @@ android:layout_height="wrap_content" android:orientation="vertical"> + + - + android:layout_height="wrap_content"> - - - diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 99aaabb5b..228a6da19 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,14 +1,13 @@ - - + + tools:ignore="UnusedAttribute"> + android:paddingStart="16dp"> - + android:layout_height="wrap_content"> - + android:layout_weight="1"> + android:layout_height="wrap_content"> #34000000 + #607d8b #f5f5f5 \ No newline at end of file From cbf25cbb766e95e82720d259ee80e23301a296df Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Fri, 28 Jul 2017 22:13:56 -0400 Subject: [PATCH 77/97] Refactoring --- .../views/TouchInterceptFrameLayout.java | 117 +++++----- .../TouchInterceptHorizontalScrollView.java | 116 +++++----- .../views/TouchInterceptTextView.java | 211 ++++++++---------- .../main/res/layout/activity_album_detail.xml | 1 - 4 files changed, 215 insertions(+), 230 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index e3496e85a..aecfc6ebf 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -19,43 +19,43 @@ */ public class TouchInterceptFrameLayout extends FrameLayout { - private static final int MAX_CLICK_DISTANCE = 5; - - // Tag used so other views can find this one - private static final String touchInterceptFrameLayoutViewTag = "TIFL"; - private static final String touchInterceptHorizontalScrollViewTag = "TIHS"; + public static final String TAG = TouchInterceptFrameLayout.class.getSimpleName(); - private static final String TAG = "E/TouchInterceptFL"; - private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you " + - "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + - "via XML? Did you set it to something null?"; + private static final int MAX_CLICK_DISTANCE = 5; private TouchInterceptHorizontalScrollView scrollView; private Rect scrollViewRect = new Rect(); private float startX; - private boolean isTap; public TouchInterceptFrameLayout(@NonNull Context context) { this(context, null); - setTag(touchInterceptFrameLayoutViewTag); + + init(); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); - setTag(touchInterceptFrameLayoutViewTag); + + init(); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + + init(); + } + + private void init() { + setTag(TouchInterceptFrameLayout.TAG); } /** * @return Returns the TouchInterceptHorizontalScrollview in this layout */ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { - return (TouchInterceptHorizontalScrollView) findViewWithTag(touchInterceptHorizontalScrollViewTag); + return (TouchInterceptHorizontalScrollView) findViewWithTag(TouchInterceptHorizontalScrollView.TAG); } /** @@ -77,65 +77,54 @@ public boolean onInterceptTouchEvent(MotionEvent e) { int y = Math.round(e.getRawY()); scrollView = getTouchInterceptHorizontalScrollView(); + scrollView.getGlobalVisibleRect(scrollViewRect); + + boolean touchedScrollView = + x > scrollViewRect.left && x < scrollViewRect.right && + y > scrollViewRect.top && y < scrollViewRect.bottom; + + if (scrollView.isScrollable()) { + switch (e.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + scrollView.slidingPanelSetTouchEnabled(true); + if (!touchedScrollView) { + scrollView.cancelPendingInputEvents(); + return false; + } + + startX = e.getX(); + isTap = true; + onTouchEvent(e); - try { - scrollView.getGlobalVisibleRect(scrollViewRect); + break; - boolean touchedScrollView = - x > scrollViewRect.left && x < scrollViewRect.right && - y > scrollViewRect.top && y < scrollViewRect.bottom; + case MotionEvent.ACTION_MOVE: + if (touchedScrollView) { + float distance = Math.abs(e.getX() - startX); - if (scrollView.isScrollable()) { - switch (e.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - scrollView.slidingPanelSetTouchEnabled(true); - if (!touchedScrollView) { - scrollView.cancelPendingInputEvents(); - return false; + // Scrolling the view: cancel event to prevent long press + if (distance > MAX_CLICK_DISTANCE) { + isTap = false; + CancelClick(); } + } + break; - startX = e.getX(); - isTap = true; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + scrollView.slidingPanelSetTouchEnabled(true); + if (touchedScrollView && isTap) { onTouchEvent(e); + } + this.requestDisallowInterceptTouchEvent(false); + break; + } - break; - - case MotionEvent.ACTION_MOVE: - if (touchedScrollView) { - float distance = Math.abs(e.getX() - startX); - - // Scrolling the view: cancel event to prevent long press - if (distance > MAX_CLICK_DISTANCE) { - isTap = false; - CancelClick(); - } - } - break; - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - scrollView.slidingPanelSetTouchEnabled(true); - if (touchedScrollView && isTap) { - onTouchEvent(e); - } - this.requestDisallowInterceptTouchEvent(false); - break; - } - - return false; - } else { - if (touchedScrollView) { - onTouchEvent(e); - } - return false; + return false; + } else { + if (touchedScrollView) { + onTouchEvent(e); } - } catch (NullPointerException ex) { - Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e(TAG, "Method: onInterceptTouchEvent()"); - Log.e(TAG, "TouchInterceptHorizontalScrollView = " + findViewWithTag("TIHS").toString()); - Log.e(TAG, "TouchInterceptTextView = " + findViewWithTag("TITV").toString()); - ex.printStackTrace(); - onTouchEvent(e); return false; } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index a843de55a..5ee17c021 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -11,7 +11,7 @@ import com.sothree.slidinguppanel.SlidingUpPanelLayout; /** - * @author Created by lincoln on 7/3/17. + * @author Lincoln (theduffmaster) * * A custom HorizontalScrollView that is only useful as the child of a TouchInterceptFrameLayout. * This allows for the TouchInterceptFrameLayout to disable and enable scrolling in addition to @@ -21,13 +21,12 @@ */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { + public static final String TAG = TouchInterceptHorizontalScrollView.class.getSimpleName(); + // The delay before triggering onEndScroll() public static final int ON_END_SCROLL_DELAY = 1000; private static final int MAX_CLICK_DISTANCE = 5; - // Tag used so other views can find this one - private static final String touchInterceptHorizontalScrollViewTag = "TIHS"; - private float startX; private Rect scrollViewRect = new Rect(); @@ -49,33 +48,49 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private SlidingUpPanelLayout queue; - // "true" if we can scroll (not locked) - // "false" if we cannot scroll (locked) private boolean mScrollable = true; public TouchInterceptHorizontalScrollView(Context context) { super(context); - setTag(touchInterceptHorizontalScrollViewTag); - setHorizontalScrollBarEnabled(false); + + init(); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); - setTag(touchInterceptHorizontalScrollViewTag); - setHorizontalScrollBarEnabled(false); + + init(); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + + init(); + } + + private void init() { + setTag(TouchInterceptHorizontalScrollView.TAG); + setHorizontalScrollBarEnabled(false); + } + + public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { + return (TouchInterceptFrameLayout) getRootView().findViewWithTag(TouchInterceptFrameLayout.TAG); + } + + /** + * @return Returns the child TouchInterceptTextView + */ + public TouchInterceptTextView getTouchInterceptTextView() { + return (TouchInterceptTextView) this.getChildAt(0); } /** * Disables and enables the ScrollView * - * @param enabled set to "true" to enable, "false" to disable + * @param scrollable set to "true" to enable, "false" to disable */ - public void setScrollingEnabled(boolean enabled) { - mScrollable = enabled; + public void setScrollable(boolean scrollable) { + mScrollable = scrollable; } /** @@ -97,21 +112,23 @@ public boolean canScroll() { @Override public boolean onTouchEvent(MotionEvent e) { switch (e.getAction()) { - case MotionEvent.ACTION_DOWN: touched = true; cancel = true; startX = e.getX(); + // If we can scroll pass the event to the superclass - if (mScrollable) return super.onTouchEvent(e); + if (mScrollable) { + return super.onTouchEvent(e); + } + // Only continue to handle the touch event if scrolling enabled - return mScrollable; // mScrollable is always false at this point + return false; case MotionEvent.ACTION_MOVE: - float distance = Math.abs(e.getX() - startX); - // Currently crolling so untruncate text + // Currently scrolling so untruncate text if (unTruncate && distance > MAX_CLICK_DISTANCE) { getTouchInterceptTextView().unTruncateText(); unTruncate = false; @@ -125,6 +142,7 @@ public boolean onTouchEvent(MotionEvent e) { postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); lastScrollUpdate = System.currentTimeMillis(); unTruncate = true; + default: return super.onTouchEvent(e); } @@ -132,7 +150,9 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { - if (e.getAction() == MotionEvent.ACTION_DOWN) slidingPanelSetTouchEnabled(true); + if (e.getAction() == MotionEvent.ACTION_DOWN) { + slidingPanelSetTouchEnabled(true); + } int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -143,19 +163,19 @@ public boolean onInterceptTouchEvent(MotionEvent e) { boolean touchedScrollView = x > scrollViewRect.left && x < scrollViewRect.right && - y > scrollViewRect.top && y < scrollViewRect.bottom; + y > scrollViewRect.top && y < scrollViewRect.bottom; if (!touchedScrollView) { return false; } - // Don't do anything with intercepted touch events if - // not scrollable + // Don't do anything with intercepted touch events if not scrollable if (!mScrollable) { onTouchEvent(e); return false; - } else - return super.onInterceptTouchEvent(e); + } + + return super.onInterceptTouchEvent(e); } /** @@ -184,34 +204,39 @@ public void fling(int velocityX) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - if (touched | mIsFling) slidingPanelSetTouchEnabled(false); + if (touched | mIsFling) { + slidingPanelSetTouchEnabled(false); + } + CancelClick(); - if (cancelCheck) cancel = true; + if (cancelCheck) { + cancel = true; + } - if (mIsFling) { - if (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0) { - slidingPanelSetTouchEnabled(true); - touched = false; - // The user is done interacting with the scroll view - cancel = false; - postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); - lastScrollUpdate = System.currentTimeMillis(); - mIsFling = false; - cancelCheck = false; - unTruncate = true; - } + if (mIsFling && (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0)) { + slidingPanelSetTouchEnabled(true); + touched = false; + // The user is done interacting with the scroll view + cancel = false; + postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); + lastScrollUpdate = System.currentTimeMillis(); + mIsFling = false; + cancelCheck = false; + unTruncate = true; } } /** - * Enables and disables Sliding Panel dragging for the playing queue sliding panel + * Enables and disables Sliding Panel dragging for the playing queue sliding panel. * * @param enable Set true to enable dragging, false to disable */ public void slidingPanelSetTouchEnabled(boolean enable) { queue = (SlidingUpPanelLayout) ((Activity) getContext()).findViewById(R.id.player_sliding_layout); - if (queue != null) queue.setTouchEnabled(enable); + if (queue != null) { + queue.setTouchEnabled(enable); + } } /** @@ -225,17 +250,6 @@ public void CancelClick() { this.cancelPendingInputEvents(); } - public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { - return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); - } - - /** - * @return Returns the child TouchInterceptTextView - */ - public TouchInterceptTextView getTouchInterceptTextView() { - return (TouchInterceptTextView) this.getChildAt(0); - } - /** * Listens for when a user has stopped interacting with the scroll view */ diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index b537dade3..6064ef1f2 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -7,210 +7,193 @@ import android.support.v7.widget.AppCompatTextView; import android.text.TextUtils; import android.util.AttributeSet; -import android.util.Log; /** - * @author Created by lincoln on 7/16/17. + * @author Lincoln (theduffmaster) * * TextView that automatically does exactly what android:ellipsize="end" does, except this works in a TouchInterceptHorizontalScrollViews. * Truncates the string so it doesn't get cuttoff in the TouchInterceptHorizontalScrollView * and puts an ellipsis at the end of it. * Must be used within a TouchInterceptHorizontalScrollview or it won't work */ - public class TouchInterceptTextView extends AppCompatTextView { + + public static final String TAG = TouchInterceptTextView.class.getSimpleName(); + private static final int RETRUNCATE_DELAY = 600; - // Tag used so other views can find this one - private static final String touchInterceptTextViewTag = "TITV"; + // Invisible character used as a marker indicating whether a string has undergone truncation + private static final String TRUNCATED_MARKER = "\u202F"; - private static final String TAG = "E/TouchInterceptFL"; - private static final String NULL_VIEWS_EXCEPTION_MESSAGE = "Either textView or scrollView is null. Maybe you " + - "forgot to set them using setTouchInterceptHorizontalScrollView and setScrollableTextView " + - "via XML? Did you set it to something null?"; + // Invisible character used as a marker indicating whether a string is untruncated + private static final String MARKER_UNTRUNCATED = "\uFEFF"; - private String title; - private String titleTruncated; + private String text; + private String truncatedText; public TouchInterceptTextView(Context context) { super(context); - setTag(touchInterceptTextViewTag); - //Have to set this enorder to enable long clicking when touching the text - setLongClickable(true); - //Blocks clicks from passing through this view - setClickable(true); - //Can't use maxlines, have to use this. Typical Android BS - setSingleLine(); + + init(); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); - setTag(touchInterceptTextViewTag); - //Have to set this enorder to enable long clicking when touching the text - setLongClickable(true); - //Blocks clicks from passing through this view - setClickable(true); - //Can't use maxlines, have to use this. Typical Android BS - setSingleLine(); + + init(); } public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + + init(); + } + + private void init() { + setTag(TouchInterceptTextView.TAG); + + // Enable long clicking when touching the text + setLongClickable(true); + + // Blocks clicks from passing through this view + setClickable(true); + + // Use this instead of maxlines + setSingleLine(); } /** - * @return Returns the TouchInterceptFrameLayout in this layout + * @return Returns the {@link TouchInterceptFrameLayout} inside this layout. */ public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { - return (TouchInterceptFrameLayout) getRootView().findViewWithTag("TIFL"); + return (TouchInterceptFrameLayout) getRootView().findViewWithTag(TouchInterceptFrameLayout.TAG); } /** - * @return Returns the parent TouchInterceptHorizontalScrollview + * @return Returns the parent {@link TouchInterceptHorizontalScrollView}. */ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { return (TouchInterceptHorizontalScrollView) getParent(); } /** - * The text undergoes truncation here. onMeasure is immediately called after setText - * and has a reference to the parent bounds. The parents bounds are used for setting the - * length of the truncate text ensuring that the text does not get cut off + * The text undergoes truncation here. {@link #onMeasure} is immediately called after + * {@link #setText} and has a reference to the parent's bounds. The bounds are used for setting + * the length of the truncated text, ensuring that the text does not get visibly cut off. */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - int textBoundsWidth = MeasureSpec.getSize(widthMeasureSpec); - String currentText = getText().toString(); - Boolean isUntruncatedSong = currentText.endsWith("\uFEFF"); + String fittedText = getText().toString(); - if (!currentText.endsWith("\u202F") && - !isUntruncatedSong) title = currentText; + final int textBoundsWidth = MeasureSpec.getSize(widthMeasureSpec); + final boolean isUntruncated = fittedText.endsWith(MARKER_UNTRUNCATED); - if (!isUntruncatedSong && - (getWidth() == 0 | textBoundsWidth < getPaint().measureText(currentText))) { + if (!fittedText.endsWith(TRUNCATED_MARKER) && !isUntruncated) { + this.text = fittedText; + } - /** - * Does exactly what android:ellipsize="end" does, except this works in HorizontalScrollViews. - * Truncates the string so it doesn't get cuttoff in the HorizontalScrollView - * and puts an ellipsis at the end of it. Then it sets the TextView with the new Ellipsized value. - */ - String truncatedText = TextUtils.ellipsize(currentText, + if (!isUntruncated && (getWidth() == 0 | textBoundsWidth < getPaint().measureText(fittedText))) { + // Mimics behavior of `android:ellipsize="end"`, except it works in a HorizontalScrollView. + // Truncates the string so it doesn't get cut off in the HorizontalScrollView with an + // ellipsis at the end of it. + fittedText = TextUtils.ellipsize(fittedText, getPaint(), (float) textBoundsWidth, TextUtils.TruncateAt.END).toString() - - //The \u202F charachter is an invisible charachter used as a marker for whether - //a string has undergone truncation or not - + "\u202F"; - - setText(truncatedText); - initiateTruncateText(title, truncatedText); - } else { - setText(currentText); - initiateTruncateText(title, currentText); + + TRUNCATED_MARKER; } + setText(fittedText); + initiateTruncateText(text, fittedText); } /** * Takes the string that's undergone truncation and based on whether it's been truncated or not - * set whether it should be scrollable or not and what to do when the user finishes scrolling + * set whether it should be scrollable or not and what to do when the user finishes scrolling. * - * @param s The string before truncation - * @param sT The string after truncation + * @param originalText The string before truncation + * @param truncatedText The string after truncation */ - public void initiateTruncateText(final String s, final String sT) { - - try { - post(new Runnable() { - @Override - public void run() { - //The \u202F charachter is an invisible charachter used as a marker for whether - //a string has undergone truncation or not - if (!s.endsWith("\u202F")) title = s; - titleTruncated = sT; - - final TouchInterceptHorizontalScrollView sV = getTouchInterceptHorizontalScrollView(); - - if (isTextTruncated(sT)) { - - if (s.equals(sT) && !sT.endsWith("\uFEFF")) { - sV.setScrollingEnabled(false); - - } else { - sV.setScrollingEnabled(true); + public void initiateTruncateText(final String originalText, final String truncatedText) { + post(new Runnable() { + @Override + public void run() { + if (!originalText.endsWith(TRUNCATED_MARKER)) text = originalText; + TouchInterceptTextView.this.truncatedText = truncatedText; - sV.setOnEndScrollListener( - new TouchInterceptHorizontalScrollView.OnEndScrollListener() { - @Override - public void onEndScroll() { - reTruncateScrollText(sT, sV, TouchInterceptTextView.this); - } - }); - } + final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); + if (isTextTruncated(truncatedText)) { + if (originalText.equals(truncatedText) && !truncatedText.endsWith(MARKER_UNTRUNCATED)) { + scrollView.setScrollable(false); } else { - if (!sT.endsWith("\uFEFF")) sV.setScrollingEnabled(false); + scrollView.setScrollable(true); + + scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() { + @Override + public void onEndScroll() { + reTruncateScrollText(truncatedText, scrollView, TouchInterceptTextView.this); + } + }); } - + } else if (!truncatedText.endsWith(MARKER_UNTRUNCATED)) { + scrollView.setScrollable(false); } - }); - } catch (NullPointerException exception) { - Log.e(TAG, NULL_VIEWS_EXCEPTION_MESSAGE); - Log.e("Method: ", "initiateTruncateText()"); - System.out.println(TAG + " TouchInterceptHorizontalScrollView = " + getTouchInterceptHorizontalScrollView().toString()); - System.out.println(TAG + " TouchInterceptTextView = " + this.toString()); - Log.e(TAG, exception.toString()); - } + } + }); } /** - * @param text The string to check - * @return Returns whether the text has been truncated or not + * Checks whether a string was truncated at some point. + * + * @param text The string to check. + * @return Returns whether the text has been truncated or not. */ public boolean isTextTruncated(String text) { - return text.endsWith("…\u202F"); + return text.endsWith("…" + TRUNCATED_MARKER); } /** - * Untruncates the text in this textview and sets it + * Untruncates and sets the text. */ public void unTruncateText() { - //The uEFF unicode charachter is an invisible charachter used as a marker for whether - //a string is the untruncated song to be set - String untrunucatedText = title + "\uFEFF"; + String untrunucatedText = text + MARKER_UNTRUNCATED; setText(untrunucatedText); } /** - * @return Returns the text in this textview truncated + * @return Returns the truncated text. */ - public String getTruncatedTitle() { - return this.titleTruncated; + public String getTruncatedText() { + return this.truncatedText; } /** - * @return Returns the text in this textview untruncated + * @return Returns the untruncated text. */ - public String getUntruncatedTitle() { - return this.title; + public String getUntruncatedText() { + return this.text; } /** - * Retruncates the text with a fancy scroll to beginning animation that takes a set amount of time + * Retruncates the text and animates it scrolling back to the start poosition. */ public void reTruncateScrollText(final String truncatedString, - final TouchInterceptHorizontalScrollView sV, - final TouchInterceptTextView tV) { - ObjectAnimator.ofInt(sV, "scrollX", 0).setDuration(RETRUNCATE_DELAY).start(); - sV.slidingPanelSetTouchEnabled(true); + final TouchInterceptHorizontalScrollView scrollView, + final TouchInterceptTextView textView) { + ObjectAnimator.ofInt(scrollView, "scrollX", 0) + .setDuration(RETRUNCATE_DELAY) + .start(); + + scrollView.slidingPanelSetTouchEnabled(true); + final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { - tV.setText(truncatedString); + textView.setText(truncatedString); } }, RETRUNCATE_DELAY); } diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 7a683859b..9ca9a5a58 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -2,7 +2,6 @@ From 95426e6b9160d59152b26f99f02b29b1a7605b48 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sat, 29 Jul 2017 16:02:39 -0400 Subject: [PATCH 78/97] Removed uses of cancelPendingInputEvents and slidingPanelSetTouchEnabled --- .../views/TouchInterceptFrameLayout.java | 5 --- .../TouchInterceptHorizontalScrollView.java | 35 +++---------------- .../views/TouchInterceptTextView.java | 2 -- 3 files changed, 5 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index aecfc6ebf..cd418d4c6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -5,7 +5,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; @@ -86,7 +85,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (scrollView.isScrollable()) { switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: - scrollView.slidingPanelSetTouchEnabled(true); if (!touchedScrollView) { scrollView.cancelPendingInputEvents(); return false; @@ -112,7 +110,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: - scrollView.slidingPanelSetTouchEnabled(true); if (touchedScrollView && isTap) { onTouchEvent(e); } @@ -134,9 +131,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { * while the user is scrolling something. */ private void CancelClick() { - this.cancelPendingInputEvents(); this.cancelLongPress(); scrollView.cancelLongPress(); - scrollView.cancelPendingInputEvents(); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 5ee17c021..b724fd3ae 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -1,13 +1,11 @@ package com.kabouzeid.gramophone.views; -import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.HorizontalScrollView; -import com.kabouzeid.gramophone.R; import com.sothree.slidinguppanel.SlidingUpPanelLayout; /** @@ -32,7 +30,7 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private long lastScrollUpdate = -1; - private boolean mIsFling; + private boolean isFling; // Whether user is interacting with this again and to cancel text retruncate private boolean cancel; @@ -46,7 +44,7 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private OnEndScrollListener onEndScrollListener; - private SlidingUpPanelLayout queue; + private SlidingUpPanelLayout slidingPanel; private boolean mScrollable = true; @@ -135,7 +133,6 @@ public boolean onTouchEvent(MotionEvent e) { } case MotionEvent.ACTION_UP: - slidingPanelSetTouchEnabled(true); touched = false; // The user is done interacting with the scroll view cancel = false; @@ -150,9 +147,6 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { - if (e.getAction() == MotionEvent.ACTION_DOWN) { - slidingPanelSetTouchEnabled(true); - } int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -197,57 +191,38 @@ public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { @Override public void fling(int velocityX) { super.fling(velocityX); - mIsFling = true; + isFling = true; } @Override protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - if (touched | mIsFling) { - slidingPanelSetTouchEnabled(false); - } - CancelClick(); if (cancelCheck) { cancel = true; } - if (mIsFling && (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0)) { - slidingPanelSetTouchEnabled(true); + if (isFling && (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0)) { touched = false; // The user is done interacting with the scroll view cancel = false; postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); lastScrollUpdate = System.currentTimeMillis(); - mIsFling = false; + isFling = false; cancelCheck = false; unTruncate = true; } } - /** - * Enables and disables Sliding Panel dragging for the playing queue sliding panel. - * - * @param enable Set true to enable dragging, false to disable - */ - public void slidingPanelSetTouchEnabled(boolean enable) { - queue = (SlidingUpPanelLayout) ((Activity) getContext()).findViewById(R.id.player_sliding_layout); - if (queue != null) { - queue.setTouchEnabled(enable); - } - } - /** * Cancels any Long Presses and inpending clicks. Used to prevent views from * stealing touches while the user is scrolling something. */ public void CancelClick() { getRootView().cancelLongPress(); - getRootView().cancelPendingInputEvents(); this.cancelLongPress(); - this.cancelPendingInputEvents(); } /** diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index 6064ef1f2..6bc6e0def 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -187,8 +187,6 @@ public void reTruncateScrollText(final String truncatedString, .setDuration(RETRUNCATE_DELAY) .start(); - scrollView.slidingPanelSetTouchEnabled(true); - final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override From 78c2a09c9b3e4c54402cd2b793386eaaf1fb9d98 Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Sat, 29 Jul 2017 19:01:33 -0400 Subject: [PATCH 79/97] More cleanup --- .../views/TouchInterceptFrameLayout.java | 53 ++++--- .../TouchInterceptHorizontalScrollView.java | 129 +++++++----------- .../views/TouchInterceptTextView.java | 8 +- 3 files changed, 81 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index cd418d4c6..eed5d6f95 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -11,10 +11,12 @@ /** * @author Lincoln (theduffmaster) * - * A custom FrameLayout view that intercepts touch events and decides whether to consume them or - * pass on the touch events to a TouchInterceptHorizontalScrollview which contains a TouchInterceptTextView. - * This only needs to be used if the layout that the TouchHorizontalScrollView and the TouchInterceptTextView - * are in is clickable in any way. + * A custom {@link FrameLayout} that intercepts touch events and decides whether to consume them or + * pass them on to a child {@link TouchInterceptHorizontalScrollView} and its + * {@link TouchInterceptTextView}. + * + * This only needs to be used if the layout containing the {@link TouchInterceptHorizontalScrollView} + * is clickable. */ public class TouchInterceptFrameLayout extends FrameLayout { @@ -24,51 +26,46 @@ public class TouchInterceptFrameLayout extends FrameLayout { private TouchInterceptHorizontalScrollView scrollView; - private Rect scrollViewRect = new Rect(); + private Rect scrollViewRect; private float startX; private boolean isTap; public TouchInterceptFrameLayout(@NonNull Context context) { this(context, null); - init(); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); - init(); } public TouchInterceptFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(); } private void init() { + scrollViewRect = new Rect(); setTag(TouchInterceptFrameLayout.TAG); } /** - * @return Returns the TouchInterceptHorizontalScrollview in this layout + * @return Returns the child {@link TouchInterceptHorizontalScrollView}. */ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView() { return (TouchInterceptHorizontalScrollView) findViewWithTag(TouchInterceptHorizontalScrollView.TAG); } /** - * This intercepts the touch event and, by returning false and onTouchEvent(), passes the touchevent - * to both itself and its child views (by calling TouchEvent it passes it to itself). + * Intercepts touch events to selectively pass the event on to its child view. * It also detects where the touch was placed so that if the touch is not in the scrollview, the - * touch is not passed to the HorizontalScrollView, avoiding the child view swallowing up the long - * click. False is passed to still allow MenuItemClick to happen. - * However, if the action is ACTION_MOVE, it cancels the touch event in itself and - * only gives it to its children, which, in this case is a HorizontalScrollView. + * touch is not passed to it, avoiding the child view swallowing up the long press. ACTION_MOVE + * actions are cancelled here and instead passed to the child view. * - * @param e the intercepted touch event - * @return If this function returns true, the MotionEvent will be intercepted, - * meaning it will be not be passed on to the child, but rather to the onTouchEvent of this View. + * @param e The intercepted touch event. + * @return True if the MotionEvent will be intercepted (i.e. it will not be passed on to its + * child, but rather to the onTouchEvent method of this view). */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { @@ -93,7 +90,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { startX = e.getX(); isTap = true; onTouchEvent(e); - break; case MotionEvent.ACTION_MOVE: @@ -103,7 +99,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { isTap = false; - CancelClick(); + cancelClick(); } } break; @@ -116,21 +112,20 @@ public boolean onInterceptTouchEvent(MotionEvent e) { this.requestDisallowInterceptTouchEvent(false); break; } - - return false; - } else { - if (touchedScrollView) { - onTouchEvent(e); - } return false; } + + if (touchedScrollView) { + onTouchEvent(e); + } + return false; } /** - * Cancels any long presses and pending clicks. Used to prevent views from stealing touches - * while the user is scrolling something. + * Cancels any long presses. Used to prevent views from stealing touches while the user is + * scrolling something. */ - private void CancelClick() { + private void cancelClick() { this.cancelLongPress(); scrollView.cancelLongPress(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index b724fd3ae..a73b8b4fd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -6,67 +6,57 @@ import android.view.MotionEvent; import android.widget.HorizontalScrollView; -import com.sothree.slidinguppanel.SlidingUpPanelLayout; - /** * @author Lincoln (theduffmaster) * - * A custom HorizontalScrollView that is only useful as the child of a TouchInterceptFrameLayout. - * This allows for the TouchInterceptFrameLayout to disable and enable scrolling in addition to - * being able to know when a user is and is not interacting with the scrolling view. + * A custom {@link HorizontalScrollView} that is only useful as the child of a + * {@link TouchInterceptFrameLayout}. Allows for the layout to disable and enable scrolling in + * addition to being able to know when a user is and is not interacting with the scrolling view. * - * Must have a TouchInterceptTextView as it's child. It can only have one child. + * Must have a {@link TouchInterceptTextView} as its only child. */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { public static final String TAG = TouchInterceptHorizontalScrollView.class.getSimpleName(); - // The delay before triggering onEndScroll() - public static final int ON_END_SCROLL_DELAY = 1000; + /** Delay before triggering {@link OnEndScrollListener#onEndScroll} */ + private static final int ON_END_SCROLL_DELAY = 1000; + private static final int MAX_CLICK_DISTANCE = 5; private float startX; - private Rect scrollViewRect = new Rect(); - private long lastScrollUpdate = -1; - + private boolean scrollable; private boolean isFling; + private Rect scrollViewRect; + private OnEndScrollListener onEndScrollListener; // Whether user is interacting with this again and to cancel text retruncate private boolean cancel; private boolean cancelCheck; // Whether to untruncate the text in the TouchInterceptTextView - private boolean unTruncate; - - // Whether this was touched - private boolean touched; - - private OnEndScrollListener onEndScrollListener; - - private SlidingUpPanelLayout slidingPanel; - - private boolean mScrollable = true; + private boolean untruncate; public TouchInterceptHorizontalScrollView(Context context) { super(context); - init(); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); - init(); } public TouchInterceptHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(); } private void init() { + lastScrollUpdate = -1; + scrollable = true; + scrollViewRect = new Rect(); setTag(TouchInterceptHorizontalScrollView.TAG); setHorizontalScrollBarEnabled(false); } @@ -76,69 +66,67 @@ public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { } /** - * @return Returns the child TouchInterceptTextView + * @return Returns the child {@link TouchInterceptTextView}. */ public TouchInterceptTextView getTouchInterceptTextView() { return (TouchInterceptTextView) this.getChildAt(0); } /** - * Disables and enables the ScrollView - * - * @param scrollable set to "true" to enable, "false" to disable + * @return Returns the set {@link OnEndScrollListener}. */ - public void setScrollable(boolean scrollable) { - mScrollable = scrollable; + public OnEndScrollListener getOnEndScrollListener() { + return onEndScrollListener; } /** - * Returns whether the ScrollView is enabled or disabled + * Disables and enables scrolling. * - * @return Returns "true" if enabled, "false" if disabled + * @param scrollable Whether the view should be scrollable. */ - public boolean isScrollable() { - return mScrollable; + public void setScrollable(boolean scrollable) { + this.scrollable = scrollable; } /** - * @return Returns true if this ScrollView can be scrolled + * Returns whether the view is scrollable. + * + * @return Whether the view is scrollable. */ - public boolean canScroll() { - return (canScrollHorizontally(1) || canScrollHorizontally(-1)); + public boolean isScrollable() { + return scrollable; } @Override public boolean onTouchEvent(MotionEvent e) { switch (e.getAction()) { case MotionEvent.ACTION_DOWN: - touched = true; cancel = true; startX = e.getX(); - // If we can scroll pass the event to the superclass - if (mScrollable) { + // If we can scroll, pass the event to the superclass + if (scrollable) { return super.onTouchEvent(e); } - // Only continue to handle the touch event if scrolling enabled + // Don't continue to handle the touch event if scrolling is disabled return false; case MotionEvent.ACTION_MOVE: float distance = Math.abs(e.getX() - startX); - // Currently scrolling so untruncate text - if (unTruncate && distance > MAX_CLICK_DISTANCE) { - getTouchInterceptTextView().unTruncateText(); - unTruncate = false; + // Currently scrolling, so untruncate text + if (untruncate && distance > MAX_CLICK_DISTANCE) { + getTouchInterceptTextView().untruncateText(); + untruncate = false; } case MotionEvent.ACTION_UP: - touched = false; - // The user is done interacting with the scroll view + // User is done interacting with the scroll view cancel = false; postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); lastScrollUpdate = System.currentTimeMillis(); - unTruncate = true; + untruncate = true; default: return super.onTouchEvent(e); @@ -147,12 +135,9 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { - int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); - scrollViewRect = new Rect(); - getGlobalVisibleRect(scrollViewRect); boolean touchedScrollView = @@ -164,7 +149,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } // Don't do anything with intercepted touch events if not scrollable - if (!mScrollable) { + if (!scrollable) { onTouchEvent(e); return false; } @@ -173,19 +158,12 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } /** - * @return Returns the set OnEndScrollListener - */ - public OnEndScrollListener getOnEndScrollListener() { - return onEndScrollListener; - } - - /** - * Sets an OnEndScrollListener. Only one can be set at a time. + * Sets the {@link OnEndScrollListener}. * - * @param mOnEndScrollListener The OnEndScrollListener to be set + * @param onEndScrollListener The listener to be set. */ - public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) { - this.onEndScrollListener = mOnEndScrollListener; + public void setOnEndScrollListener(OnEndScrollListener onEndScrollListener) { + this.onEndScrollListener = onEndScrollListener; } @Override @@ -198,46 +176,45 @@ public void fling(int velocityX) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - CancelClick(); + cancelClick(); if (cancelCheck) { cancel = true; } if (isFling && (Math.abs(x - oldX) < 2 || x >= getMeasuredWidth() || x == 0)) { - touched = false; - // The user is done interacting with the scroll view + // User is done interacting with the scroll view cancel = false; postDelayed(new ScrollStateHandler(), ON_END_SCROLL_DELAY); lastScrollUpdate = System.currentTimeMillis(); isFling = false; cancelCheck = false; - unTruncate = true; + untruncate = true; } } /** - * Cancels any Long Presses and inpending clicks. Used to prevent views from - * stealing touches while the user is scrolling something. + * Cancels any long presses. Used to prevent views from stealing touches while the user is + * scrolling something. */ - public void CancelClick() { + private void cancelClick() { getRootView().cancelLongPress(); this.cancelLongPress(); } - /** - * Listens for when a user has stopped interacting with the scroll view - */ - public interface OnEndScrollListener { - // Triggered when a user has stopped interacting with the scroll view + interface OnEndScrollListener { + /** + * Triggered when a user has stopped interacting with the + * {@link TouchInterceptHorizontalScrollView}. + */ void onEndScroll(); } private class ScrollStateHandler implements Runnable { - // Runs when the user has not touched the scroll view for 1 second @Override public void run() { if (!cancel) { + // Hasn't been touched for some time long currentTime = System.currentTimeMillis(); if ((currentTime - lastScrollUpdate) > ON_END_SCROLL_DELAY) { lastScrollUpdate = -1; diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java index 6bc6e0def..240cd5574 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java @@ -98,11 +98,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Mimics behavior of `android:ellipsize="end"`, except it works in a HorizontalScrollView. // Truncates the string so it doesn't get cut off in the HorizontalScrollView with an // ellipsis at the end of it. - fittedText = TextUtils.ellipsize(fittedText, + String ellipsizedText = TextUtils.ellipsize(fittedText, getPaint(), (float) textBoundsWidth, - TextUtils.TruncateAt.END).toString() - + TRUNCATED_MARKER; + TextUtils.TruncateAt.END).toString(); + fittedText = ellipsizedText + TRUNCATED_MARKER; } setText(fittedText); @@ -158,7 +158,7 @@ public boolean isTextTruncated(String text) { /** * Untruncates and sets the text. */ - public void unTruncateText() { + public void untruncateText() { String untrunucatedText = text + MARKER_UNTRUNCATED; setText(untrunucatedText); } From a0bfa37a293864cffb1e521cb15281c4dc6411a3 Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 1 Aug 2017 15:10:42 -0400 Subject: [PATCH 80/97] Removed invisible test view and changed TouchInterceptTextView to AutoTruncateTextView --- ...extView.java => AutoTruncateTextView.java} | 20 +++++++++---------- .../views/TouchInterceptFrameLayout.java | 10 ++++++++-- .../main/res/layout/activity_album_detail.xml | 7 +------ .../res/layout/activity_artist_detail.xml | 7 +------ app/src/main/res/layout/item_list.xml | 11 ++-------- 5 files changed, 22 insertions(+), 33 deletions(-) rename app/src/main/java/com/kabouzeid/gramophone/views/{TouchInterceptTextView.java => AutoTruncateTextView.java} (91%) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java similarity index 91% rename from app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java rename to app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 240cd5574..8d1e32127 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -16,9 +16,9 @@ * and puts an ellipsis at the end of it. * Must be used within a TouchInterceptHorizontalScrollview or it won't work */ -public class TouchInterceptTextView extends AppCompatTextView { +public class AutoTruncateTextView extends AppCompatTextView { - public static final String TAG = TouchInterceptTextView.class.getSimpleName(); + public static final String TAG = AutoTruncateTextView.class.getSimpleName(); private static final int RETRUNCATE_DELAY = 600; @@ -31,26 +31,26 @@ public class TouchInterceptTextView extends AppCompatTextView { private String text; private String truncatedText; - public TouchInterceptTextView(Context context) { + public AutoTruncateTextView(Context context) { super(context); init(); } - public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs) { + public AutoTruncateTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } - public TouchInterceptTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + public AutoTruncateTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { - setTag(TouchInterceptTextView.TAG); + setTag(AutoTruncateTextView.TAG); // Enable long clicking when touching the text setLongClickable(true); @@ -121,7 +121,7 @@ public void initiateTruncateText(final String originalText, final String truncat @Override public void run() { if (!originalText.endsWith(TRUNCATED_MARKER)) text = originalText; - TouchInterceptTextView.this.truncatedText = truncatedText; + AutoTruncateTextView.this.truncatedText = truncatedText; final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); @@ -134,7 +134,7 @@ public void run() { scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() { @Override public void onEndScroll() { - reTruncateScrollText(truncatedText, scrollView, TouchInterceptTextView.this); + reTruncateScrollText(truncatedText, scrollView, AutoTruncateTextView.this); } }); } @@ -182,7 +182,7 @@ public String getUntruncatedText() { */ public void reTruncateScrollText(final String truncatedString, final TouchInterceptHorizontalScrollView scrollView, - final TouchInterceptTextView textView) { + final AutoTruncateTextView textView) { ObjectAnimator.ofInt(scrollView, "scrollX", 0) .setDuration(RETRUNCATE_DELAY) .start(); @@ -195,4 +195,4 @@ public void run() { } }, RETRUNCATE_DELAY); } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index eed5d6f95..6ef26b2e0 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -2,6 +2,7 @@ import android.content.Context; import android.graphics.Rect; +import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; @@ -13,7 +14,7 @@ * * A custom {@link FrameLayout} that intercepts touch events and decides whether to consume them or * pass them on to a child {@link TouchInterceptHorizontalScrollView} and its - * {@link TouchInterceptTextView}. + * {@link AutoTruncateTextView}. * * This only needs to be used if the layout containing the {@link TouchInterceptHorizontalScrollView} * is clickable. @@ -83,7 +84,12 @@ public boolean onInterceptTouchEvent(MotionEvent e) { switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (!touchedScrollView) { - scrollView.cancelPendingInputEvents(); + // Check if we're running on Android API 19 or higher + if (Build.VERSION.SDK_INT >= 19) { + scrollView.cancelPendingInputEvents(); + } else { + scrollView.cancelLongPress(); + } return false; } diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 9ca9a5a58..7fa9c86e8 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -50,7 +50,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"> - - - diff --git a/app/src/main/res/layout/activity_artist_detail.xml b/app/src/main/res/layout/activity_artist_detail.xml index 4d6cfdaa7..392affeaf 100644 --- a/app/src/main/res/layout/activity_artist_detail.xml +++ b/app/src/main/res/layout/activity_artist_detail.xml @@ -34,11 +34,6 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - - + - Date: Tue, 1 Aug 2017 15:11:07 -0400 Subject: [PATCH 81/97] Refactored to AutoTruncateTextView --- .../views/TouchInterceptHorizontalScrollView.java | 8 ++++---- app/src/main/res/layout/item_list_single_row.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index a73b8b4fd..ccebfd096 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -13,7 +13,7 @@ * {@link TouchInterceptFrameLayout}. Allows for the layout to disable and enable scrolling in * addition to being able to know when a user is and is not interacting with the scrolling view. * - * Must have a {@link TouchInterceptTextView} as its only child. + * Must have a {@link AutoTruncateTextView} as its only child. */ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { @@ -66,10 +66,10 @@ public TouchInterceptFrameLayout getTouchInterceptFrameLayout() { } /** - * @return Returns the child {@link TouchInterceptTextView}. + * @return Returns the child {@link AutoTruncateTextView}. */ - public TouchInterceptTextView getTouchInterceptTextView() { - return (TouchInterceptTextView) this.getChildAt(0); + public AutoTruncateTextView getTouchInterceptTextView() { + return (AutoTruncateTextView) this.getChildAt(0); } /** diff --git a/app/src/main/res/layout/item_list_single_row.xml b/app/src/main/res/layout/item_list_single_row.xml index ad55608d0..a7c6a1f4b 100644 --- a/app/src/main/res/layout/item_list_single_row.xml +++ b/app/src/main/res/layout/item_list_single_row.xml @@ -69,7 +69,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"> - Date: Tue, 1 Aug 2017 15:31:32 -0400 Subject: [PATCH 82/97] fixed wrong string not truncating (I think) --- .../com/kabouzeid/gramophone/views/AutoTruncateTextView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 8d1e32127..045f95903 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -98,7 +98,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Mimics behavior of `android:ellipsize="end"`, except it works in a HorizontalScrollView. // Truncates the string so it doesn't get cut off in the HorizontalScrollView with an // ellipsis at the end of it. - String ellipsizedText = TextUtils.ellipsize(fittedText, + final String ellipsizedText = TextUtils.ellipsize(fittedText, getPaint(), (float) textBoundsWidth, TextUtils.TruncateAt.END).toString(); From e9596edaca7cbe1be6fb8575eb2242d8eda45260 Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 1 Aug 2017 19:35:07 -0400 Subject: [PATCH 83/97] Reverted invisible view removal because it turns out those are used to keep the title view visible --- app/src/main/res/layout/activity_album_detail.xml | 5 +++++ app/src/main/res/layout/activity_artist_detail.xml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 7fa9c86e8..6f0bf9984 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -62,6 +62,11 @@ + + diff --git a/app/src/main/res/layout/activity_artist_detail.xml b/app/src/main/res/layout/activity_artist_detail.xml index 392affeaf..bb87236fd 100644 --- a/app/src/main/res/layout/activity_artist_detail.xml +++ b/app/src/main/res/layout/activity_artist_detail.xml @@ -62,6 +62,11 @@ + + From caa3d2cb9891834b3b51c264823e3e4e26250cc8 Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Tue, 1 Aug 2017 20:24:29 -0400 Subject: [PATCH 84/97] Minor edits --- .../gramophone/adapter/song/SongAdapter.java | 1 - .../ui/activities/ArtistDetailActivity.java | 3 +-- .../ui/activities/PlaylistDetailActivity.java | 2 +- .../com/kabouzeid/gramophone/util/MusicUtil.java | 1 - .../gramophone/views/AutoTruncateTextView.java | 14 ++++++-------- .../views/TouchInterceptFrameLayout.java | 3 +-- .../views/TouchInterceptHorizontalScrollView.java | 2 +- app/src/main/res/layout/fragment_mini_player.xml | 3 +-- app/src/main/res/layout/item_list.xml | 4 ++-- app/src/main/res/layout/item_list_single_row.xml | 3 +-- 10 files changed, 14 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index dc5249d69..40885a551 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -111,7 +111,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (holder.title != null) { holder.title.setText(getSongTitle(song)); } - if (holder.text != null) { holder.text.setText(getSongText(song)); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java index fd9a37dcd..2f9edc2b7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java @@ -59,9 +59,8 @@ import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.Util; -import java.util.Locale; - import java.util.ArrayList; +import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java index 641a63a1b..5cc35eda7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java @@ -20,8 +20,8 @@ import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils; import com.kabouzeid.appthemehelper.ThemeStore; import com.kabouzeid.gramophone.R; -import com.kabouzeid.gramophone.adapter.song.PlaylistSongAdapter; import com.kabouzeid.gramophone.adapter.song.OrderablePlaylistSongAdapter; +import com.kabouzeid.gramophone.adapter.song.PlaylistSongAdapter; import com.kabouzeid.gramophone.adapter.song.SongAdapter; import com.kabouzeid.gramophone.dialogs.SleepTimerDialog; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/MusicUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/MusicUtil.java index 4f299565c..04687eb7b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/MusicUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/MusicUtil.java @@ -23,7 +23,6 @@ import com.kabouzeid.gramophone.loader.SongLoader; import com.kabouzeid.gramophone.model.Artist; import com.kabouzeid.gramophone.model.Playlist; -import com.kabouzeid.gramophone.model.PlaylistSong; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics; diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 045f95903..96ac73c71 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -11,10 +11,11 @@ /** * @author Lincoln (theduffmaster) * - * TextView that automatically does exactly what android:ellipsize="end" does, except this works in a TouchInterceptHorizontalScrollViews. - * Truncates the string so it doesn't get cuttoff in the TouchInterceptHorizontalScrollView + * TextView that automatically does exactly what android:ellipsize="end" does, except this works in + * a {@link TouchInterceptHorizontalScrollView}. + * Truncates the string so it doesn't get cuttoff in the {@link TouchInterceptHorizontalScrollView} * and puts an ellipsis at the end of it. - * Must be used within a TouchInterceptHorizontalScrollview or it won't work + * Must be used within a {@link TouchInterceptHorizontalScrollView}. */ public class AutoTruncateTextView extends AppCompatTextView { @@ -33,19 +34,16 @@ public class AutoTruncateTextView extends AppCompatTextView { public AutoTruncateTextView(Context context) { super(context); - init(); } public AutoTruncateTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); - init(); } public AutoTruncateTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(); } @@ -178,7 +176,7 @@ public String getUntruncatedText() { } /** - * Retruncates the text and animates it scrolling back to the start poosition. + * Retruncates the text and animates it scrolling back to the start position. */ public void reTruncateScrollText(final String truncatedString, final TouchInterceptHorizontalScrollView scrollView, @@ -195,4 +193,4 @@ public void run() { } }, RETRUNCATE_DELAY); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 6ef26b2e0..2af260ad7 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -84,8 +84,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: if (!touchedScrollView) { - // Check if we're running on Android API 19 or higher - if (Build.VERSION.SDK_INT >= 19) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { scrollView.cancelPendingInputEvents(); } else { scrollView.cancelLongPress(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index ccebfd096..f520a2716 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -228,4 +228,4 @@ public void run() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout/fragment_mini_player.xml b/app/src/main/res/layout/fragment_mini_player.xml index fe6792c3a..3e28e3a41 100644 --- a/app/src/main/res/layout/fragment_mini_player.xml +++ b/app/src/main/res/layout/fragment_mini_player.xml @@ -1,6 +1,5 @@ - - + - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_list_single_row.xml b/app/src/main/res/layout/item_list_single_row.xml index a7c6a1f4b..b316da291 100644 --- a/app/src/main/res/layout/item_list_single_row.xml +++ b/app/src/main/res/layout/item_list_single_row.xml @@ -78,7 +78,6 @@ - - \ No newline at end of file + From a617668ed667bd3fcf8ea25736d3ff58a37fffa8 Mon Sep 17 00:00:00 2001 From: Duffman Date: Wed, 2 Aug 2017 00:44:34 -0400 Subject: [PATCH 85/97] Possibly fixed wrong re truncating text --- .../com/kabouzeid/gramophone/views/AutoTruncateTextView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 96ac73c71..dfd4c2c3a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -189,7 +189,7 @@ public void reTruncateScrollText(final String truncatedString, handler.postDelayed(new Runnable() { @Override public void run() { - textView.setText(truncatedString); + if(getText().toString().endsWith(MARKER_UNTRUNCATED)) textView.setText(truncatedString); } }, RETRUNCATE_DELAY); } From ac46c3021abd6d15875a90c65f4afd2d55f5040b Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Wed, 2 Aug 2017 22:55:58 -0400 Subject: [PATCH 86/97] Possibly better fix for wrong text --- .../gramophone/views/AutoTruncateTextView.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index dfd4c2c3a..ec6979025 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -115,24 +115,24 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { * @param truncatedText The string after truncation */ public void initiateTruncateText(final String originalText, final String truncatedText) { + if (!originalText.endsWith(TRUNCATED_MARKER)) { + text = originalText; + } + this.truncatedText = truncatedText; + + final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); post(new Runnable() { @Override public void run() { - if (!originalText.endsWith(TRUNCATED_MARKER)) text = originalText; - AutoTruncateTextView.this.truncatedText = truncatedText; - - final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); - if (isTextTruncated(truncatedText)) { if (originalText.equals(truncatedText) && !truncatedText.endsWith(MARKER_UNTRUNCATED)) { scrollView.setScrollable(false); } else { scrollView.setScrollable(true); - scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() { @Override public void onEndScroll() { - reTruncateScrollText(truncatedText, scrollView, AutoTruncateTextView.this); + retruncateScrollText(truncatedText, scrollView, AutoTruncateTextView.this); } }); } @@ -178,7 +178,7 @@ public String getUntruncatedText() { /** * Retruncates the text and animates it scrolling back to the start position. */ - public void reTruncateScrollText(final String truncatedString, + public void retruncateScrollText(final String truncatedString, final TouchInterceptHorizontalScrollView scrollView, final AutoTruncateTextView textView) { ObjectAnimator.ofInt(scrollView, "scrollX", 0) @@ -189,7 +189,7 @@ public void reTruncateScrollText(final String truncatedString, handler.postDelayed(new Runnable() { @Override public void run() { - if(getText().toString().endsWith(MARKER_UNTRUNCATED)) textView.setText(truncatedString); + textView.setText(truncatedString); } }, RETRUNCATE_DELAY); } From 4237452b1afd6d61cc8a3a49aa5a071f886ebcd9 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 7 Aug 2017 12:25:58 -0400 Subject: [PATCH 87/97] Fixed the occasional long click on scroll --- .../com/kabouzeid/gramophone/views/AutoTruncateTextView.java | 2 +- .../gramophone/views/TouchInterceptHorizontalScrollView.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index ec6979025..4cc104bb3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -56,7 +56,7 @@ private void init() { // Blocks clicks from passing through this view setClickable(true); - // Use this instead of maxlines + // Have to use this instead of maxlines in order for scrolling to work setSingleLine(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index f520a2716..655c2651e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -57,6 +57,7 @@ private void init() { lastScrollUpdate = -1; scrollable = true; scrollViewRect = new Rect(); + setLongClickable(false); setTag(TouchInterceptHorizontalScrollView.TAG); setHorizontalScrollBarEnabled(false); } From a24bd988bd1279183964a80c2e02eca4c9e3bfd9 Mon Sep 17 00:00:00 2001 From: Duffman Date: Mon, 7 Aug 2017 12:34:40 -0400 Subject: [PATCH 88/97] Don't need this anymore --- .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 1 - .../gramophone/views/TouchInterceptHorizontalScrollView.java | 1 - 2 files changed, 2 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 2af260ad7..df1ad2c6e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -132,6 +132,5 @@ public boolean onInterceptTouchEvent(MotionEvent e) { */ private void cancelClick() { this.cancelLongPress(); - scrollView.cancelLongPress(); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 655c2651e..5d70dd442 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -200,7 +200,6 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) { */ private void cancelClick() { getRootView().cancelLongPress(); - this.cancelLongPress(); } interface OnEndScrollListener { From b2971b3b626965b381daca8938f565e6bf8694bc Mon Sep 17 00:00:00 2001 From: Duffman Date: Tue, 8 Aug 2017 18:21:31 -0400 Subject: [PATCH 89/97] Code cleanup --- .../gramophone/views/TouchInterceptFrameLayout.java | 10 +--------- .../views/TouchInterceptHorizontalScrollView.java | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index df1ad2c6e..936e923ad 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -104,7 +104,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { isTap = false; - cancelClick(); + this.cancelLongPress(); } } break; @@ -125,12 +125,4 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } return false; } - - /** - * Cancels any long presses. Used to prevent views from stealing touches while the user is - * scrolling something. - */ - private void cancelClick() { - this.cancelLongPress(); - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 5d70dd442..dfa31df47 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -177,7 +177,7 @@ public void fling(int velocityX) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - cancelClick(); + getRootView().cancelLongPress(); if (cancelCheck) { cancel = true; @@ -194,14 +194,6 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) { } } - /** - * Cancels any long presses. Used to prevent views from stealing touches while the user is - * scrolling something. - */ - private void cancelClick() { - getRootView().cancelLongPress(); - } - interface OnEndScrollListener { /** * Triggered when a user has stopped interacting with the From 0c68210b2784a9667d9a41da945e5cc242f09b33 Mon Sep 17 00:00:00 2001 From: Duffman Date: Wed, 9 Aug 2017 13:02:15 -0400 Subject: [PATCH 90/97] Reverted back to old method of checking for retruncate for performance reasons and other performance improvements After testing I found that finding the scrollview on the main thread sometimes slowed things down. --- .../views/AutoTruncateTextView.java | 12 ++++------ .../views/TouchInterceptFrameLayout.java | 24 ++++++++++++++++++- .../TouchInterceptHorizontalScrollView.java | 11 ++++++++- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 4cc104bb3..b110fc641 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -120,10 +120,10 @@ public void initiateTruncateText(final String originalText, final String truncat } this.truncatedText = truncatedText; - final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); post(new Runnable() { @Override public void run() { + final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); if (isTextTruncated(truncatedText)) { if (originalText.equals(truncatedText) && !truncatedText.endsWith(MARKER_UNTRUNCATED)) { scrollView.setScrollable(false); @@ -132,7 +132,7 @@ public void run() { scrollView.setOnEndScrollListener(new TouchInterceptHorizontalScrollView.OnEndScrollListener() { @Override public void onEndScroll() { - retruncateScrollText(truncatedText, scrollView, AutoTruncateTextView.this); + retruncateScrollText(truncatedText); } }); } @@ -178,10 +178,8 @@ public String getUntruncatedText() { /** * Retruncates the text and animates it scrolling back to the start position. */ - public void retruncateScrollText(final String truncatedString, - final TouchInterceptHorizontalScrollView scrollView, - final AutoTruncateTextView textView) { - ObjectAnimator.ofInt(scrollView, "scrollX", 0) + public void retruncateScrollText(final String truncatedText) { + ObjectAnimator.ofInt(getTouchInterceptHorizontalScrollView(), "scrollX", 0) .setDuration(RETRUNCATE_DELAY) .start(); @@ -189,7 +187,7 @@ public void retruncateScrollText(final String truncatedString, handler.postDelayed(new Runnable() { @Override public void run() { - textView.setText(truncatedString); + if(getText().toString().endsWith(MARKER_UNTRUNCATED)) setText(truncatedText); } }, RETRUNCATE_DELAY); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 936e923ad..8ba69604b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -6,6 +6,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; @@ -29,6 +30,7 @@ public class TouchInterceptFrameLayout extends FrameLayout { private Rect scrollViewRect; private float startX; + private float startY; private boolean isTap; public TouchInterceptFrameLayout(@NonNull Context context) { @@ -70,6 +72,8 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { + Log.d("Frame Layout Touch",e.toString()); + int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -93,6 +97,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } startX = e.getX(); + startY = e.getY(); isTap = true; onTouchEvent(e); break; @@ -100,11 +105,19 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_MOVE: if (touchedScrollView) { float distance = Math.abs(e.getX() - startX); + float verticalDistance = Math.abs(e.getY() - startY); + + //Scrolling list: cancel long press + if(verticalDistance > MAX_CLICK_DISTANCE){ + Log.d("Vertical","True"); + isTap = false; + cancelLongClick(); + } // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { isTap = false; - this.cancelLongPress(); + cancelLongClick(); } } break; @@ -125,4 +138,13 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } return false; } + + /** + * Cancels any long presses. Used to prevent views from stealing touches while the user is + * scrolling something. + */ + private void cancelLongClick() { + scrollView.cancelLongPress(); + this.cancelLongPress(); + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index dfa31df47..b491e81b2 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -177,7 +177,7 @@ public void fling(int velocityX) { protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); - getRootView().cancelLongPress(); + cancelLongClick(); if (cancelCheck) { cancel = true; @@ -194,6 +194,15 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) { } } + /** + * Cancels any long presses. Used to prevent views from stealing touches while the user is + * scrolling something. + */ + private void cancelLongClick() { + getRootView().cancelLongPress(); + this.cancelLongPress(); + } + interface OnEndScrollListener { /** * Triggered when a user has stopped interacting with the From 6f600b6d301ffda0a693c451fa33083127fd04ba Mon Sep 17 00:00:00 2001 From: Duffman Date: Wed, 9 Aug 2017 13:33:21 -0400 Subject: [PATCH 91/97] Better way of canceling unwarranted long clicks --- .../views/TouchInterceptFrameLayout.java | 26 ++++++++++--------- .../TouchInterceptHorizontalScrollView.java | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 8ba69604b..798e0a782 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -6,7 +6,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.widget.FrameLayout; @@ -30,7 +29,6 @@ public class TouchInterceptFrameLayout extends FrameLayout { private Rect scrollViewRect; private float startX; - private float startY; private boolean isTap; public TouchInterceptFrameLayout(@NonNull Context context) { @@ -72,7 +70,6 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - Log.d("Frame Layout Touch",e.toString()); int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -97,7 +94,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } startX = e.getX(); - startY = e.getY(); isTap = true; onTouchEvent(e); break; @@ -105,14 +101,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case MotionEvent.ACTION_MOVE: if (touchedScrollView) { float distance = Math.abs(e.getX() - startX); - float verticalDistance = Math.abs(e.getY() - startY); - - //Scrolling list: cancel long press - if(verticalDistance > MAX_CLICK_DISTANCE){ - Log.d("Vertical","True"); - isTap = false; - cancelLongClick(); - } // Scrolling the view: cancel event to prevent long press if (distance > MAX_CLICK_DISTANCE) { @@ -123,6 +111,13 @@ public boolean onInterceptTouchEvent(MotionEvent e) { break; case MotionEvent.ACTION_CANCEL: + //Long click cancels should have an x coordinate of 0 during ACTION_CANCEL + //If it does not have an x coordinate of 0 then it is not a long click so cancel it + if(e.getX() != 0){ + cancelLongClick(); + } + break; + case MotionEvent.ACTION_UP: if (touchedScrollView && isTap) { onTouchEvent(e); @@ -134,6 +129,13 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } if (touchedScrollView) { + //Long click cancels should have an x coordinate of 0 during ACTION_CANCEL + //If it does not have an x coordinate of 0 then it is not a long click so cancel it + if(e.getAction() == MotionEvent.ACTION_CANCEL){ + if(e.getX() != 0 ){ + cancelLongClick(); + } + } onTouchEvent(e); } return false; diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index b491e81b2..5ec507df6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -136,6 +136,7 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { + int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); From 1800182c3e3d8de4101840fac5a17436696ed9a4 Mon Sep 17 00:00:00 2001 From: Duffman Date: Wed, 9 Aug 2017 13:35:15 -0400 Subject: [PATCH 92/97] Code cleanup --- .../kabouzeid/gramophone/views/TouchInterceptFrameLayout.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 798e0a782..4e6174c4a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -122,7 +122,6 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (touchedScrollView && isTap) { onTouchEvent(e); } - this.requestDisallowInterceptTouchEvent(false); break; } return false; @@ -132,7 +131,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { //Long click cancels should have an x coordinate of 0 during ACTION_CANCEL //If it does not have an x coordinate of 0 then it is not a long click so cancel it if(e.getAction() == MotionEvent.ACTION_CANCEL){ - if(e.getX() != 0 ){ + if(e.getX() != 0){ cancelLongClick(); } } From f09c1452224c321ef826c4c8879dde953479c7ca Mon Sep 17 00:00:00 2001 From: Duffman Date: Thu, 10 Aug 2017 02:53:28 -0400 Subject: [PATCH 93/97] Addressed invalid pointer id error --- .../TouchInterceptHorizontalScrollView.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index 5ec507df6..f2df7b092 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -35,6 +35,9 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private boolean cancel; private boolean cancelCheck; + // ID of the active pointer. + private int activePointerId; + // Whether to untruncate the text in the TouchInterceptTextView private boolean untruncate; @@ -140,6 +143,20 @@ public boolean onInterceptTouchEvent(MotionEvent e) { int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); + // Check to see if it's a valid pointerID. If it's invalid a long click is triggered. This + // stops that. + switch (e.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + activePointerId = e.getPointerId(0); + break; + case MotionEvent.ACTION_MOVE: { + if (e.findPointerIndex(activePointerId) == -1) { + cancelLongClick(); + } + break; + } + } + getGlobalVisibleRect(scrollViewRect); boolean touchedScrollView = From 8bef5ccc843303045b2cef5de93581fde002d60d Mon Sep 17 00:00:00 2001 From: Duffman Date: Thu, 10 Aug 2017 02:58:26 -0400 Subject: [PATCH 94/97] Reverted scrollview because that fixes the occasional unwarranted text retruncate --- .../com/kabouzeid/gramophone/views/AutoTruncateTextView.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index b110fc641..45c53fd0d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -119,11 +119,12 @@ public void initiateTruncateText(final String originalText, final String truncat text = originalText; } this.truncatedText = truncatedText; + final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); post(new Runnable() { @Override public void run() { - final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); + if (isTextTruncated(truncatedText)) { if (originalText.equals(truncatedText) && !truncatedText.endsWith(MARKER_UNTRUNCATED)) { scrollView.setScrollable(false); From 3b3104e8e74fcd4b0265a0563b818302e22c3122 Mon Sep 17 00:00:00 2001 From: Eugene Cheung Date: Sat, 12 Aug 2017 10:26:07 -0400 Subject: [PATCH 95/97] Use animator listener to retruncate text instead of timeout handler --- .../views/AutoTruncateTextView.java | 52 +++++++++++++------ .../views/TouchInterceptFrameLayout.java | 18 +++---- .../TouchInterceptHorizontalScrollView.java | 11 ++-- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 45c53fd0d..196d86e01 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -1,8 +1,8 @@ package com.kabouzeid.gramophone.views; +import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; -import android.os.Handler; import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; import android.text.TextUtils; @@ -75,9 +75,9 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( } /** - * The text undergoes truncation here. {@link #onMeasure} is immediately called after - * {@link #setText} and has a reference to the parent's bounds. The bounds are used for setting - * the length of the truncated text, ensuring that the text does not get visibly cut off. + * The text undergoes truncation here. This is immediately called after {@link #setText} and has + * a reference to the parent's bounds. The bounds are used for setting the length of the + * truncated text, ensuring that the text does not get visibly cut off. */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @@ -119,13 +119,12 @@ public void initiateTruncateText(final String originalText, final String truncat text = originalText; } this.truncatedText = truncatedText; - final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); + final TouchInterceptHorizontalScrollView scrollView = getTouchInterceptHorizontalScrollView(); post(new Runnable() { @Override public void run() { - - if (isTextTruncated(truncatedText)) { + if (isTruncated(truncatedText)) { if (originalText.equals(truncatedText) && !truncatedText.endsWith(MARKER_UNTRUNCATED)) { scrollView.setScrollable(false); } else { @@ -150,10 +149,14 @@ public void onEndScroll() { * @param text The string to check. * @return Returns whether the text has been truncated or not. */ - public boolean isTextTruncated(String text) { + public boolean isTruncated(String text) { return text.endsWith("…" + TRUNCATED_MARKER); } + public boolean isUntruncated() { + return getText().toString().endsWith(MARKER_UNTRUNCATED); + } + /** * Untruncates and sets the text. */ @@ -177,19 +180,34 @@ public String getUntruncatedText() { } /** - * Retruncates the text and animates it scrolling back to the start position. + * Re-truncates the text and animates it scrolling back to the start position. */ public void retruncateScrollText(final String truncatedText) { - ObjectAnimator.ofInt(getTouchInterceptHorizontalScrollView(), "scrollX", 0) - .setDuration(RETRUNCATE_DELAY) - .start(); + Animator animator = ObjectAnimator + .ofInt(getTouchInterceptHorizontalScrollView(), "scrollX", 0) + .setDuration(RETRUNCATE_DELAY); - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { + animator.addListener(new Animator.AnimatorListener() { @Override - public void run() { - if(getText().toString().endsWith(MARKER_UNTRUNCATED)) setText(truncatedText); + public void onAnimationStart(Animator animator) { + } + + @Override + public void onAnimationEnd(Animator animator) { + if (isUntruncated()) { + setText(truncatedText); + } } - }, RETRUNCATE_DELAY); + + @Override + public void onAnimationCancel(Animator animator) { + } + + @Override + public void onAnimationRepeat(Animator animator) { + } + }); + + animator.start(); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java index 4e6174c4a..ad16be528 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptFrameLayout.java @@ -70,7 +70,6 @@ public TouchInterceptHorizontalScrollView getTouchInterceptHorizontalScrollView( */ @Override public boolean onInterceptTouchEvent(MotionEvent e) { - int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); @@ -111,9 +110,9 @@ public boolean onInterceptTouchEvent(MotionEvent e) { break; case MotionEvent.ACTION_CANCEL: - //Long click cancels should have an x coordinate of 0 during ACTION_CANCEL - //If it does not have an x coordinate of 0 then it is not a long click so cancel it - if(e.getX() != 0){ + // Long click cancels should have an x coordinate of 0 during ACTION_CANCEL. + // If it does not, then it is not a long click so cancel it. + if (e.getX() != 0) { cancelLongClick(); } break; @@ -124,16 +123,15 @@ public boolean onInterceptTouchEvent(MotionEvent e) { } break; } + return false; } if (touchedScrollView) { - //Long click cancels should have an x coordinate of 0 during ACTION_CANCEL - //If it does not have an x coordinate of 0 then it is not a long click so cancel it - if(e.getAction() == MotionEvent.ACTION_CANCEL){ - if(e.getX() != 0){ - cancelLongClick(); - } + // Long click cancels should have an x coordinate of 0 during ACTION_CANCEL. + // If it does not, then it is not a long click so cancel it. + if (e.getAction() == MotionEvent.ACTION_CANCEL && e.getX() != 0) { + cancelLongClick(); } onTouchEvent(e); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java index f2df7b092..12447a1c8 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/TouchInterceptHorizontalScrollView.java @@ -35,7 +35,7 @@ public class TouchInterceptHorizontalScrollView extends HorizontalScrollView { private boolean cancel; private boolean cancelCheck; - // ID of the active pointer. + // ID of the active pointer private int activePointerId; // Whether to untruncate the text in the TouchInterceptTextView @@ -139,22 +139,21 @@ public boolean onTouchEvent(MotionEvent e) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { - int x = Math.round(e.getRawX()); int y = Math.round(e.getRawY()); - // Check to see if it's a valid pointerID. If it's invalid a long click is triggered. This - // stops that. + // Check to see if it's a valid pointerID. + // If it's invalid, a long click is triggered. This stops that. switch (e.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: activePointerId = e.getPointerId(0); break; - case MotionEvent.ACTION_MOVE: { + + case MotionEvent.ACTION_MOVE: if (e.findPointerIndex(activePointerId) == -1) { cancelLongClick(); } break; - } } getGlobalVisibleRect(scrollViewRect); From 9eb14b687bea6b5ddbcab865d6b2c9e4bf7f6e77 Mon Sep 17 00:00:00 2001 From: Duffman Date: Sat, 12 Aug 2017 19:11:43 -0400 Subject: [PATCH 96/97] Added further documentation --- .../kabouzeid/gramophone/views/AutoTruncateTextView.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index 196d86e01..bb5839573 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -149,10 +149,15 @@ public void onEndScroll() { * @param text The string to check. * @return Returns whether the text has been truncated or not. */ - public boolean isTruncated(String text) { + public boolean isTruncated(final String text) { return text.endsWith("…" + TRUNCATED_MARKER); } + /** + * Checks whether a string was untruncated at some point. + * + * @return Returns whether the current text has been untruncated or not. + */ public boolean isUntruncated() { return getText().toString().endsWith(MARKER_UNTRUNCATED); } From 78890be76a6ebeeefe6f8ef37c90eec1494098ec Mon Sep 17 00:00:00 2001 From: Duffman Date: Sun, 13 Aug 2017 21:22:43 -0400 Subject: [PATCH 97/97] Corrected code inconsistency --- .../com/kabouzeid/gramophone/views/AutoTruncateTextView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java index bb5839573..86ff3124d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/AutoTruncateTextView.java @@ -116,7 +116,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { */ public void initiateTruncateText(final String originalText, final String truncatedText) { if (!originalText.endsWith(TRUNCATED_MARKER)) { - text = originalText; + this.text = originalText; } this.truncatedText = truncatedText;