您的位置:首页 > 其它

自定义侧滑组件+自定义属性

2016-06-24 01:21 387 查看
继承HorizontalScrollView,通过添加各种方法,自定义实现各种侧滑效果

先看xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<com.example.administrator.slidingmenu.widget.SlidingMenu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"

<!--自定义属性的赋值-->
app:left_off_width="300"

tools:context="com.example.administrator.slidingmenu.MainActivity">

<com.example.administrator.slidingmenu.widget.OrdetDrawLinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<LinearLayout
android:id="@+id/teach_left_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorAccent"
>

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="左侧菜单"
/>
</LinearLayout>

<LinearLayout
android:id="@+id/teach_main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="@color/colorPrimary">

<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:src="@mipmap/ic_launcher"
/>
</LinearLayout>
</com.example.administrator.slidingmenu.widget.OrdetDrawLinearLayout>
</com.example.administrator.slidingmenu.widget.SlidingMenu>


再看Java代码。自定义侧滑组件的类SlidingMenu继承于HorizoltalScrollView

package com.example.administrator.slidingmenu.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.example.administrator.slidingmenu.R;

/**
*
* ViewGroup 绘制流程
* onMeasure
* onLayout
* onDraw
*
*
*自定义属性
* 1在value下创建attrs,在其中使用<declare-styleable标签声明我们自己要为哪个View设置属性
* 2在自定义属性中创建自己的属性,指定name和format
* 2在我们View的构造函数中,使用TypeArray进行属性的加载,使用完成要注意回收
* 4对我们获取的值进行使用,在xml布局中使用自定义属性
*
* Created by Administrator on 2016/6/16.
*/
public class SlidingMenu extends HorizontalScrollView{

private static final String TAG = SlidingMenu.class.getSimpleName();
private View mLeftMenu;//左侧的侧滑布局
private View mContent;//主内容布局
private int mScreenWidth;//屏幕宽度
private int leftMenuWidthOff;//当左侧菜单划出的时候屏幕的剩余宽度

private static final int MENU_DEFAULT_WIDTH_OFF=150;//指定默认值,没有更改时就是这个值
private int leftMenuWidth;//左侧菜单的宽度
private boolean isMeasure;//布局测量的标记位
private int leftMenuHaftWidth;//左侧菜单宽度的一半

public SlidingMenu(Context context) {
this(context, null);
}

/**
* 使用Inflate进来的View走两个参数的构造
* @param context
* @param attrs
*/
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

//获取屏幕宽度
mScreenWidth=getResources().getDisplayMetrics().widthPixels;

//自定义的所有属性
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenr, defStyleAttr, 0);
leftMenuWidthOff=typedArray.getInt(R.styleable.SlidingMenr_left_off_width, MENU_DEFAULT_WIDTH_OFF);
//使用完成要回收
typedArray.recycle();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

if (!isMeasure) {
//滑动布局中的唯一的Child
LinearLayout single = (LinearLayout) getChildAt(0);
//获取左侧菜单
mLeftMenu = single.getChildAt(0);
//获取中间的内容部分
mContent = single.getChildAt(1);

//左侧的菜单宽度赋值
leftMenuWidth = mScreenWidth - leftMenuWidthOff;
//左侧菜单的一半
// leftMenuHaftWidth=leftMenuWidth/2;
leftMenuHaftWidth=leftMenuWidth >> 1;
//设置左边Menu的宽度
mLeftMenu.getLayoutParams().width = leftMenuWidth;
//设置主内容区域的宽度
mContent.getLayoutParams().width=mScreenWidth;

}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if(changed){
//粗暴滚动
scrollTo(leftMenuWidth, 0);
isMeasure=true;
}
}

@Override
public boolean onTouchEvent(MotionEvent ev) {

switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
int scrollX = getScrollX();
Log.e(TAG, "onTouchEvent"+scrollX);
//滑动距离大于左侧菜单的一半
if (scrollX>leftMenuHaftWidth) {
//显示主内容区
//平滑滚动
smoothScrollTo(leftMenuWidth, 0);
}else {
//显示左侧菜单
smoothScrollTo(0,0);
}
return true;
}
return super.onTouchEvent(ev);
}

//可以在onScrollChanged方法中添加各种动画
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
Log.e(TAG, "onScrollChanged: -->" + l + "---" + t);
//测试手机宽度1080,左侧菜单减少宽度150,上一步向左滚动了leftMenuWidth,所以这里初始l为1080-150=930。向左滑动l为正值

//效果:当向右滑动时,左侧菜单同时向右平移,感觉左侧菜单一直在右侧的底部
//即菜单被掩盖
// mLeftMenu.setTranslationX(l);

//主内容被掩盖。
mContent.setTranslationX(l-leftMenuWidth);
}
}
当执行上面onScrollChanged方法

//主内容被掩盖。
mContent.setTranslationX(l-leftMenuWidth);

的方法的时候,会出现bug,导致内容页面完全覆盖侧滑页面,所以执行下面自定义方法,改变其Child的绘制顺序

package com.example.administrator.slidingmenu.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/**
* 更改View绘制的顺序
* 重写getChildDrawingOrder
* 设置Child绘制顺序可以更改(启用绘制顺序)
*
*
* Created by Administrator on 2016/6/16.
*/
public class OrdetDrawLinearLayout extends LinearLayout {
public OrdetDrawLinearLayout(Context context) {
this(context, null);
}

public OrdetDrawLinearLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public OrdetDrawLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

setChildrenDrawingOrderEnabled(true);
}

<span style="font-family:KaiTi_GB2312;">//改变其Child组件的绘制顺序</span>
@Override
protected int getChildDrawingOrder(int childCount, int i) {

switch (i) {
case 1:
return 0;
case 0:
return 1;
}

return super.getChildDrawingOrder(childCount, i);
}
}

自定义属性:在main/ res/ values 文件夹下,建attrs文件,里面写下面代码

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SlidingMenr">
<attr name="left_off_width" format="integer"/>

</declare-styleable>
</resources>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: