效果图如下:
实现原理
- 监听
ScrollView
滑动事件 - 根据监听的滑动值设置顶部
view
的 margin,这个地方的重点是设置为负数
步骤:
- 给
ScrollView
设置滑动监听,因为直接的回调方法setOnScrollChangeListener
有 API 版本的限制,所以这里利用onScrollChanged(int x, int y, int oldx, int oldy)
回调方法来获取滑动值
public class ObserveScrollView extends ScrollView {
public interface ScrollViewListener {
void onScrollChanged(ObserveScrollView scrollView, int x, int y,
int oldx, int oldy);}
private ScrollViewListener scrollViewListener = null;
public ObserveScrollView(Context context) {
super(context);
}
public ObserveScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public ObserveScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
}
2 设置顶部 view
的margin 值
这里注意: 为了使得 margin 为负数时生效,最好是利用 LinearLayout
作为父控件,例如:
<com.example.panhe.demos.view.ObserveScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="@dimen/dp300"
android:background="@drawable/changjinglu" />
<TextView
android:id="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="1500dp"
android:background="@color/colorPrimary" />
</LinearLayout>
</com.example.panhe.demos.view.ObserveScrollView>
然后注册监听,跟进滑动值调用 setMargins()
方法
// 这里用的是kotlin代码,需要稍微注意下
class MarginActivity : AppCompatActivity(), ObserveScrollView.ScrollViewListener {
override fun onScrollChanged(scrollView: ObserveScrollView?, x: Int, y: Int, oldx: Int, oldy: Int) {
// 这里改变iamge的margin值
val para = image?.layoutParams
if (para is ViewGroup.MarginLayoutParams) {
para.setMargins(0, y / 2, 0, -y / 2)
image.layoutParams = para
image.requestLayout()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_margin)
scrollView.setScrollViewListener(this)
}
}
备注: 很简单的思路,但是不知道这个思路的话会觉得这个效果挺难的,我就是这样.
这个思路是从前同事陈*遗留的代码看到的,感谢.