CoordinatorLayout是在desgin包下的一个用于协调子控件的组件,可以解决绝大部分滑动联动问题,使用方法也很简单,为观察者注册一个Behavior,在Behavior指定要监听的控件(可以多个)
这边实现一个TextView随着另一个TextView的移动而移动
代码语言:javascript
复制<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@ id/tv_obed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="被观察者"
android:textSize="18sp" />
<TextView
android:id="@ id/tv_ob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="观察者"
android:textSize="18sp"
app:layout_behavior="com.aruba.coordinatorlayoutapplication.MyBehavior" />
</android.support.design.widget.CoordinatorLayout>
代码语言:javascript
复制public class MyBehavior extends CoordinatorLayout.Behavior {
/**
* 注意:一定要写这个构造方法,因为是CoordinatorLayout反射要用到
*
* @param context
* @param attrs
*/
public MyBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 确定要监听哪个控件
*
* @param parent
* @param child
* @param dependency
* @return
*/
@Override
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
if (dependency.getId() == R.id.tv_obed)//监听我们的被观察者
return true;
return false;
}
/**
* 被监听的控件发生的改变,则会回调此方法
*
* @param parent
* @param child
* @param dependency
* @return
*/
@Override
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
child.setY(dependency.getY() dependency.getHeight());//将观察者view放在被监听的控件的下面
child.setX(dependency.getX());
return true;
}
}
代码语言:javascript
复制public class MainActivity extends AppCompatActivity {
private TextView tvObed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvObed = findViewById(R.id.tv_obed);
//被观察者随着手指的移动而移动
tvObed.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
tvObed.setX(event.getRawX());
tvObed.setY(event.getRawY());
return true;
}
});
}
}
最后效果:
此外FloatingActionButton拥有自己封装好的Behavior,下面结合RecyclerView进行使用
代码语言:javascript
复制<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FloatingActivity">
<android.support.v7.widget.RecyclerView
android:id="@ id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="@drawable/ic_add_24dp"
app:borderWidth="0dp"
app:layout_behavior=".FloatingBehavior" />
</android.support.design.widget.CoordinatorLayout>
代码语言:javascript
复制public class FloatingBehavior extends FloatingActionButton.Behavior {
private ValueAnimator valueAnimator;
private boolean isReverse;
public FloatingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 设置我们需要监听的滑动,横向还是竖直
*
* @param coordinatorLayout
* @param child
* @param directTargetChild
* @param target
* @param axes
* @param type
* @return
*/
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull FloatingActionButton child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
//只关注竖直滑动
return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
/**
* 滑动控件有滑动的时候,会回调这个方法
*
* @param coordinatorLayout
* @param child
* @param target
* @param dxConsumed
* @param dyConsumed
* @param dxUnconsumed
* @param dyUnconsumed
* @param type
*/
@Override
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull FloatingActionButton child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
createValueAnimator(child);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {//滑动控件往下滚动
animeOut();
} else if (dyConsumed < 0 && child.getVisibility() == View.INVISIBLE) {
child.setVisibility(View.VISIBLE);
animeIn();
}
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
}
private void animeIn() {
if (valueAnimator == null || valueAnimator.isRunning()) {
return;
}
valueAnimator.reverse();
isReverse = true;
}
private void animeOut() {
if (valueAnimator == null || valueAnimator.isRunning()) {
return;
}
valueAnimator.start();
isReverse = false;
}
public void createValueAnimator(final FloatingActionButton child) {
if (valueAnimator == null) {
valueAnimator = ValueAnimator.ofFloat(1f);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
child.setScaleX(1 - fraction);
child.setScaleY(1 - fraction);
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!isReverse) {
child.setVisibility(View.INVISIBLE);
}
super.onAnimationEnd(animation);
}
});
valueAnimator.setDuration(1000);
}
}
}
代码语言:javascript
复制public class FloatingActivity extends AppCompatActivity {
private RecyclerView recyclerview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_floating);
recyclerview = findViewById(R.id.recyclerview);
recyclerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
MyAdapter myAdapter = new MyAdapter();
recyclerview.setAdapter(myAdapter);
}
class MyAdapter extends RecyclerView.Adapter {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
TextView textView = new TextView(viewGroup.getContext());
textView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT));
textView.setTextSize(30);
textView.setGravity(Gravity.CENTER);
RecyclerView.ViewHolder viewHolder = new ViewHolder(textView);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
((TextView) viewHolder.itemView).setText(String.valueOf(i 1));
}
@Override
public int getItemCount() {
return 20;
}
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}
}
效果如下: