您的浏览器不支持播放该视频!复制链接浏览器打开 http://zhx02.xiaoxingxing.online/2020/03/29/4ee85d854030a7b98001dc9e9f201b92.mp4
实现这个拖拽动画最重要的我们需要重写一下基本控件方法,setHeight,setWidht,setMarintop属性等,不然我们无法使用属性动画来实现,整个过程将会复杂许多。上节也提到了要想在属性动画中使用height widht这些属性我们就需要去实现相应的set方法。
先贴出完成代码,然后再讲解:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<com.gesture.zhx.zhxgesture.CustomUI.MyFramLayout
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:id="@+id/m4_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:orientation="vertical">
<com.gesture.zhx.zhxgesture.CustomUI.MyVideoView
android:id="@+id/video"
android:layout_width="match_parent"
android:layout_height="200dp">
</com.gesture.zhx.zhxgesture.CustomUI.MyVideoView>
<com.gesture.zhx.zhxgesture.CustomUI.MyScrollView
android:id="@+id/scr"
android:layout_marginTop="200dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:background="#ff0000"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#4678ff"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#ff0000"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#4678ff"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#ff0000"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
<TextView
android:background="#4678ff"
android:layout_width="match_parent"
android:layout_height="100dp">
</TextView>
</LinearLayout>
</com.gesture.zhx.zhxgesture.CustomUI.MyScrollView>
</com.gesture.zhx.zhxgesture.CustomUI.MyFramLayout>
mainactivity文件:
public class Main4Activity extends Activity {
private int dx, dy, mx, my, ux, uy;
private MyFramLayout m4Group;
private MyVideoView video;
private MyScrollView scr;
private int residueHeight = 0, SumscrollY = 0, OffsetY = 0;
private int groupHeight = 0, videoHeight = 0, scrHeight = 0;
private int groupWidth = 0, videoWidth = 0, scrWidth = 0;
private float alpha = 255;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
initView();
}
private void initView() {
m4Group = (MyFramLayout) findViewById(R.id.m4_group);
video = (MyVideoView) findViewById(R.id.video);
scr = (MyScrollView) findViewById(R.id.scr);
//网络数据
String s = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";
Uri uri = Uri.parse(s);
video.setVideoURI(uri);
video.requestFocus();
video.start();
m4Group.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dy = (int) event.getRawY();
SumscrollY = 0;
if (groupHeight == 0) groupHeight = m4Group.getHeight();
if (videoHeight == 0) videoHeight = video.getHeight();
if (scrHeight == 0) scrHeight = scr.getHeight();
if (residueHeight == 0) residueHeight = groupHeight - videoHeight;
if (groupWidth == 0) groupWidth = m4Group.getWidth();
if (videoWidth == 0) videoWidth = video.getWidth();
if (scrWidth == 0) scrWidth = scr.getWidth();
break;
case MotionEvent.ACTION_MOVE:
my = (int) event.getRawY();
uploadView();
break;
case MotionEvent.ACTION_UP:
uy = (int) event.getRawY();
/**
* 抬起的时候判断最终落点在上半区域还是下半区域
* 如果是上半区域则向上恢复
* 如果是下半区域则向下执行运动
*/
if (uy < groupHeight / 2) {
//上半区
resetTopVideoview();
resetTopScrollView();
} else {
//下半区
resetBottomVideoView();
resetBottomScrollView();
}
break;
}
return true;
}
});
}
private void uploadView() {
OffsetY = my - dy;
SumscrollY = video.getMargin()[1] + OffsetY;
if (SumscrollY > residueHeight)
SumscrollY = (int) residueHeight;
if (SumscrollY < 0)
SumscrollY = 0;
alpha = txfloat((residueHeight - SumscrollY), residueHeight);
int mr = (int) ((1f - alpha) * videoWidth / 2);
scr.setAlpha(alpha);
scr.setMarginTop(SumscrollY + video.getHeight());
video.setMarginTop(SumscrollY);
video.setMarginRight(mr);
int h = (int) (videoHeight * alpha);
if (h <= videoHeight / 3 *2){
h = videoHeight /3 *2;
}
video.setHeight(h);
dy = my;
}
private void resetTopVideoview() {
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.ofInt(video, "height", video.getHeight(), videoHeight);
ObjectAnimator animator2 = ObjectAnimator.ofInt(video, "marginTop", video.getMargin()[1], 0);
ObjectAnimator animator3 = ObjectAnimator.ofInt(video, "marginRight", video.getMargin()[2], 0);
animatorSet.setDuration(600);
animatorSet.playTogether(animator1, animator2, animator3);
animatorSet.start();
}
private void resetTopScrollView() {
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.ofFloat(scr, "alpha", scr.getAlpha(), 255);
ObjectAnimator animator2 = ObjectAnimator.ofInt(scr, "marginTop", scr.getMargin()[1], videoHeight);
animatorSet.setDuration(600);
animatorSet.playTogether(animator1, animator2);
animatorSet.start();
}
private void resetBottomVideoView() {
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.ofInt(video, "height", video.getHeight(), videoHeight / 3 * 2);
ObjectAnimator animator2 = ObjectAnimator.ofInt(video, "marginTop", video.getMargin()[1], residueHeight);
ObjectAnimator animator3 = ObjectAnimator.ofInt(video, "marginRight", video.getMargin()[2], videoWidth / 2);
animatorSet.setDuration(1200);
animatorSet.playTogether(animator1, animator2, animator3);
animatorSet.start();
}
private void resetBottomScrollView() {
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator animator1 = ObjectAnimator.ofFloat(scr, "alpha", scr.getAlpha(), 0);
ObjectAnimator animator2 = ObjectAnimator.ofInt(scr, "marginTop", scr.getMargin()[1], residueHeight + video.getHeight());
animatorSet.setDuration(600);
animatorSet.playTogether(animator1, animator2);
animatorSet.start();
}
public Float txfloat(int a, int b) {
DecimalFormat df = new DecimalFormat("0.00");
String s = String.valueOf(df.format((float) a / b));
return Float.parseFloat(s);
}
}
MyFramLayout文件:
public class MyFramLayout extends FrameLayout {
public MyFramLayout(Context context){
super(context);
}
public MyFramLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public void setHeight(int height) {
ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams();
params.height = height;
setLayoutParams(params);
}
public void setWidth(int value) {
LayoutParams params = (LayoutParams) getLayoutParams();
params.width = value;
setLayoutParams(params);
}
public void setMarginTop(int values){
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
params.topMargin = values;
setLayoutParams(params);
}
public void setMarginLeft(int values){
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
params.leftMargin = values;
setLayoutParams(params);
}
public void setMarginRight(int values){
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
params.rightMargin = values;
setLayoutParams(params);
}
public void setMarginBottom(int values){
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
params.bottomMargin = values;
setLayoutParams(params);
}
public int[] getMargin() {
int[] arr = new int[6];
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
arr[0] = params.leftMargin;
arr[1] = params.topMargin;
arr[2] = params.rightMargin;
arr[3] = params.bottomMargin;
arr[4] = params.height;
arr[5] = params.width;
return arr;
}
}
MyScrollView,MyVideoView不多说与上面的MyFramLayout文件一样就写几个属性方法。
在我们手指按下的时候我们就记录控件初始化的高度,这些参数我们都需要用到后面,所以只需要赋值一次,在抬起来的时候我们分析手指是在屏幕上区域还是下区域,然后调用相应的方法实现动画。
在uploadView方法中我们需要去记录手指滑动的总距离,这里我们是获取videoview距离上面的高度加上此次的偏移量来算,为什么这样左,这样左有一个好处,就是当你再次按下的时候就能接着上次的距离来进行计算,不需要去判断是往上滚动还是往下滚动。
然后对videoview来说需要改变他的height margintop marginright三个属性
对Scrollview来说我们需要改变他的 alpha margintop 俩个属性
在相应方法中,计算出最后的结果值,传入当前的属性值即可。
整个逻辑还是有点绕的,不过自己动手试试也很好理解。
那么动画我们是实现了,activity的背景色我们怎么设置透明,
android:theme="@android:style/Theme.Translucent.NoTitleBar"
更改主题属性就可以了,那么在activity中我们怎么实现一个应用内所有界面悬浮播放的效果,这个可以用打开一个新窗口实现,类似于悬浮窗原理。
如果是一个fragment,那最好还是用悬浮窗原理去做,但是如果你的项目是一个activity加多一个fragment组成,那么你可以直接用fragment,把这个videofragment置于栈顶,并以后所有添加的fragment都置于第二层即可。