`
isiqi
  • 浏览: 16081797 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Android 自定义控件-SnakeLayout (仿gallery)

阅读更多

转载请注明转载地址:

http://wallage.blog.163.com/blog/static/1738962420108211120850/

简要介绍:相信大部分用过android Gallery控件的人,对gallery这个控件可谓是又爱又恨,gallery动画效果不错,非常实用,可是却有很多限制,从布局上来讲,gallery仅能水平放置,若想使用垂直放置的gallery,除非重写gallery。本文所述SnakeLayout继承于FrameLayout,用户可在SnakeLayout里自定义多个ImageView (大于等于3)的位置,并将指定的ID分配给所定义的ImageView;之后在主文件里进行简单的初始化后,就可以像gallery一样拖动所定义的ImageView,如同一条蛇一样连续的移动,不仅能横着拖,竖着拖,还能斜着拖,甚至绕圈圈。

效果图如下(android虚拟机长宽为800*600):

Android 自定义控件-SnakeLayout (仿gallery) - Wallace - 懒羊羊的南瓜屋
Android 自定义控件-SnakeLayout (仿gallery) - Wallace - 懒羊羊的南瓜屋
(测试版)代码如下:
package com.Snake;
/*
* Author: Wallace Wang
* Email: wallage@qq.com
*/
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class SnakeLayout extends FrameLayout {
private static final String LOG_TAG = "SnakeLayout";
private GestureDetector mGestureDetector;
private SnakeOnGestureListener mGestureListener;
private List<View> ViewHolder;
private int selectImg;
private int totalViewNum;
private View mContentView;
private SnakeView ScrollView;
private Context mContext;
private enum State {
ABOUT_TO_ANIMATE,
ANIMATING,
ANIMATE_END,
READY,
TRACKING
};
private State mState;
private double aniStartPos;// Value = scrollNum + percent*direction;
private double aniStopPos;// Value = scrollNum + percent*direction;
private Date aniStartTime;
private long aniTime = 1000;
private double aniSpeed = 500;
private double aniDefG = 5;

private int mContentWidth = 0;
private int mContentHeight = 0;
private int clickItem = -1;
private int direction = 0;
private int movDirection = 0;
private double percent = 0;
private int scrollNum = 0;
private PathScale myPathViews;
private List<Bitmap> BmpRecViews;
private OnSelectListener selectListener;
private OnClickListener clickListener;
private int currentIndex = 0;
public SnakeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(LOG_TAG, "Init Snake Layout");
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.SnakeLayout);
selectImg = a.getInteger(R.styleable.SnakeLayout_selectImg, -1);
a.recycle();
mGestureListener = new SnakeOnGestureListener();
mGestureDetector = new GestureDetector(mGestureListener);
mGestureDetector.setIsLongpressEnabled(false);
BmpRecViews = new ArrayList<Bitmap>();
myPathViews = new PathScale();
mState = State.READY;
}
public void Init(){
for (int i = 0; i < totalViewNum; i++) {
ImageView v = (ImageView)ViewHolder.get(i);
v.setScaleType(ImageView.ScaleType.FIT_XY);
v.setImageBitmap(BmpRecViews.get((i + currentIndex)% BmpRecViews.size()));
}
}

public void addBitmap(Bitmap b){
if(b != null)
BmpRecViews.add(b);
}

public void addBitmap(Bitmap b, int position){
if(b != null)
BmpRecViews.add(position, b);
}

public void addRec(int rec){
Bitmap b = BitmapFactory.decodeResource(this.getResources(),rec);
if(b != null)
BmpRecViews.add(b);
}
......
代码太长,省略
res/values/attrs.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SnakeLayout">
<!-- Defines the special selected position Image -->
<attr name="selectImg" format="integer" />
</declare-styleable>
</resources>
res/values/ids.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="snakeImg0" />
<item type="id" name="snakeImg1" />
<item type="id" name="snakeImg2" />
<item type="id" name="snakeImg3" />
<item type="id" name="snakeImg4" />
<item type="id" name="snakeImg5" />
<item type="id" name="snakeImg6" />
<item type="id" name="snakeImg7" />
<item type="id" name="snakeImg8" />
<item type="id" name="snakeImg9" />
<item type="id" name="snakeImg10" />
<item type="id" name="snakeImg11" />
<item type="id" name="snakeImg12" />
<item type="id" name="snakeImg13" />
<item type="id" name="snakeImg14" />
<item type="id" name="snakeImg15" />
<item type="id" name="snakeImg16" />
<item type="id" name="snakeImg17" />
<item type="id" name="snakeImg18" />
<item type="id" name="snakeImg19" />
<item type="id" name="snakeImg20" />
<item type="id" name="snakeImg21" />
<item type="id" name="snakeImg22" />
<item type="id" name="snakeImg23" />
<item type="id" name="snakeImg24" />
<item type="id" name="snakeImg25" />
<item type="id" name="snakeImg26" />
<item type="id" name="snakeImg27" />
<item type="id" name="snakeImg28" />
<item type="id" name="snakeImg29" />
<item type="id" name="snakeContent" />
</resources>
主布局文件:main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:snake="http://schemas.android.com/apk/res/com.Snake"
android:orientation="vertical" android:background="@drawable/bj"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.Snake.SnakeLayout android:layout_width="fill_parent" android:layout_weight="1"
android:id="@+id/my_snake" android:layout_height="fill_parent"
snake:selectImg="7">
<LinearLayout android:layout_width="fill_parent" android:orientation="vertical"
android:layout_height="wrap_content" android:id="@id/snakeContent">
<LinearLayout android:layout_width="fill_parent" android:paddingTop="70dip"
android:layout_height="wrap_content">
<TextView android:layout_width="270dip" android:layout_height="1dip"/>
<ImageView android:layout_width="40dip" android:id="@id/snakeImg0"
android:layout_height="40dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="300dip" android:layout_height="1dip"/>
<ImageView android:layout_width="60dip" android:id="@id/snakeImg1"
android:layout_height="60dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="295dip" android:layout_height="1dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg2"
android:layout_height="50dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="290dip" android:layout_height="1dip"/>
<ImageView android:layout_width="35dip" android:id="@id/snakeImg3"
android:layout_height="35dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="290dip" android:layout_height="1dip"/>
<ImageView android:layout_width="35dip" android:id="@id/snakeImg4"
android:layout_height="35dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="292dip" android:layout_height="1dip"/>
<ImageView android:layout_width="40dip" android:id="@id/snakeImg5"
android:layout_height="40dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="320dip" android:layout_height="1dip"/>
<ImageView android:layout_width="40dip" android:id="@id/snakeImg6"
android:layout_height="40dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg7"
android:layout_height="55dip" android:paddingTop="15dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg8"
android:layout_height="55dip" android:paddingTop="15dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg9"
android:layout_height="55dip" android:paddingTop="15dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg10"
android:layout_height="50dip" android:paddingTop="10dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg11"
android:layout_height="40dip" android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg12"
android:layout_height="40dip" android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg13"
android:layout_height="50dip" android:paddingLeft="10dip"
android:paddingTop="10dip"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="260dip" android:layout_height="1dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg21"
android:layout_height="25dip"
android:paddingLeft="25dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg20"
android:layout_height="55dip" android:paddingTop="20dip"
android:paddingLeft="15dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg19"
android:layout_height="65dip" android:paddingTop="25dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg18"
android:layout_height="65dip" android:paddingTop="25dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg17"
android:layout_height="55dip" android:paddingTop="15dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="50dip" android:id="@id/snakeImg16"
android:layout_height="45dip" android:paddingTop="5dip"
android:paddingLeft="10dip"/>
<ImageView android:layout_width="45dip" android:id="@id/snakeImg15"
android:layout_height="35dip" android:paddingLeft="10dip"/>
<ImageView android:layout_width="45dip" android:id="@id/snakeImg14"
android:layout_height="35dip" android:paddingLeft="10dip"/>
</LinearLayout>
</LinearLayout>
</com.Snake.SnakeLayout>
</LinearLayout>
Snake.java 文件:
package com.Snake;
import android.app.Activity;
import android.os.Bundle;
public class Snake extends Activity {
/** Called when the activity is first created. */
SnakeLayout mSnake;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

mSnake = (SnakeLayout)findViewById(R.id.my_snake);
mSnake.addRec(R.drawable.png1);
mSnake.addRec(R.drawable.png2);
mSnake.addRec(R.drawable.png3);
mSnake.addRec(R.drawable.png4);
mSnake.addRec(R.drawable.png5);
mSnake.addRec(R.drawable.png6);
mSnake.addRec(R.drawable.png7);
mSnake.addRec(R.drawable.png8);
mSnake.addRec(R.drawable.png9);
mSnake.addRec(R.drawable.png10);
mSnake.addRec(R.drawable.png11);
mSnake.addRec(R.drawable.png12);
mSnake.addRec(R.drawable.png13);
mSnake.addRec(R.drawable.png14);
mSnake.addRec(R.drawable.png15);
mSnake.addRec(R.drawable.png16);
mSnake.addRec(R.drawable.png17);
mSnake.addRec(R.drawable.png18);
mSnake.addRec(R.drawable.png19);
mSnake.addRec(R.drawable.png20);
mSnake.addRec(R.drawable.png21);
mSnake.addRec(R.drawable.png22);
mSnake.addRec(R.drawable.png23);
mSnake.addRec(R.drawable.png24);
mSnake.addRec(R.drawable.png25);
mSnake.addRec(R.drawable.png26);
mSnake.addRec(R.drawable.png27);
mSnake.addRec(R.drawable.png28);
mSnake.Init();
}
}
分享到:
评论

相关推荐

    自定义组件:SnakeLayout

    NULL 博文链接:https://gundumw100.iteye.com/blog/1045660

    用SnakeLayout实现纵向Gallery完整代码

    用SnakeLayout实现纵向Gallery完整代码,如果修改布局文件,还可以实现横向,斜向,不规则向等翻动。 另向SnakeLayout作者致敬。

    FlexLayouts 布局

    Flex 自定义布局 FlowLayout SnakeLayout CircleLayout RectangleLayout 官方下载地址:http://flexlayouts.org/download/

    自定义布局 FlexLayouts 源码

    FlexLayouts 自定义布局源码 src\org\flexlayouts\layouts\CircleLayout.as src\org\flexlayouts\layouts\FlowLayout.as src\org\flexlayouts\layouts\RectangleLayout.as src\org\flexlayouts\layouts\SnakeLayout....

    毕业设计基于STC12C5A、SIM800C、GPS的汽车防盗报警系统源码.zip

    STC12C5A通过GPS模块获取当前定位信息,如果车辆发生异常震动或车主打来电话(主动请求定位),将通过GSM发送一条定位短信到车主手机,车主点击链接默认打开网页版定位,如果有安装高德地图APP将在APP中打开并展示汽车当前位置 GPS模块可以使用多家的GPS模块,需要注意的是,当前程序对应的是GPS北斗双模芯片,故只解析 GNRMC数据,如果你使用GPS芯片则应改为GPRMC数据即可。 系统在初始化的时候会持续短鸣,每初始化成功一部分后将长鸣一声,如果持续短鸣很久(超过20分钟),建议通过串口助手查看系统输出的调试信息,系统串口默认输出从初始化开始的所有运行状态信息。 不过更建议你使用SIM868模块,集成GPS.GSM.GPRS,使用更加方便

    基于tensorflow2.x卷积神经网络字符型验证码识别.zip

    基于tensorflow2.x卷积神经网络字符型验证码识别 卷积神经网络(Convolutional Neural Networks, CNNs 或 ConvNets)是一类深度神经网络,特别擅长处理图像相关的机器学习和深度学习任务。它们的名称来源于网络中使用了一种叫做卷积的数学运算。以下是卷积神经网络的一些关键组件和特性: 卷积层(Convolutional Layer): 卷积层是CNN的核心组件。它们通过一组可学习的滤波器(或称为卷积核、卷积器)在输入图像(或上一层的输出特征图)上滑动来工作。 滤波器和图像之间的卷积操作生成输出特征图,该特征图反映了滤波器所捕捉的局部图像特性(如边缘、角点等)。 通过使用多个滤波器,卷积层可以提取输入图像中的多种特征。 激活函数(Activation Function): 在卷积操作之后,通常会应用一个激活函数(如ReLU、Sigmoid或tanh)来增加网络的非线性。 池化层(Pooling Layer): 池化层通常位于卷积层之后,用于降低特征图的维度(空间尺寸),减少计算量和参数数量,同时保持特征的空间层次结构。 常见的池化操作包括最大池化(Max Pooling)和平均池化(Average Pooling)。 全连接层(Fully Connected Layer): 在CNN的末端,通常会有几层全连接层(也称为密集层或线性层)。这些层中的每个神经元都与前一层的所有神经元连接。 全连接层通常用于对提取的特征进行分类或回归。 训练过程: CNN的训练过程与其他深度学习模型类似,通过反向传播算法和梯度下降(或其变种)来优化网络参数(如滤波器权重和偏置)。 训练数据通常被分为多个批次(mini-batches),并在每个批次上迭代更新网络参数。 应用: CNN在计算机视觉领域有着广泛的应用,包括图像分类、目标检测、图像分割、人脸识别等。 它们也已被扩展到处理其他类型的数据,如文本(通过卷积一维序列)和音频(通过卷积时间序列)。 随着深度学习技术的发展,卷积神经网络的结构和设计也在不断演变,出现了许多新的变体和改进,如残差网络(ResNet)、深度卷积生成对抗网络(DCGAN)等。

    【三维装箱】遗传和模拟退火算法求解三维装箱优化问题【含Matlab源码 031期】.zip

    【三维装箱】遗传和模拟退火算法求解三维装箱优化问题【含Matlab源码 031期】.zip

    自己编写的python 程序计算cpk/ppk

    cpk&ppk python 小程序,品友点评

    基于Springboot开发的分布式抽奖系统.zip

    基于springboot的java毕业&课程设计

    课设毕设基于SpringBoot+Vue的影城管理系统 LW+PPT+源码可运行.zip

    课设毕设基于SpringBoot+Vue的影城管理系统 LW+PPT+源码可运行.zip

    MC教育版(免登录版)

    MC教育版(免登录版)

    农作物叶片病害分类和分割数据集【数据集+标签】

    包含13993张数据和对应的13993张mask分割模版,数据集用不同目录保存,也可以用作分类数据集 类别包含:桃子、辣椒、覆盆子、大豆、南瓜、草莓

    基于vue+springboot二手交易网站.zip

    基于springboot的java毕业&课程设计

    【三维装箱】遗传算法求解三维装箱优化问题【含Matlab源码 3408期】.zip

    【三维装箱】遗传算法求解三维装箱优化问题【含Matlab源码 3408期】.zip

    基于javaspring 开发框架的培训教程 TP1.zip

    基于javaspring 开发框架的培训教程 TP1.zip

    信号和系统 MATLAB 代码:探索信号生成、系统建模、傅立叶分析、滤波器设计、采样和控制系统仿真.zip

    1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    医院网上预约系统设计与开发/毕业设计

    医院网上预约系统设计与开发/毕业设计 JSP基于SSM网上医院预约挂号系统 科室信息: 科室id,科室名称,科室介绍,成立日期,负责人 医生信息: 医生工号,登录密码,所在科室,医生姓名,性别,医生照片,出生日期,医生职位,工作经验,联系方式,擅长,医生介绍 病人信息: 病人id,医生,病人姓名,性别,身份证号,联系电话,病人病例,登记时间 预约信息: 预约id,预约用户,预约医生,预约日期,时段,联系电话,下单时间,处理状态,医生回复 新闻信息: 新闻id,新闻标题,新闻图片,新闻内容,新闻日期,新闻来源 留言: 留言id,留言标题,留言内容,留言人,留言时间,管理回复,回复时间 用户: 用户名,登录密码,姓名,性别,出生日期,用户照片,联系电话,邮箱,家庭地址,注册时间

    企业数据治理之数据质量治理方案.pptx

    企业数据治理之数据质量治理方案

    MySQL8.4.0 LTS(mysql-8.4.0-10.fc38.x86-64.rpm-bundle.tar)

    MySQL8.4.0 LTS(mysql-8.4.0-10.fc38.x86_64.rpm-bundle.tar)适用于Linux Fedora 38 (x86, 64-bit)

    1659 jsp游乐园管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目源码

    一、源码特点 java 医疗数据管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助采用了数据模型进行区块链设计,系统具有完整的源代码和数据库,系统采用web模式,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使用java语言开发。 二、功能介绍 如博客中介绍 三、注意事项 1、管理员账号:admin 密码:admin 数据库配置文件DBO.java ,权限包括管理员,用户 2、开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql,使用java语言开发。 3、数据库文件名是jspyly 系统名称yly 4、地址:http://127.0.0.1:8080/yly/qt/index.jsp

Global site tag (gtag.js) - Google Analytics