最终效果图
2017-09-20-02mzLppp.gif好吧,看起来和上一个侧滑栏没有什么不同,但是两个实现完全不同一个是利用控件本身的TranslationX来移动的,一个是利用scrollTo /scrollBy实现的,是继承ViewGroup
还有自带的滚动器 Scroller scroller;使用
代码(全部)
package com.example.downlist.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Scroller;
import com.example.downlist.utils.UIUtlis;
/**
* Created by Administrator on 2017/9/11.
*/
//左边侧滑栏
public class LiftView extends ViewGroup {
//当前是否打开
private boolean isOpen;
//滚动器
private Scroller scroller;
private FrameLayout fragment_mid;
private FrameLayout fragment_lift;
//左边FraLayout的宽度,指定宽度
private int w = UIUtlis.dp2Px(150);
//中间值
private int mid = UIUtlis.dp2Px(150) / 2;
private int startX;
//自定义防抖数值
private int dipX = 10;
public LiftView(Context context) {
super(context);
initView(context);
}
public LiftView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public LiftView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
scroller = new Scroller(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
fragment_mid = (FrameLayout) getChildAt(0);
fragment_lift = (FrameLayout) getChildAt(1);
fragment_mid.layout(l, t, r, b);
fragment_lift.layout(-w, t, 0, b);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//开始测量左边FrameLayout
if (getChildCount() < 2) {
throw new RuntimeException("指定孩子不能小于2个");
}
//左边的FrameLayout
View childAt = getChildAt(1);
int liftWidth = childAt.getLayoutParams().width;
int width = MeasureSpec.makeMeasureSpec(liftWidth, MeasureSpec.EXACTLY);
childAt.measure(width, heightMeasureSpec);
getChildAt(0).measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
int endX = (int) event.getX();
int mid = endX - startX;
scrollBy(-mid, 0);
noMove(event);
animFrameLayout();
if (getScrollX() == -w) {
isOpen = true;
isOpenListener();
}
if (getScrollX() == 0) {
isOpen = false;
isOpenListener();
}
startX = endX;
break;
case MotionEvent.ACTION_UP:
noMid();
break;
}
return true;
}
//判断是否拦截该事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int startX = 0;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) ev.getX();
break;
case MotionEvent.ACTION_MOVE:
int endX = (int) ev.getX();
int mid = endX - startX;
//向左滑
if (mid > dipX) {
Log.e("拦截", "onInterceptTouchEvent: " + "开始拦截");
return true;
}
//向右滑
if (mid < -dipX) {
Log.e("拦截", "onInterceptTouchEvent: " + "开始拦截");
return true;
}
endX = startX;
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onInterceptTouchEvent(ev);
}
//如果在中间不能让它停留在中间
private void noMid() {
int scrollX = getScrollX();
//直接关闭到右边测
if (scrollX >= -mid) {
moveIndex(0);
isOpen = false;
}
//直接开启到左侧
if (scrollX <= -mid) {
moveIndex(-w);
isOpen = true;
}
}
//防止越界
private void noMove(MotionEvent event) {
int scrollX = getScrollX();
//左边越界标准 //不能小于 -w
if (scrollX <= -w) {
scrollTo(-w, 0);
isOpen = true;
}
//右边越界标准 //不能大于于0
if (scrollX >= 0) {
scrollTo(0, 0);
isOpen = false;
}
}
@Override
public void computeScroll() {
super.computeScroll();
//滚动器的方法,需要重写
if (scroller.computeScrollOffset()) {
int currX = scroller.getCurrX();
scrollTo(currX, 0);
Log.e("----", "computeScroll: " + currX);
if (currX == 0 || currX == -w) {
isOpenListener();
}
animFrameLayout();
}
invalidate();
}
//滚动到某个位置
private void moveIndex(int index) {
int scrollX = getScrollX();
int dx = index - scrollX;
//DX表示,从哪里滑到哪里,比如:从哪个起点滑到那个终点
scroller.startScroll(scrollX, 0, dx, 0);
invalidate();
}
public void setOpenAndClose(boolean isOpen) {
if (isOpen) {
//打开
moveIndex(-w);
this.isOpen = true;
} else {
//关闭
moveIndex(0);
this.isOpen = false;
}
}
public boolean getOpenAndClose() {
return isOpen;
}
//只要打开或者关闭就会调用
private void isOpenListener() {
if (isOpen) {
UIUtlis.runOnUIToast("打开了");
} else {
UIUtlis.runOnUIToast("关闭了");
}
if (onOpenCloseListener != null)
onOpenCloseListener.isOpen(isOpen);
}
private OnOpenCloseListener onOpenCloseListener;
public void setOnOpenCloseListener(OnOpenCloseListener onOpenCloseListener) {
this.onOpenCloseListener = onOpenCloseListener;
}
public interface OnOpenCloseListener {
void isOpen(boolean isOpen);
}
public void animFrameLayout() {
/*
int scrollX = getScrollX();
float i = (float) (Math.abs(scrollX) * 1.0 / w * 1.0);
float i2 = (float) (1.0 - i);
Log.e("----", "animFrameLayout: " + i);
getChildAt(0).setScaleX((float) (i2));
getChildAt(0).setScaleY((float) (i2));*/
}
}
希望以上代码,对你的自定义控件有所帮助
--XINHAO_HAN
如果那块有不懂得请联我哟...0.0 哈哈
使用
<?xml version="1.0" encoding="utf-8"?>
<com.example.downlist.view.LiftView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mySheView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/mid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#123456">
<LinearLayout
android:layout_width="300dp"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
<FrameLayout
android:id="@+id/lift"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#654321">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dshshfhdskjfhdsf" />
</LinearLayout>
</FrameLayout>
</com.example.downlist.view.LiftView>
Demo下载:
链接: https://pan.baidu.com/s/1i5P6WML 密码: 3283
网友评论