我尝试使用 ViewDragHelp 来实现可拖动面板,但问题是面板的隐藏部分未显示。 Picture what i meant
这是我的代码。 SlidePanel是可拖动的面板和" white_pane"是部分隐藏的面板(我将bttom边距设置为-280dp)
SlidePanel.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center|bottom"
>
<RelativeLayout
android:id="@+id/name_pane"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@drawable/name_layout"
>
<TextView
android:id="@+id/name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test"
android:textSize="20sp"
android:fontFamily="sans-serif-medium"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
>
</TextView>
</RelativeLayout>
<RelativeLayout
android:id="@+id/white_pane"
android:layout_width="match_parent"
android:layout_height="280dp"
android:layout_marginBottom="-200dp"
android:background="#F0F2F4">
</RelativeLayout>
</LinearLayout>
SlidePanel.java
public class SlidePanel extends LinearLayout {
private ViewDragHelper mDragHelper;
protected ViewGroup whitePanel;
protected ViewGroup namePanel;
protected TextView nameText;
private Status status;
private Animation show , hide;
MapsActivity mapAct;
LayoutInflater mInflater;
private int mDraggingBorder;
private int mVerticalRange;
private boolean mIsOpen;
private final double AUTO_OPEN_SPEED_LIMIT = 800.0;
private int mDraggingState = 0;
public SlidePanel(Context context) {
super(context);
mInflater = LayoutInflater.from(context);
init();
}
public SlidePanel(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mInflater = LayoutInflater.from(context);
init();
}
public SlidePanel(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
init();
}
public void init()
{
mInflater.inflate(R.layout.slide_panel, this, true);
//hiddenPanel = (ViewGroup)mapAct.findViewById(R.id.hidden_panel);
whitePanel = (ViewGroup)findViewById(R.id.white_pane);
namePanel = (ViewGroup)findViewById(R.id.name_pane);
nameText = (TextView)findViewById(R.id.name_text);
//slidingLayout = (SlidingUpPanelLayout)mapAct.findViewById(R.id.sliding_layout);
status = Status.HIDDEN;
this.setVisibility(View.INVISIBLE);
mDragHelper = ViewDragHelper.create(this,1.0f , new DragHelperCallback());
}
public void initAnim(MapsActivity mapAct){
this.mapAct = mapAct;
show = AnimationUtils.loadAnimation(mapAct, R.anim.show);
hide = AnimationUtils.loadAnimation(mapAct, R.anim.hide);
}
public void show(ParseObject area){
if(status.equals(Status.HIDDEN)){
startAnimation(show);
setVisibility(View.VISIBLE);
status = Status.SHOW;
//hashMarker.get(marker.getId())
}
nameText.setText(area.getString("name"));
}
public void hide(){
if(status.equals(Status.SHOW)){
startAnimation(hide);
setVisibility(View.INVISIBLE);
status = Status.HIDDEN;
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (isTarget(event) /*&& mDragHelper.shouldInterceptTouchEvent(event)*/) {
//Log.e("intercept", "intercept true");
return true;
} else {
//Log.e("intercept", "intercept false");
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isTarget(event) || isMoving()) {
mDragHelper.processTouchEvent(event);
//Log.e("touch", "touch true");
return true;
} else {
//Log.e("touch", "touch false");
return super.onTouchEvent(event);
}
}
private boolean isTarget(MotionEvent event) {
int[] location = new int[2];
whitePanel.getLocationOnScreen(location);
int upperLimit = location[1] + whitePanel.getMeasuredHeight();
int lowerLimit = location[1] - namePanel.getMeasuredHeight();
int y = (int) event.getRawY();
//Log.e("touch", "upper target: " + upperLimit +" & lower target: "+ lowerLimit);
//Log.e("touch", "touch at: " + y);
return (y > lowerLimit && y < upperLimit);
}
private class DragHelperCallback extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View view, int pointerId) {
//Log.e("capture", "Capture white is " + (view.getId() == R.id.white_pane) + " but it capture " + view.getId());
//return (view.getId() == R.id.white_pane);
return true;
}
@Override
public void onViewDragStateChanged(int state) {
if (state == mDraggingState) { // no change
return;
}
if ((mDraggingState == ViewDragHelper.STATE_DRAGGING || mDraggingState == ViewDragHelper.STATE_SETTLING) &&
state == ViewDragHelper.STATE_IDLE) {
// the view stopped from moving.
if (mDraggingBorder == 0) {
onStopDraggingToClosed();
} else if (mDraggingBorder == mVerticalRange) {
mIsOpen = true;
}
}
if (state == ViewDragHelper.STATE_DRAGGING) {
onStartDragging();
}
mDraggingState = state;
Log.e("Drag" , "State changed : " + state);
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
mDraggingBorder = top;
}
public int getViewVerticalDragRange(View child) {
return mVerticalRange;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int topBound = getPaddingTop();
final int bottomBound = mVerticalRange;
Log.e("Drag" , "clamp at topBound = " + topBound + " and bottom = " + bottomBound + " and top= " + top);
//return Math.min(Math.max(top, topBound), bottomBound);
//status = top>0? Status.SLIDE_DOWN:Status.SLIDE_UP;
return Math.min(top, bottomBound);
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
final float rangeToCheck = mVerticalRange;
Log.e("Drag" , "Released. rangeToCheck: " + rangeToCheck + " and mDraggingBorder: " + mDraggingBorder);
if (mDraggingBorder == 0) {
mIsOpen = false;
return;
}
if (mDraggingBorder == rangeToCheck) {
mIsOpen = true;
return;
}
Log.e("Drag" , "Released. y velocity = " + yvel);
boolean settleToOpen = false;
if (yvel > AUTO_OPEN_SPEED_LIMIT) { // speed has priority over position
settleToOpen = true;
Log.e("drag" , "FUCKING OVER SPEED");
} else if (yvel < -AUTO_OPEN_SPEED_LIMIT) {
settleToOpen = true;
} else if (Math.abs(mDraggingBorder )> rangeToCheck / 2) {
settleToOpen = true;
} else if (Math.abs(mDraggingBorder) < rangeToCheck / 2) {
settleToOpen = false;
}
int settleDestY = settleToOpen ? mVerticalRange : 0;
if(yvel > AUTO_OPEN_SPEED_LIMIT) settleDestY = 0;
Log.e("drag" , "settle Dest Y : " + settleDestY );
if(mDraggingBorder < 0)settleDestY = settleDestY * -1;
if(mDragHelper.settleCapturedViewAt(0, settleDestY)) {
ViewCompat.postInvalidateOnAnimation(SlidePanel.this);
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//mVerticalRange = (int) (h * 0.66);
int inPixel = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 110, getResources().getDisplayMetrics());
mVerticalRange = h - inPixel;
//super.onSizeChanged(w, h, oldw, oldh);
}
private void onStopDraggingToClosed() {
// To be implemented
Log.e("Drag" , "On stop drag to close");
}
private void onStartDragging() {
Log.e("Drag" , "On start drag");
}
@Override
public void computeScroll() { // needed for automatic settling.
if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
public boolean isMoving() {
return (mDraggingState == ViewDragHelper.STATE_DRAGGING ||
mDraggingState == ViewDragHelper.STATE_SETTLING);
}
public boolean isOpen() {
if(status == Status.SHOW){
return false;
}else{
return mIsOpen;
}
}
}