第一步:搭建列表界面
第二步:分析组件原理
准备工作
说明:条目分为两个部分
第一个部分:ContentView---代表内容视图
第二个部分:FunctionView---代表功能视图
1、滑动视图摆放(左边、右边)
注意:
第一种方案:ItemView可以是LinearLayout(左右摆放)---这种方式通过linearLayout自带的属性控制
第二种方案 :FrameLayout实现(覆盖,ContentView在下面,FunctionView在上面)
通过代码算法控制FunctionView到右边
2、滑动视图状态(三种状态:CloseStatus、OpenStatus、SlidingStatus)
CloseStatus:关闭功能视图
OpenStatus:打开功能视图
SlidingStatus:功能视图正在滑动
第三步:具体功能实现
分为两个部分实现
第一个部分:实现布局摆放
1、定义组件
2、定义滑动视图摆放方向(采用枚举定义)
3、定义滑动视图滑动状态(采用枚举)
4、初始化当前SlidingItemLayout条目子视图
注意:规范(只允许有两个儿子)
5、滑动视图测量
目的:计算滑动视图-滑动偏移量
6、滑动视图摆放(onlayout方法)
注意:滑动视图处于关闭状态
6.1 摆放内容视图
6.2 摆放功能视图
完成,测试
package com.tz.dream.slidinglayout.libs;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
//1、定义组件
public class SlidingItemLayout extends FrameLayout {
// 2、定义滑动视图摆放方向(采用枚举定义)
public enum SlidingType {
Left, Right;
}
// 3、定义滑动视图滑动状态(采用枚举)
public enum SlidingStatus {
Close, Open, Sliding;
}
// 4、初始化当前SlidingItemLayout条目子视图-内容视图
private View contentView;
// 4、初始化当前SlidingItemLayout条目子视图-功能视图
private View functionView;
private int horizontalDX;
// 6.1.1 计算布局摆放的位置(矩形:left top right buttom)
private SlidingType slidingType = SlidingType.Right;
// 6.1.1 计算布局摆放的位置(矩形:left top right buttom)
private SlidingStatus slidingStatus = SlidingStatus.Close;
public SlidingItemLayout(Context context) {
super(context);
}
public SlidingItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 4、初始化当前SlidingItemLayout条目子视图
@Override
protected void onFinishInflate() {
super.onFinishInflate();
initView();
}
// 4、初始化当前SlidingItemLayout条目子视图
private void initView() {
if (getChildCount() != 2) {
throw new IllegalArgumentException("你的子视图只允许有两个");
}
contentView = getChildAt(0);
functionView = getChildAt(1);
}
// 5、滑动视图测量
// 目的:计算滑动视图-滑动偏移量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 普及:测量有很多策略......mode
// 默认:我的FunctionView有多宽,那么我的偏移量就多大
// 以下是我的规范
horizontalDX = functionView.getMeasuredWidth();
}
// 6、滑动视图摆放(onlayout方法)
// 注意:滑动视图处于关闭状态
// 6.1 摆放内容视图
// 6.2 摆放功能视图
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
layoutView(true);
}
// 6、滑动视图摆放(onlayout方法)
// 注意:滑动视图处于关闭状态
// 6.1 摆放内容视图
// 6.2 摆放功能视图
// isOpen(true:代表默认打开 false:默认关闭)
private void layoutView(boolean isOpen) {
// 6.1 摆放内容视图
// 6.1.1 计算布局摆放的位置
Rect contentRect = layoutContentView(isOpen);
// 6.1.2 摆放内容视图
contentView.layout(contentRect.left, contentRect.top,
contentRect.right, contentRect.bottom);
// 6.2 摆放功能视图
// 6.2.1 计算功能视图的位置
Rect functionRect = layoutFunctionView(contentRect);
// 6.2.2 摆放功能视图
functionView.layout(functionRect.left, functionRect.top,
functionRect.right, functionRect.bottom);
}
// 6.1.1 计算布局摆放的位置(矩形:left top right buttom)
private Rect layoutContentView(boolean isOpen) {
int left = 0;
// 处理true状态
if (isOpen) {
if (slidingType == SlidingType.Left) {
// 功能视图摆放方向---左边
left = horizontalDX;
} else if (slidingType == SlidingType.Right) {
// 功能视图摆放右边
left = -horizontalDX;
}
}
// 首先摆放默认情况--false状态
return new Rect(left, 0, left + getMeasuredWidth(), getMeasuredHeight());
}
// 6.2 摆放功能视图
// 6.2.1 计算功能视图的位置
private Rect layoutFunctionView(Rect rect) {
int left = 0;
// 根据类型摆放
if (slidingType == SlidingType.Right) {
// 功能视图摆放在右边
left = rect.right;
} else if (slidingType == SlidingType.Left) {
// 功能视图摆放在左边
left = -horizontalDX;
}
return new Rect(left, 0, left + horizontalDX,
functionView.getMeasuredHeight());
}
}
<?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" >
<com.tz.dream.slidinglayout.libs.SlidingItemLayout
android:layout_width="match_parent"
android:layout_height="60dp" >
<LinearLayout
android:id="@+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:background="@android:color/darker_gray">
<ImageView
android:id="@+id/iv_header"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/header"/>
</LinearLayout>
<LinearLayout
android:id="@+id/functionView"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:orientation="horizontal" >
<Button
android:id="@+id/bt_call"
android:layout_width="60dp"
android:layout_height="fill_parent"
android:background="#888888"
android:gravity="center"
android:text="@string/call"
android:textColor="@android:color/white" />
<Button
android:id="@+id/bt_delete"
android:layout_width="60dp"
android:layout_height="fill_parent"
android:background="#ff0000"
android:gravity="center"
android:text="@string/delete"
android:textColor="@android:color/white" />
</LinearLayout>
</com.tz.dream.slidinglayout.libs.SlidingItemLayout>
</LinearLayout>
先看下效果图!
注意下这个方法
onFinishInflate
* 我们一般使用View的流程是在onCreate中使用setContentView来设置要显示Layout文件或直接创建一个View,
* 在当设置了ContentView之后系统会对这个View进行解析,然后回调当前视图View中的onFinishInflate方法。
* 只有解析了这个View我们才能在这个View容器中获取到拥有Id的组件, 同样因为系统解析完View之后才会调用
* onFinishInflate方法,所以我们自定义组件时可以onFinishInflate方法中获取指定子View的引用。
我这里有三张图,大家可以参照看下
我会在下一篇文章中详细的介绍具体功能的实现;会包含跟多的算法
作者:qczg_wxg 发表于2016/10/18 10:47:13 原文链接
阅读:37 评论:0 查看评论