Skip to content

Commit

Permalink
Merge pull request #12 from parkin1/stuckShadow
Browse files Browse the repository at this point in the history
added shadow feature below the stuck view.
  • Loading branch information
emilsjolander committed Jan 29, 2014
2 parents 131b9c1 + 5f1335c commit fc64dbb
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 6 deletions.
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ So you go from this:
to this:
```xml
<StickyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent" android:layout_width="match_parent">
android:layout_height="match_parent" android:layout_width="match_parent"
android:id="@+id/sticky_scroll">
<!-- scroll view child goes here -->
</StickyScrollView>
```

As with a regular `ScrollView` you are only allowed one child. But that child can contain any number of children. It is these children or any of their children that can be tagged as a sticky view. If you want t view to stick to the top when you scroll passed it add a `sticky` tag with the `android:tag` attribute to it like this:
```xml
<StickyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sticky_scroll"
android:layout_height="match_parent" android:layout_width="match_parent">

<LinearLayout
Expand All @@ -55,3 +57,23 @@ As with a regular `ScrollView` you are only allowed one child. But that child ca
There are also two additional flags that can be set on views that were added to optimize performance for the most usual cases. If the view you want to stick either has transparency or does not have a constant representation than you must supply one or both of the following flags. `-hastransparancy` for views that have transparancy and `-nonconstant` for views that will change appearance during there sticky time (examples are buttons with pressed states as well as progress spinners).

So this ends up with 4 different ways to tag a view as sticky resulting is slightly different behaviour `android:tag="sticky"` `android:tag="sticky-hastransparancy"` `android:tag="sticky-nonconstant"` and `android:tag="sticky-hastransparancy-nonconstant"`.

If you want to add a shadow drawable below the stuck items, you must declare a namespace to find the shadow attributes `xmlns:whatever="http://schemas.android.com/apk/res-auto"`. Usually you do this in the root layout element in you layout.xml file. You can then specify the shadow drawable with `whatever:stuckShadowDrawable=""` and the shadow height with `whatever:stuckShadowHeight=""` in xml. Note that when left unspecified, the default shadow height is 10dip.
```xml
<StickyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:whatever="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent" android:layout_width="match_parent"
android:id="@+id/sticky_scroll"
whatever:stuckShadowDrawable="@drawable/sticky_shadow_default"
whatever:stuckShadowHeight="50dip" >
<!-- scroll view child goes here -->
</StickyScrollView>
```

These shadow height and drawable can also be set programatically. Note that, unlike the xml attribute, `setShadowHeight(pixels)` only takes the values in pixels.
```java
StickyScrollView stickyScroll = (StickyScrollView) findViewById(R.id.sticky_scroll);
stickyScroll.setShadowDrawable(getResources().getDrawable(
R.drawable.shadow_drawable));
stickyScroll.setShadowHeight(50); // in pixels
```
10 changes: 10 additions & 0 deletions library/res/values/attrs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="StickyScrollView">
<attr name="stuckShadowHeight" format="dimension" />
<attr name="stuckShadowDrawable" format="reference" />
</declare-styleable>

</resources>

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import java.util.ArrayList;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
Expand Down Expand Up @@ -33,6 +35,11 @@ public class StickyScrollView extends ScrollView {
* Flag for views that have aren't fully opaque
*/
public static final String FLAG_HASTRANSPARANCY = "-hastransparancy";

/**
* Default height of the shadow peeking out below the stuck view.
*/
private static final int DEFAULT_SHADOW_HEIGHT = 10; // dp;

private ArrayList<View> stickyViews;
private View currentlyStickingView;
Expand All @@ -42,6 +49,9 @@ public class StickyScrollView extends ScrollView {
private boolean clippingToPadding;
private boolean clipToPaddingHasBeenSet;

private int mShadowHeight;
private Drawable mShadowDrawable;

private final Runnable invalidateRunnable = new Runnable() {

@Override
Expand All @@ -68,7 +78,40 @@ public StickyScrollView(Context context, AttributeSet attrs) {
public StickyScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();



TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.StickyScrollView, defStyle, 0);

final float density = context.getResources().getDisplayMetrics().density;
int defaultShadowHeightInPix = (int) (DEFAULT_SHADOW_HEIGHT * density + 0.5f);

mShadowHeight = a.getDimensionPixelSize(
R.styleable.StickyScrollView_stuckShadowHeight,
defaultShadowHeightInPix);

int shadowDrawableRes = a.getResourceId(
R.styleable.StickyScrollView_stuckShadowDrawable, -1);

if (shadowDrawableRes != -1) {
mShadowDrawable = context.getResources().getDrawable(
shadowDrawableRes);
}

a.recycle();

}

/**
* Sets the height of the shadow drawable in pixels.
*
* @param height
*/
public void setShadowHeight(int height) {
mShadowHeight = height;
}


public void setup(){
stickyViews = new ArrayList<View>();
Expand Down Expand Up @@ -161,8 +204,21 @@ protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(currentlyStickingView != null){
canvas.save();
canvas.translate(getPaddingLeft() + stickyViewLeftOffset,
getScrollY() + stickyViewTopOffset + (clippingToPadding ? getPaddingTop() : 0));
canvas.translate(getPaddingLeft() + stickyViewLeftOffset, getScrollY() + stickyViewTopOffset + (clippingToPadding ? getPaddingTop() : 0));

canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0),
getWidth() - stickyViewLeftOffset,
currentlyStickingView.getHeight() + mShadowHeight + 1);

if (mShadowDrawable != null) {
int left = 0;
int right = currentlyStickingView.getWidth();
int top = currentlyStickingView.getHeight();
int bottom = currentlyStickingView.getHeight() + mShadowHeight;
mShadowDrawable.setBounds(left, top, right, bottom);
mShadowDrawable.draw(canvas);
}

canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), getWidth(), currentlyStickingView.getHeight());
if(getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARANCY)){
showView(currentlyStickingView);
Expand Down
4 changes: 3 additions & 1 deletion sample/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-7
target=android-19
android.library=false
android.library.reference.1=../library
12 changes: 12 additions & 0 deletions sample/res/drawable/sticky_shadow_default.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

<gradient
android:angle="90"
android:centerColor="#22222222"
android:endColor="#AA222222"
android:startColor="#00222222" >
</gradient>

</shape>

4 changes: 3 additions & 1 deletion sample/res/layout/main.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<com.emilsjolander.components.StickyScrollViewItems.StickyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:whatever="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
whatever:stuckShadowDrawable="@drawable/sticky_shadow_default"
android:id="@+id/ScrollView" >

<LinearLayout
Expand Down Expand Up @@ -111,4 +113,4 @@
android:background="#ff00ffff" />
</LinearLayout>

</com.emilsjolander.components.StickyScrollViewItems.StickyScrollView>
</com.emilsjolander.components.StickyScrollViewItems.StickyScrollView>
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,14 @@ public void onClick(View v) {
Toast.makeText(getApplicationContext(), "hej", Toast.LENGTH_SHORT).show();
}
});

/**
* Below shows setting the scroll view shadow properties programatically.
*/
// StickyScrollView scrollView = (StickyScrollView)
// findViewById(R.id.ScrollView);
// scrollView.setShadowDrawable(getResources().getDrawable(
// R.drawable.sticky_shadow_default));
// scrollView.setShadowHeight(height);
}
}
}

0 comments on commit fc64dbb

Please sign in to comment.