Skip to content

Commit

Permalink
Merge pull request #11 from techery/feature/scroll_controller_addition
Browse files Browse the repository at this point in the history
Feature :: scroll controller addition
  • Loading branch information
almozavr authored Jul 26, 2017
2 parents 6b1d89f + efc7dc7 commit 62d4c05
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 15 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ seekBar.getHintDelegate()
</style>
```

**5)** Optionally if inside ScrollView

Use `ProgressHintScrollController` to hide & show popup properly on scrolling.
See [Sample's Activity](https://github.com/techery/progresshint/blob/master/sample/src/main/java/com/example/progresshint/ScrollActivity.java) for details

## Credits
Thanks to
+ @moondroid for [inspiration](https://github.com/moondroid/SeekBarHint)
Expand Down
3 changes: 3 additions & 0 deletions library-addition/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ android {
dependencies {
compile project(':library')
compile 'com.h6ah4i.android.widget.verticalseekbar:verticalseekbar:0.7.2'
compile "com.android.support:support-core-ui:$rootProject.ext.supportPackageVersion"
compile "com.android.support:appcompat-v7:$rootProject.ext.supportPackageVersion"
compile "com.android.support:animated-vector-drawable:$rootProject.ext.supportPackageVersion"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;
import io.techery.progresshint.ProgressHintDelegate;

Expand Down Expand Up @@ -38,4 +39,15 @@ private int getHorizontalOffset(int progress) {
private int getVerticalOffset() {
return -(mSeekBar.getHeight() + mPopupView.getMeasuredHeight() + mPopupOffset);
}

///////////////////////////////////////////////////////////////////////////
// Visibility Helper
///////////////////////////////////////////////////////////////////////////

@Override public boolean isWidgetFullyVisible(View container) {
int relativeTop = ViewUtil.getRelativeTop(mSeekBar, container);
return (container.getScrollY() < relativeTop - mPopupView.getHeight() - mPopupOffset) // top edge
&& (container.getHeight() + container.getScrollY() - mPopupView.getHeight() - mPopupOffset
> relativeTop - mSeekBar.getHeight()); // bottom edge
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.techery.progresshint.addition;

import android.view.View;
import android.view.ViewTreeObserver;
import io.techery.progresshint.ProgressHintDelegate;
import io.techery.progresshint.ProgressHintDelegate.SeekBarHintDelegateHolder;

public class ProgressHintScrollController implements ViewTreeObserver.OnScrollChangedListener {

private final View container;
private final ProgressHintDelegate delegate;

public static ProgressHintScrollController register(View container, SeekBarHintDelegateHolder holder) {
ProgressHintScrollController controller = new ProgressHintScrollController(container, holder);
container.getViewTreeObserver().addOnScrollChangedListener(controller);
return controller;
}

ProgressHintScrollController(View container, SeekBarHintDelegateHolder holder) {
this.container = container;
this.delegate = holder.getHintDelegate();
}

@Override public void onScrollChanged() {
if (delegate.isPopupVisible()) {
if (!delegate.isWidgetFullyVisible(container)) delegate.hidePopup();
} else if (delegate.isPopupAlwaysShown() && delegate.isWidgetFullyVisible(container)) {
delegate.showPopup();
}
}

public void dispose() {
container.getViewTreeObserver().removeOnScrollChangedListener(this);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.support.annotation.IntDef;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;
import io.techery.progresshint.ProgressHintDelegate;
import java.lang.annotation.Retention;
Expand Down Expand Up @@ -71,4 +72,33 @@ private int getVerticalOffset(int progress) {

private static final int CW = 1;
private static final int CCW = 0;

///////////////////////////////////////////////////////////////////////////
// Visibility Helper
///////////////////////////////////////////////////////////////////////////

@Override public boolean isWidgetFullyVisible(View container) {
int relativeTop = ViewUtil.getRelativeTop(mSeekBar, container);
int followPosition = getFollowPosition(getPopupStyle() == POPUP_FOLLOW ? mSeekBar.getProgress() : mSeekBar.getMax() / 2);
//
boolean fitsTop;
boolean fitsBottom;
switch (getOrientation()) {
case CW:
fitsTop =
relativeTop + followPosition + mSeekBar.getPaddingLeft() - mPopupView.getHeight() / 2 > container.getScrollY();
fitsBottom = container.getHeight() + container.getScrollY() >
relativeTop + followPosition + mSeekBar.getPaddingRight() + mPopupView.getHeight() / 2;
break;
case CCW:
fitsTop = relativeTop + (mSeekBar.getWidth() - followPosition) - mPopupView.getHeight() > container.getScrollY();
fitsBottom = container.getHeight() + container.getScrollY() + (followPosition + mSeekBar.getPaddingLeft()) >
relativeTop + mSeekBar.getWidth() + mPopupView.getHeight() / 2;
break;
default:
throw new IllegalStateException("This widget orientation is not supported");
}
//
return fitsTop && fitsBottom;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.techery.progresshint.addition;

import android.view.View;

final class ViewUtil {

static int getRelativeTop(View view, View container) {
if (view.getParent() == container) return view.getTop();
else return view.getTop() + getRelativeTop((View) view.getParent(), container);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import io.techery.progresshint.ProgressHintDelegate;
import io.techery.progresshint.addition.HorizontalProgressHintDelegate;

public class SeekBar extends android.widget.SeekBar implements
ProgressHintDelegate.SeekBarHintDelegateHolder {
public class SeekBar extends android.support.v7.widget.AppCompatSeekBar implements ProgressHintDelegate.SeekBarHintDelegateHolder {

private ProgressHintDelegate hintDelegate;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import io.techery.progresshint.ProgressHintDelegate.SeekBarHintDelegateHolder;
import io.techery.progresshint.addition.VerticalProgressHintDelegate;

public class VerticalSeekBar extends com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar
implements SeekBarHintDelegateHolder {
public class VerticalSeekBar extends com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar implements SeekBarHintDelegateHolder {

private ProgressHintDelegate hintDelegate;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ private void checkInitialState() {
protected abstract PointF getHintDragCoordinates(MotionEvent event);

public void showPopup() {
handler.removeCallbacksAndMessages(null);
handler.post(new Runnable() {
@Override public void run() {
showPopupInternally();
Expand All @@ -176,10 +177,20 @@ public void hidePopup() {
if (mPopup.isShowing()) mPopup.dismiss();
}

public boolean isPopupVisible() {
return mPopup.isShowing();
}

public abstract boolean isWidgetFullyVisible(View container);

///////////////////////////////////////////////////////////////////////////
// Public api
///////////////////////////////////////////////////////////////////////////

public SeekBar getSeekBar() {
return mSeekBar;
}

@LayoutRes public int getPopupLayout() {
return mPopupLayout;
}
Expand Down
1 change: 0 additions & 1 deletion sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,4 @@ dependencies {
compile 'com.jakewharton:butterknife:8.7.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'

compile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
}
14 changes: 6 additions & 8 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.progresshint"
>
package="com.example.progresshint">

<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
>
android:name=".App"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
>
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ScrollActivity"/>
</application>

</manifest>
</manifest>
2 changes: 0 additions & 2 deletions sample/src/main/java/com/example/progresshint/App.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.example.progresshint;

import android.app.Application;
import com.squareup.leakcanary.LeakCanary;

public class App extends Application {

@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.progresshint;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
Expand Down Expand Up @@ -51,6 +52,9 @@ public class MainActivity extends AppCompatActivity {
case R.id.action_follow:
style = POPUP_FOLLOW;
break;
case R.id.action_open_scroll:
startActivity(new Intent(this, ScrollActivity.class));
return true;
}
for (SeekBarHintDelegateHolder seekBar : seekBars) {
seekBar.getHintDelegate().setPopupStyle(style);
Expand Down
30 changes: 30 additions & 0 deletions sample/src/main/java/com/example/progresshint/ScrollActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.progresshint;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.techery.progresshint.addition.ProgressHintScrollController;
import io.techery.progresshint.addition.widget.SeekBar;
import io.techery.progresshint.addition.widget.VerticalSeekBar;

public class ScrollActivity extends AppCompatActivity {

@BindView(R.id.scroll_container) View scrollView;
@BindView(R.id.seekbar1) SeekBar seekBar1;
@BindView(R.id.seekbar2) VerticalSeekBar seekBar2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scroll);
ButterKnife.bind(this);

seekBar1.setProgress(10);
seekBar2.setProgress(20);

ProgressHintScrollController.register(scrollView, seekBar1);
ProgressHintScrollController.register(scrollView, seekBar2);
}
}
80 changes: 80 additions & 0 deletions sample/src/main/res/layout/activity_scroll.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<View
android:layout_width="wrap_content"
android:layout_height="200dp"
android:background="#58961e"
/>

<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scroll_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>

<View
android:layout_width="wrap_content"
android:layout_height="200dp"
android:background="#1e3e96"
/>

<io.techery.progresshint.addition.widget.SeekBar
android:id="@+id/seekbar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:popupAlwaysShown="true"
app:popupStyle="follow"
/>

<View
android:layout_width="wrap_content"
android:layout_height="200dp"
android:background="#961e8e"
/>

<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_gravity="left"
app:layout_marginBottomPercent="10%"
app:layout_marginLeftPercent="30%"
app:layout_marginTopPercent="10%"
>

<io.techery.progresshint.addition.widget.VerticalSeekBar
android:id="@+id/seekbar2"
android:layout_width="0dp"
android:layout_height="0dp"
android:splitTrack="false"
app:popupAlwaysShown="true"
app:popupStyle="fixed"
app:seekBarRotation="CW90"
/>
<!-- Rotation: CW90 or CW270 -->
</com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper>

<View
android:layout_width="wrap_content"
android:layout_height="500dp"
android:background="#ba3720"
/>

</LinearLayout>
</ScrollView>

</LinearLayout>
4 changes: 4 additions & 0 deletions sample/src/main/res/menu/menu_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@
<item android:id="@+id/action_follow"
android:title="@string/action_follow"
app:showAsAction="never" />

<item android:id="@+id/action_open_scroll"
android:title="@string/action_open_scroll"
app:showAsAction="never" />
</menu>
1 change: 1 addition & 0 deletions sample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

<string name="action_follow">Follow</string>
<string name="action_fixed">Fixed</string>
<string name="action_open_scroll">Check Scroll</string>
</resources>

0 comments on commit 62d4c05

Please sign in to comment.