Skip to content

Commit

Permalink
feat:新增吸顶view常驻配置效果
Browse files Browse the repository at this point in the history
  • Loading branch information
lijian committed Apr 20, 2020
1 parent a77f015 commit f361b4e
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 24 deletions.
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ConsecutiveActivity"/>
<activity android:name=".ConsecutiveActivity"></activity>
<activity android:name=".StickyActivity" />
<activity android:name=".SampleActivity" />
<activity android:name=".ViewPagerActivity" />
<activity android:name=".PermanentStickyActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ public void onClick(View v) {
startActivity(intent);
}
});
findViewById(R.id.sticky_permanent).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, PermanentStickyActivity.class);
startActivity(intent);
}
});

}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.donkingliang.consecutivescrollerdemo;

import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout;
import com.donkingliang.consecutivescrollerdemo.adapter.RecyclerViewAdapter;

public class PermanentStickyActivity extends AppCompatActivity {

private ConsecutiveScrollerLayout scrollerLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sticky_permanent);

scrollerLayout = findViewById(R.id.scrollerLayout);

WebView webView = findViewById(R.id.webView);
webView.loadUrl("https://github.com/donkingliang");

webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
// 在webView加载的过程中,用户滚动了webView内容,可能会使webView的显示与scrollerLayout断层,
// 需要让scrollerLayout重新检查一下所有View的显示位置
scrollerLayout.checkLayoutChange();
}
});


RecyclerView recyclerView1 = findViewById(R.id.recyclerView1);
recyclerView1.setLayoutManager(new LinearLayoutManager(this));
RecyclerViewAdapter adapter1 = new RecyclerViewAdapter(this,"RecyclerView1-");
recyclerView1.setAdapter(adapter1);

RecyclerView recyclerView2 = findViewById(R.id.recyclerView2);
recyclerView2.setLayoutManager(new LinearLayoutManager(this));
RecyclerViewAdapter adapter2 = new RecyclerViewAdapter(this,"RecyclerView2-");
recyclerView2.setAdapter(adapter2);

}
}
5 changes: 5 additions & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,10 @@
android:layout_height="wrap_content"
android:text="支持ViewPager"
android:textAllCaps="false" />
<Button
android:id="@+id/sticky_permanent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="布局吸顶常驻" />

</LinearLayout>
135 changes: 135 additions & 0 deletions app/src/main/res/layout/activity_sticky_permanent.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scrollerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_isPermanent="true"
android:scrollbars="vertical">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:padding="10dp"
android:text="吸顶View - 1"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_isSticky="true" />

<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical"
app:layout_isSticky="true">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="吸顶View - 2 我是个LinearLayout"
android:textColor="@android:color/black"
android:textSize="18sp" />

</LinearLayout>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:padding="10dp"
android:text="吸顶View - 3"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_isSticky="true" />

<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_blue_bright"
android:gravity="center"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:gravity="center"
android:text="NestedScrollView"
android:textColor="@android:color/black"
android:textSize="24sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:gravity="center"
android:text="NestedScrollView"
android:textColor="@android:color/black"
android:textSize="24sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:gravity="center"
android:text="NestedScrollView"
android:textColor="@android:color/black"
android:textSize="24sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:gravity="center"
android:text="NestedScrollView"
android:textColor="@android:color/black"
android:textSize="24sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:gravity="center"
android:text="NestedScrollView"
android:textColor="@android:color/black"
android:textSize="24sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:gravity="center"
android:text="NestedScrollView"
android:textColor="@android:color/black"
android:textSize="24sp" />

</LinearLayout>
</androidx.core.widget.NestedScrollView>


<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:padding="10dp"
android:text="吸顶View - 4"
android:textColor="@android:color/black"
android:textSize="18sp"
app:layout_isSticky="true" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public class ConsecutiveScrollerLayout extends ViewGroup implements NestedScroll

private View mScrollToTopView;
private int mAdjust;

private boolean isPermanent;
// 这是RecyclerView的代码,让ConsecutiveScrollerLayout的fling效果更接近于RecyclerView。
static final Interpolator sQuinticInterpolator = new Interpolator() {
@Override
Expand All @@ -118,7 +118,14 @@ public ConsecutiveScrollerLayout(Context context, AttributeSet attrs) {

public ConsecutiveScrollerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

TypedArray a = null;
try {
a = context.obtainStyledAttributes(attrs, R.styleable.ConsecutiveScrollerLayout);
isPermanent = a.getBoolean(R.styleable.ConsecutiveScrollerLayout_layout_isPermanent, false);
} finally {
if (a != null)
a.recycle();
}
mScroller = new OverScroller(getContext(), sQuinticInterpolator);
ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mMaximumVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
Expand Down Expand Up @@ -852,38 +859,41 @@ private void resetSticky() {
List<View> children = getStickyChildren();
if (!children.isEmpty()) {
int count = children.size();

// 让所有的View恢复原来的状态
for (int i = 0; i < count; i++) {
View child = children.get(i);
child.setTranslationY(0);
child.setTranslationZ(0);
}

// 需要吸顶的View
View stickyView = null;
// 下一个需要吸顶的View
View nextStickyView = null;

// 找到需要吸顶的View
for (int i = count - 1; i >= 0; i--) {
View child = children.get(i);
if (child.getTop() <= getScrollY()) {
stickyView = child;
if (i != count - 1) {
nextStickyView = children.get(i + 1);
if (isPermanent) {//常驻
permanentStickyChild(children);
} else {//
// 需要吸顶的View
View stickyView = null;
// 下一个需要吸顶的View
View nextStickyView = null;

// 找到需要吸顶的View
for (int i = count - 1; i >= 0; i--) {
View child = children.get(i);
if (child.getTop() <= getScrollY()) {
stickyView = child;
if (i != count - 1) {
nextStickyView = children.get(i + 1);
}
break;
}
break;
}
}

if (stickyView != null) {
int offset = 0;
if (nextStickyView != null) {
offset = Math.max(0, stickyView.getHeight() - (nextStickyView.getTop() - getScrollY()));
if (stickyView != null) {
int offset = 0;
if (nextStickyView != null) {
offset = Math.max(0, stickyView.getHeight() - (nextStickyView.getTop() - getScrollY()));
}
stickyChild(stickyView, offset);
}
stickyChild(stickyView, offset);
}

}
}
}
Expand All @@ -904,6 +914,32 @@ private void stickyChild(View child, int offset) {
child.setClickable(true);
}

/**
* 子View吸顶常驻
* @param children
*/
@SuppressLint("NewApi")
private void permanentStickyChild(List<View> children) {
for (int i = 0; i < children.size(); i++) {
View child = children.get(i);
int permanentHeight = getPermanentHeight(children, i);
if (child.getTop() <= getScrollY() + permanentHeight) {
child.setY(getScrollY() + permanentHeight);
child.setTranslationZ(1);
child.setClickable(true);
}
}
}

private int getPermanentHeight(List<View> children, int currentPosition) {
int height = 0;
for (int i = 0; i < currentPosition; i++) {
View child = children.get(i);
height += child.getMeasuredHeight();
}
return height;
}

/**
* 使用这个方法取代View的getScrollY
*
Expand Down
3 changes: 3 additions & 0 deletions consecutivescroller/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
<attr name="layout_isNestedScroll" format="boolean"/>
<attr name="layout_isSticky" format="boolean"/>
</declare-styleable>
<declare-styleable name="ConsecutiveScrollerLayout">
<attr name="layout_isPermanent" format="boolean"/>
</declare-styleable>
</resources>

0 comments on commit f361b4e

Please sign in to comment.