这篇文章主要为大家详细介绍了机器人使用水平滚动视图实现水平滚动,并点击有相应的反应效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
水平滚动视图和滚动视图都是由框架布局派生出来的。它们就是一个用于为普通组件添加滚动条的组件。且水平滚动视图和滚动视图里面最多只能包含一个组件(当然组件里面还可以嵌套组件)。它们不同的是水平滚动视图用于添加水平滚动,而滚动视图用于添加垂直滚动。
突然间想到做一个屏幕下方水平滑动,屏幕上方并作出相应的反应的效果。只是在下方滚动时,屏幕上方没有作出理想的反应,点击事件倒是实现了。最终只能在网上搜索,终于找到了一个。于是作出的效果如下:
只是这个效果还有所缺陷,加载了13 张图片,在屏幕下方水平滚动到最后一页时,第9 张的图片并没有在上面的显示出来(原作者的也有这个问题);如果图片的数量小于或者等于四张时则不能运行。
本例的难点主要在于我的水平视图类中,并且还有收集而来的注解。
MainActivity.java:
包com。疯狂。horizontalscrollviewtest
导入Java。io。inputstream
导入Java。util。ArrayList
导入Java。util。数组;
导入Java。util。列表;
导入com。疯狂。horizontalscrollviewtest。我的水平视图。currentimagechangelistener
导入com。疯狂。horizontalscrollviewtest。我的水平视图。onitemclicklistener
导入安卓。内容。语境;
导入安卓。图形。位图;
导入安卓。图形。bitmapfactory
导入安卓。图形。颜色;
导入安卓。OS。捆绑;
导入安卓。util。日志;
导入安卓。查看。查看;
导入安卓。小部件。imageview
导入安卓。支持。V7。app。app compat活动;
公共类主要活动扩展AppCompatActivity {
私有图像视图mImageView
私人我的水平视图我的水平视图;
私有列表位图位图列表
私有我的适配器适配器;
@覆盖
受保护的void onCreate(Bundle saved instancestate){
超级棒。oncreate(savedInstanceState);
setContentView(r . layout。活动_主);
init();
}
私有void init() {
mimage view=(ImageView)findViewById(r . id。ImageView);
bitmapList=新数组列表(数组。阿斯利斯特(
readBitMap(this,R.drawable.bricks),
readBitMap(this,R.drawable.dog),
readBitMap(this,R.drawable.flower),
readBitMap(this,R.drawable.grass),
readBitMap(this,R.drawable.stones),
readBitMap(this,R.drawable.wood),
readBitMap(this,R.drawable.bg_01),
readBitMap(this,R.drawable.bg_02),
readBitMap(this,R.drawable.bg_03),
readBitMap(this,R.drawable.bg_04),
readBitMap(this,R.drawable.bg_05),
readBitMap(this,R.drawable.bg_06),
readBitMap(this,R.drawable.bg_07)
));
我的水平视图=(我的水平视图)findViewById(r . id。我的_横);
adapter=new MyAdapter(this,bitmapList);
//设置适配器
myHorizontalView.initDatas(适配器);
//添加滚动回调
我的水平视图。setCurrentImageChangeListener(new CurrentImageChangeListener(){
@覆盖
public void onCurrentImgChanged(int position,View viewIndicator) {
Log.e('============','============'位置);
图像视图。setimage位图(位图列表。get(位置));
查看指示器。设置背景颜色(颜色。解析颜色(# aa 024 da 4));
}
});
//添加点击回调
我的水平视图。setonitemclicklistener(new OnItemClickListener(){
@覆盖
public void onItemClick(View view,int position) {
图像视图。setimage位图(位图列表。get(位置));
查看。设置背景颜色(颜色。解析颜色(# aa 024 da 4 ');
}
});
}
公共静态位图readBitMap(Context mContext,int resId) {
位图工厂Options opt=new BitmapFactory .options();
opt.inPreferredConfig=Bitmap .配置。RGB _ 565
opt.inPurgeable=true
opt.inInputShareable=true
InputStream是=m上下文。获取资源().openRawResource(resId);
返回BitmapFactory.decodeStream(is,null,opt);
}
}
我的适配器这部分并不是为抽象视图和AbsSpinner及其子类提供列表项的。它主要用于为水平滚动视图提供数据。
MyAdapter.java:
包com。疯狂。horizontalscrollviewtest
导入Java。util。ArrayList
导入Java。util。列表;
导入安卓。内容。语境;
导入安卓。图形。位图;
导入安卓。util。日志;
导入安卓。查看。查看;
导入安卓。查看。查看组;
导入安卓。小部件。基本适配器;
导入安卓。小部件。imageview
导入安卓。小部件。相对布局;
/**
*由反物质于2016年一月9日创建。
*/
公共类我的适配器扩展基本适配器{
私有列表位图位图列表
私有上下文mContext
公共我的适配器(上下文上下文,列表位图位图列表){
mContext=上下文;
if (bitmapList==null) {
bitmap list=new ArrayList bitmap();
}否则{
this.bitmapList=bitmapList
}
}
@覆盖
public int getCount() {
返回位图列表。size();
}
@覆盖
公共对象getItem(int position) {
返回位图列表。get(位置);
}
@覆盖
public long getItemId(int position){
返回位置;
}
@覆盖
公共视图getView(int position,View convertView,ViewGroup parent) {
视图持有者视图持有者=空
视图视图=空
//此处要用相对布局,且与可扩展标记语言中的布局相同;
//如果使用线性布局,则显示不完整
相对布局布局;
if (convertView==null) {
布局=(相对布局)视图。inflate(m context,R.layout.image_item_layout,null);
view holder=new view holder();
视图支架。image=(ImageView)布局。findviewbyid(r . id。top _ image);
布局。settag(视图持有者);
}否则{
layout=(相对布局)转换视图;
视图=布局;
视图支架=(视图支架)布局。gettag();
Log.e('MyAdapter ','正在检测数据来了没有');
}
Bitmap btm=(Bitmap)getItem(position);
视图支架。形象。setimagebitmap(btm);
Log.e('MyAdapter ','信息来了哦!');
返回布局;
}
私有静态类视图容器{
图像视图图像;
}
}
我的水平视图类主要用于未维护活动类提供接口、水平滚动时屏幕上方的反应及相应的点击事件等。该类主要使用了收集而来的代码,并做了相应的调整。
MyHorizontalView.java:
包com。疯狂。horizontalscrollviewtest
导入Java。util。hashmap
导入Java。util。地图;
导入安卓。app。活动;
导入安卓。内容。语境;
导入安卓。图形。颜色;
导入安卓。util。attributeset
导入安卓。util。显示指标;
导入安卓。util。日志;
导入安卓。查看。运动事件;
导入安卓。查看。查看;
导入安卓。查看。查看组;
导入安卓。小部件。horizontalscrollview
/**
*由反物质于2016年一月9日创建。
*/
公共类我的水平视图扩展了水平滚动视图
实现视图OnClickListener {
private String TAG=' MyHorizontalView ';
私有视图组父级;
私人(同Internationalorganizations)国际组织屏幕宽度;
/* 当前最后一张图片的索引*/
私有int mCurrentIndex
/* 当前第一张图片的下标*/
私有int mFristIndex
/* 每屏幕最多显示的个数*/
private int mCountOneScreen
/* 子元素的宽度*/
private int mChildWidth
/* 子元素的高度*/
private int mChildHeight
二等兵我的适应者
private CurrentImageChangeListener m侦听器;
private OnItemClickListener monitemclistener;
/**
* 图片滚动时的回调接口
*/
公共接口CurrentImageChangeListener {
void onCurrentImgChanged(int position,View视图指示器);
}
/**
* 点击条目时的回调
*/
公共接口OnItemClickListener {
void onItemClick(View view,int pos);
}
/* 保存视角与位置的键值对*/
private MapView,Integer mViewPos=new HashMap();
公共我的水平视图(上下文上下文){
这(上下文,空);
}
公共我的水平视图(上下文上下文,属性集属性){
this(context,attrs,0);
}
公共myhorizontal视图(上下文Context,AttributeSet attrs,int defStyleAttr) {
super(context,attrs,defStyleAttr);
这个。setsmoothscrollingenabled(true);
显示指标metrics=新显示指标();
//取得窗口属性
((活动)上下文)。getWindowManager().getDefaultDisplay().getMetrics(度量);
//窗口的宽度(像素)
屏幕宽度=metrics.widthPixels像素像素;
}
/**
* 初始化数据,设置数据适配器
*/
公共void初始化数据(我的适配器适配器){
if (getChildCount()==0) {
Log.e(标签,'必须要有子元素');
}
if(get child count()==0 | | m adapter==null)
返回;
this.mAdapter=mAdapter
parent=(视图组)get child at(0);
//获得适配器中第一个视角
最终视图视图=ma适配器。获取视图(0,null,parent);
parent.addView(视图);
//strong制计算当前视角的宽和高
if(m子宽度==0m子高度==0){
int w=View .测量规格。makemasurespec(0,
查看。未指定的测量规格);
int h=View .测量规格。makemasurespec(0,
查看。未指定的测量规格);
view.measure(w,h);
mChildHeight=视图。getmeasuredheight();
mChildWidth=视图。getmeasuredwidth();
Log.e(标签,'子组件的宽:' mChildWidth ',子组件的高:' mChildHeight);
//计算每次加载多少个视角
mCountOneScreen=屏幕宽度/mchild宽度2;
Log.e(标记,' mCountOneScreen=' mCountOneScreen
,mChildWidth=' mChildWidth);
}
//初始化第一屏幕的元素
加载第一个孩子(mcountonscreen);
}
/**
* 加载第一屏的视角
*/
public void load first child(int mCountOneScreen){
父母。删除所有视图();
mviewpos。clear();
for(int I=0;i mCountOneScreeni ) {
View view=mAdapter.getView(i,null,parent);
查看。setonclicklistener(this);
parent.addView(视图);
mViewPos.put(view,I);
mCurrentIndex=I;
}
if (mListener!=null) {
notifyCurrentImageChanged();
}
}
@覆盖
公共布尔onTouchEvent(运动事件事件){
switch (event.getAction()) {
案例运动事件。动作_移动:
int scrollX=getScrollX();
//如果当前卷轴为视角的宽度,加载下一张,移除第一张
if(scrollX=mchildwight){
load nextimage();
}
//如果当前scrollX=0,往前设置一张,移除最后一张
if (scrollX==0) {
loadPreImage();
}
打破;
}
//这里无论返回值是设置真实的还是错误的
//HorizontalScrollView都不会滑动
返回super.onTouchEvent(事件);
}
/**
* 加载下一张图片
*/
受保护的void loadNextImage() {
//数组边界值计算
if(mCurrentIndex==m适配器。get count()-1){
返回;
}
//移除第一张图片,且将水平滚动位置置0(图片有宽度,所以为置0)
scrollTo(0,0);
mviewpos。移除(父。在(0)处获取子级);
父母。删除位于(0)的视图;
//获取下一张图片,并且设置onClick事件,且加入容器中
视图视图=ma适配器。get view(mCurrentIndex,null,parent);
Log.e(标签,' mCurrentIndex===' mCurrentIndex);
查看。setonclicklistener(this);
parent.addView(视图);
mViewPos.put(view,mCurrentIndex);
//当前第一张图片小标
制造指数
//如果设置了滚动监听则触发
if (mListener!=null) {
notifyCurrentImageChanged();
}
}
/**
* 加载前一张图片
*/
受保护的void loadPreImage() {
//如果当前已经是第一张,则返回
if (mFristIndex==0)
返回;
//获得当前应该显示为第一张图片的下标
int index=mCurrentIndex-mCountOneScreen;
if (index=0) {
//移除最后一张
int oldViewPos=parent。获取子计数()-1;
mviewpos。移除(父。在(oldViewPos))处获取子级;
父母。删除viewat(oldViewPos);
//将此视角放入第一个位置
视图视图=ma适配器。获取视图(索引,空,父);
mViewPos.put(视图,索引);
parent.addView(视图,0);
查看。setonclicklistener(this);
//水平滚动位置向左移动视角的宽度个像素
scrollTo(mChildWidth,0);
//当前位置- ,当前第一个显示的下标-
mCurrentIndex-;
mFristIndex-;
//回调
if (mListener!=null) {
notifyCurrentImageChanged();
}
}
}
/**
* 滑动时的回调
*/
public void notifyCurrentImageChanged(){
int sum=parent。获取子计数();
for(int I=0;我求和;i ) {
//清除所有的背景色,点击时会设置为蓝色
parent.getChildAt(i).setBackgroundColor(颜色。白色);
}
m听众。oncurrentimgchanged(制造商istindex,父级。在(0)处获取子级);
}
@覆盖
公共void onClick(视图五){
if(monitemclistener!=null) {
int sum=parent。获取子计数();
for(int I=0;我求和;i ) {
parent.getChildAt(i).setBackgroundColor(颜色。白色);
}
moniteclicklistener。onitemclick(v,mviewpos。get(v));
}
}
public void setOnItemClickListener(OnItemClickListener mOnClickListener){
这个。monitemcliclistener=mOnClickListener;
}
public void setCurrentImageChangeListener(CurrentImageChangeListener m listener){
这个。m监听器=m监听器;
}
}
该类中的很多数据都在目录集合里面,而集合的下标初始值为0,与list.size()不相等。顾猜测,正是由于这个原因,在mImageView显示图片时,不能显示到第9 张。
在这个类中计算每次加载多少个视角时的mCountOneScreen计算方法感觉略有问题,从效果图中可以看出,屏幕中能加载3张多一点的图片mCountOneScreen=屏幕宽度/mchild width 2;在我的模拟器上计算得出的结果等于5,也就是为什么不能加载小于等于四张图片,如果想要让该屏幕底部上只显示3张即一个屏幕也就能显示完。那就不用水平滚动了,那样就感觉使用水平滚动视图失去了意义。
所用到的布局文件:
content_main.xml:
?可扩展标记语言版本='1.0 '编码='utf-8 '?
相对布局xmlns:Android=' http://模式。安卓。' com/apk/RES/Android '
xmlns:app=' http://模式。安卓。' com/apk/RES-auto '
xmlns:tools=' http://模式。安卓。' com/tools '
Android:layout _ width=' match _ parent '
Android:layout _ height=' match _ parent '
android:paddingLeft='5dp '
android:paddingTop='5dp '
android:paddingRight='5dp '
android:paddingBottom='5dp '
app:layout _ behavior=' @ string/app bar _ scrolling _ view _ behavior '
工具:context=' com。疯狂。horizontalscrollviewtest。'主要活动'
工具:showIn='@layout/activity_main '
图像视图
android:id='@ id/imageView '
Android:layout _ width=' match _ parent '
android:layout_height='380dp '
Android:scale type='中心裁剪'/
com。疯狂。horizontalscrollviewtest。我的水平视图
android:id='@ id/my_horizontal '
Android:layout _ below=' @ id/imageView '
Android:layout _ alignParentBottom=' true '
安卓系统:滚动条='无'
Android:layout _ width=' match _ parent '
Android:layout _ height=' wrap _ content '
线性布局
android:id='@ id/linear_layout '
安卓:方向='水平'
Android:layout _ gravity=' center _ vertical '
Android:layout _ width=' wrap _ content '
Android:layout _ height=' wrap _ content '
/线性布局
/com。疯狂。horizontalscrollviewtest。我的水平视图
/RelativeLayout
image_item_layout.xml主要用于提供水平滚动的图片(屏幕底部)):
?可扩展标记语言版本='1.0 '编码='utf-8 '?
相对布局xmlns:Android=' http://模式。安卓。' com/apk/RES/Android '
Android:layout _ width=' match _ parent '
Android:layout _ height=' match _ parent '
安卓:方向='垂直'
图像视图
android:id='@ id/top_image '
Android:layout _ width=' wrap _ content '
Android:layout _ height=' wrap _ content '
android:layout_margin='10dp '
Android:scale type='中心裁剪'/
/RelativeLayout
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。