最近项目中有个功能,在课程播放页,有个讲师详情页:上面展示文字信息,下面展示一个webView,但是webView,要通过上拉才出现。网上找的一个开源的demo。对里面进行了一定的修改,以符合项目要求:
https://github.com/cnbleu/SlideDetailsLayout
注:
**1、滑动的自定义布局 SlideDetailsLayout 中,只包含2个子view。多了会有问题
2、如果第一个默认展示的view没有被填满,会有留白。详见效果图**
以下会对在Activity中,已经在Fragment中使用,分别附上源码(代码、布局文件)
—————————————————————————————————
效果图:
1、Activity中使用:
2、Fragment中使用
3、默认展示控件中的数据没有完全填充
代码:
1、因为有webView,先加上网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
2、有自定义属性,所以,需要在 values文件夹下,创建 attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SlideDetailsLayout">
<!-- float value for indicate the moment of switch panel-->
<attr name="percent" format="float"/>
<!-- how long the animation keep-->
<attr name="duration" format="integer"/>
<!-- default panel to show after init-->
<attr name="default_panel" format="enum">
<enum name="front" value="0"/>
<enum name="behind" value="1"/>
</attr>
</declare-styleable>
</resources>
3、回调接口
/**
* 滑动回调接口
*/
public interface ISlideCallback {
//展开详情
void openDetails(boolean smooth);
//关闭详情
void closeDetails(boolean smooth);
}
4、最核心的代码:SlideDetailsLayout
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
/**
* 滑动的自定义view
*/
public class SlideDetailsLayout extends ViewGroup {
/**
* Callback for panel OPEN-CLOSE status changed.
*/
public interface OnSlideDetailsListener {
/**
* Called after status changed.
*
* @param status {@link Status}
*/
void onStatucChanged(Status status);
}
/**
* 状态值
*/
public enum Status {
CLOSE,
OPEN;
public static Status valueOf(int stats) {
if (0 == stats) {
return CLOSE;
} else if (1 == stats) {
return OPEN;
} else {
return CLOSE;
}
}
}
//默认百分比
private static final float DEFAULT_PERCENT = 0.2f;
//默认执行时间
private static final int DEFAULT_DURATION = 300;
//默认最大速度
private static final float DEFAULT_MAX_VELOCITY = 2500f;
private View mFrontView;
private View mBehindView;
private float mTouchSlop;
private float mInitMotionY;
private float mInitMotionX;
private View mTarget;
private float mSlideOffset;
private Status mStatus = Status.CLOSE;
private boolean isFirstShowBehindView = true;
private float mPercent = DEFAULT_PERCENT;
private long mDuration = DEFAULT_DURATION;
private int mDefaultPanel = 0;
private VelocityTracker mVelocityTracker;
private OnSlideDetailsListener mOnSlideDetailsListener;
public SlideDetailsLayout(Context context) {
this(context, null);
}
public SlideDetailsLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlideDetailsLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideDetailsLayout, defStyleAttr, 0);
mPercent = a.getFloat(R.styleable.SlideDetailsLayout_percent, DEFAULT_PERCENT);
mDuration = a.getInt(R.styleable.SlideDetailsLayout_duration, DEFAULT_DURATION);
mDefaultPanel = a.getInt(R.styleable.SlideDetailsLayout_default_panel, 0);
a.recycle();
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
/**
* Set the callback of panel OPEN-CLOSE status.
*
* @param listener {@link OnSlideDetailsListener}
*/
public void setOnSlideDetailsListener(OnSlideDetailsListener listener) {
this.mOnSlideDetailsListener = listener;
}
/**
* Open pannel smoothly.
*
* @param smooth true, smoothly. false otherwise.
*/
public void smoothOpen(boolean smooth) {
if (mStatus != Status.OPEN) {
mStatus = Status.OPEN;
final float height = -getMeasuredHeight();
animatorSwitch(0, height, true, smooth ? mDuration : 0);
}
}
/**
* Close pannel smoothly.
*
* @param smooth true, smoothly. false otherwise.
*/
public void smoothClose(boolean smooth) {
if (mStatus != Status.CLOSE) {
mStatus = Status.OPEN;
final float height = -getMeasuredHeight();
animatorSwitch(height,