【转】Android android listview的HeadView左右切换图片(仿新浪,网易,百度等切换图片)...
首先我们还是看一些示例:(网易,新浪,百度)
下面我简单的介绍下实现方法:其实就是listview addHeaderView.只不过这个view是一个可以切换图片的view,至于这个view怎么做,就要根据自己的喜爱了,实现有多种方法,下面我简单介绍一下.
第一种:ViewFlipper+GestureDetector
主布局就是一个listview,这里就不介绍了,我介绍下切换图片布局head_iamge.xml
1 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <FrameLayout 8 android:id="@+id/fl_main" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" > 11 12 <ViewFlipper 13 android:id="@+id/ViewFlipper01" 14 android:layout_width="fill_parent" 15 android:layout_height="fill_parent" > 16 </ViewFlipper> 17 18 <LinearLayout 19 android:id="@+id/ll_point" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:layout_gravity="bottom|center_horizontal" 23 android:layout_marginBottom="10dp" 24 android:src="@drawable/indicator" /> 25 </FrameLayout> 26 27 </LinearLayout></span>
这里我就添加一系列切换点,至于显示新闻标题,透明效果等等,大家可以自己布局,方法同理,不难实现.
接下来我们看动画布局.
push_left_in.xml
1 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?> 2 <set xmlns:android="http://schemas.android.com/apk/res/android" 3 android:fillAfter="true" > 4 5 <translate 6 android:duration="500" 7 android:fromXDelta="-100%p" 8 android:toXDelta="0" /> 9 10 <alpha 11 android:duration="500" 12 android:fromAlpha="0.1" 13 android:toAlpha="1.0" /> 14 15 </set></span>
push_left_out.xml
1 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?> 2 <set xmlns:android="http://schemas.android.com/apk/res/android" > 3 4 <translate 5 android:duration="500" 6 android:fromXDelta="0" 7 android:toXDelta="-100%p" /> 8 9 <alpha 10 android:duration="500" 11 android:fromAlpha="1.0" 12 android:toAlpha="0.5" /> 13 14 </set></span>
push_right_in.xml
1 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?> 2 <set xmlns:android="http://schemas.android.com/apk/res/android" 3 android:fillAfter="true" > 4 5 <translate 6 android:duration="500" 7 android:fromXDelta="100%p" 8 android:toXDelta="0" /> 9 10 <alpha 11 android:duration="500" 12 android:fromAlpha="0.1" 13 android:toAlpha="1.0" /> 14 15 </set></span>
push_right_out.xml
1 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?> 2 <set xmlns:android="http://schemas.android.com/apk/res/android" > 3 4 <translate 5 android:duration="500" 6 android:fromXDelta="0" 7 android:toXDelta="100%p" /> 8 9 <alpha 10 android:duration="500" 11 android:fromAlpha="1.0" 12 android:toAlpha="0.5" /> 13 14 </set></span>
我简单介绍下这些布局:
push_left_in:左边进入,则要进入的view初始位置在-100%p位置,终止位置在0,而push_left_out:左边出来,则此时view的位置在0,而终止位置在-100%p.
右进右出同理,至于alpha渐变,很简单,动画就说道这里,相信了解动画的同学们不用看就ok了.
下面重点是如何实现.
代码:
1 <span style="font-size:12px;">package com.jj.chage2; 2 3 import java.util.ArrayList; 4 import java.util.Timer; 5 import java.util.TimerTask; 6 7 import android.app.Activity; 8 import android.content.Context; 9 import android.graphics.Bitmap; 10 import android.graphics.BitmapFactory; 11 import android.graphics.Matrix; 12 import android.os.Bundle; 13 import android.util.Log; 14 import android.view.GestureDetector; 15 import android.view.LayoutInflater; 16 import android.view.MotionEvent; 17 import android.view.View; 18 import android.view.ViewGroup; 19 import android.view.View.OnTouchListener; 20 import android.view.animation.AnimationUtils; 21 import android.widget.AdapterView; 22 import android.widget.AdapterView.OnItemClickListener; 23 import android.widget.Button; 24 import android.widget.ImageView.ScaleType; 25 import android.widget.LinearLayout.LayoutParams; 26 import android.widget.ArrayAdapter; 27 import android.widget.FrameLayout; 28 import android.widget.ImageView; 29 import android.widget.LinearLayout; 30 import android.widget.ListView; 31 import android.widget.TextView; 32 import android.widget.Toast; 33 import android.widget.ViewFlipper; 34 35 public class MainActivity extends Activity implements 36 GestureDetector.OnGestureListener { 37 private GestureDetector detector; 38 private ViewFlipper flipper; 39 private int image_id[] = { R.drawable.a, R.drawable.b, R.drawable.c }; 40 private ListView lv_main; 41 private LayoutInflater layoutInflater; 42 private LinearLayout ll_point; 43 private FrameLayout frameLayout; 44 private final String msg[] = { "one", "two", "three", "four", "five", 45 "six", "seven" }; 46 private int frameheight;// 图片的高度 47 private int window_width;// 屏幕宽度 48 private ArrayList<ImageView> imageViews;// ponit 集合 49 private ArrayList<View> views;// flipper的孩子 50 private Timer timer; 51 52 /*** 53 * 初始化 point 54 */ 55 void initPoint() { 56 imageViews = new ArrayList<ImageView>(); 57 ImageView imageView; 58 for (int i = 0; i < image_id.length; i++) { 59 imageView = new ImageView(this); 60 imageView.setBackgroundResource(R.drawable.indicator); 61 LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 62 new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, 63 LayoutParams.WRAP_CONTENT)); 64 layoutParams.leftMargin = 10; 65 layoutParams.rightMargin = 10; 66 ll_point.addView(imageView, layoutParams); 67 imageViews.add(imageView); 68 } 69 70 } 71 72 /*** 73 * ChildView 74 */ 75 void initChildView(ViewFlipper flipper) { 76 views = new ArrayList<View>(); 77 LayoutParams layoutParams = new LayoutParams(LayoutParams.FILL_PARENT, 78 LayoutParams.FILL_PARENT); 79 for (int i = 0; i < image_id.length; i++) { 80 ImageView imageView = new ImageView(this); 81 imageView.setScaleType(ScaleType.FIT_XY); 82 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), 83 image_id[i]); 84 Bitmap bitmap2 = getBitmap(bitmap, window_width); 85 frameheight = bitmap2.getHeight();// 获取要显示的高度 86 imageView.setImageResource(image_id[i]); 87 flipper.addView(imageView, layoutParams); 88 views.add(imageView); 89 } 90 initPoint(); 91 } 92 93 /*** 94 * 初始化 HeadImage 95 */ 96 void initHeadImage() { 97 layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 98 View headview = layoutInflater.inflate(R.layout.head_image, null); 99 100 flipper = (ViewFlipper) headview.findViewById(R.id.ViewFlipper01); 101 102 ll_point = (LinearLayout) headview.findViewById(R.id.ll_point); 103 frameLayout = (FrameLayout) headview.findViewById(R.id.fl_main); 104 initChildView(flipper); 105 106 LayoutParams layoutParams = (LayoutParams) frameLayout 107 .getLayoutParams(); 108 layoutParams.height = frameheight; 109 frameLayout.setLayoutParams(layoutParams); 110 draw_Point(0);// 默认首次进入 111 lv_main.addHeaderView(headview);// 要卸载setAdapter前面 112 lv_main.setAdapter(new ArrayAdapter<String>(this, 113 android.R.layout.simple_list_item_1, msg)); 114 115 } 116 117 /*** 118 * init view 119 */ 120 void initView() { 121 setTitle("jjhappyforever..."); 122 setContentView(R.layout.main); 123 lv_main = (ListView) findViewById(R.id.lv_main); 124 lv_main.setOnItemClickListener(new OnItemClickListener() { 125 126 @Override 127 public void onItemClick(AdapterView<?> parent, View view, 128 int position, long id) { 129 130 if (position != 0) 131 Toast.makeText(MainActivity.this, msg[position - 1], 1) 132 .show(); 133 else { 134 int index = getPageIndex(flipper.getCurrentView()); 135 Toast.makeText(MainActivity.this, "图" + index, 1).show(); 136 137 } 138 139 } 140 }); 141 initHeadImage(); 142 } 143 144 /*** 145 * 更新选中点 146 * 147 * @param index 148 */ 149 private void draw_Point(int index) { 150 for (int i = 0; i < imageViews.size(); i++) { 151 imageViews.get(i).setImageResource(R.drawable.indicator); 152 } 153 imageViews.get(index).setImageResource(R.drawable.indicator_focused); 154 } 155 156 @Override 157 public void onCreate(Bundle savedInstanceState) { 158 super.onCreate(savedInstanceState); 159 setContentView(R.layout.main); 160 // 获取屏幕的宽度 161 window_width = (int) getResources().getDimension(R.dimen.window_width); 162 detector = new GestureDetector(this); 163 initView(); 164 165 timer = new Timer(true); 166 timer.schedule(new TimerTask() { 167 @Override 168 public void run() { 169 runOnUiThread(new Runnable() { 170 @Override 171 public void run() { 172 173 int pageIndex = getPageIndex(flipper.getCurrentView()); 174 175 if (pageIndex == flipper.getChildCount() - 1) 176 pageIndex = 0; 177 else 178 pageIndex++; 179 180 flipper.setInAnimation(AnimationUtils.loadAnimation( 181 MainActivity.this, R.anim.push_right_in)); 182 flipper.setOutAnimation(AnimationUtils.loadAnimation( 183 MainActivity.this, R.anim.push_left_out)); 184 flipper.showNext(); 185 draw_Point(pageIndex); 186 187 } 188 }); 189 } 190 }, 5000, 5000); 191 192 } 193 194 /*** 195 * 对图片处理 196 * 197 * @author zhangjia 198 * 199 */ 200 Bitmap getBitmap(Bitmap bitmap, int width) { 201 int w = bitmap.getWidth(); 202 int h = bitmap.getHeight(); 203 Matrix matrix = new Matrix(); 204 float scale = (float) width / w; 205 // 保证图片不变形. 206 matrix.postScale(scale, scale); 207 // w,h是原图的属性. 208 return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true); 209 } 210 211 @Override 212 public boolean dispatchTouchEvent(MotionEvent ev) { 213 this.detector.onTouchEvent(ev); 214 return super.dispatchTouchEvent(ev); 215 } 216 217 @Override 218 public boolean onDown(MotionEvent e) { 219 return true; 220 } 221 222 /*** 223 * 返回当前第几屏 224 */ 225 int getPageIndex(View view) { 226 for (int i = 0; i < views.size(); i++) { 227 if (view == views.get(i)) 228 return i; 229 } 230 return 0; 231 232 } 233 234 /** 235 * 监听滑动 236 */ 237 @Override 238 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 239 float velocityY) { 240 int pageIndex = getPageIndex(flipper.getCurrentView()); 241 242 // 左划 243 if (e1.getX() - e2.getX() > 120) { 244 this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, 245 R.anim.push_right_in)); 246 this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, 247 R.anim.push_left_out)); 248 this.flipper.showNext(); 249 if (pageIndex == flipper.getChildCount() - 1) 250 draw_Point(0); 251 else 252 draw_Point(++pageIndex); 253 return true; 254 // 右划 255 } else if (e1.getX() - e2.getX() < -120) { 256 this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, 257 R.anim.push_left_in)); 258 this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, 259 R.anim.push_right_out)); 260 this.flipper.showPrevious(); 261 if (pageIndex == 0) 262 draw_Point(flipper.getChildCount() - 1); 263 else 264 draw_Point(--pageIndex); 265 return true; 266 } 267 return true; 268 } 269 270 @Override 271 public void onLongPress(MotionEvent e) { 272 273 } 274 275 @Override 276 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, 277 float distanceY) { 278 return false; 279 } 280 281 @Override 282 public void onShowPress(MotionEvent e) { 283 284 } 285 286 @Override 287 public boolean onSingleTapUp(MotionEvent e) { 288 return false; 289 } 290 291 }</span>
上诉代码写的有点小乱,别介意.
效果:
你可以手势左右滑动图片切换,由于我们加入了动画,则在切换图片效果会比较人性,这一 点比较不错.另外一点,我开启了timer,让它自己切换,感觉这点比较不错,可惜好多应用都没有这么搞,总之实现就行了,我们开发人员嘛,就是开发别人 想出来的东西,感慨程序员苦逼...
如果你按照上诉操作的话会有几个问题:1,我移动图片下面的item图片也会切换,2,我在滑动切换图片的时候偶尔也会执行onclick事件,这两点bug严重不允许,为之我也煞费神经细胞啊,没办法因为基础不好,对触摸种种事件还是搞不明白,有时间了还得在看看研究研究,扯远了,下面我说下解决方法:
第一:我只让listview的第一项监听手势操作,其他的不执行.
方法很简单,自定义一个listview.重写其onTouchEvent事件.
@Overridepublic boolean onTouchEvent(MotionEvent ev) {Log.e("jj", "onTouchEvent...");int x = (int) ev.getX();int y = (int) ev.getY();int position = pointToPosition(x, y);// 只有headview才进行手势操作.if (position == 0) {// 注入手势 gestureDetector.onTouchEvent(ev);}return super.onTouchEvent(ev);}
大家一看就明白了,我们只对position==0进行手势监听,也 许有人问了,其实也可以直接在MainActivity中的dispatchTouchEvent分发事件中获取点击listview的 position,可是这样不准确,我点击第0项获取的有的是0,有的是1,原因目前不明,不过但可以肯定,这样是能获取listview的 position的,所以就干脆自定义吧,这样不会出错.这样解决了不会滑动下面item图片跟着切换.
再有就是我们要把listview item的第一项 onclick事件禁止了,我们直接把这个点击事件搬到onSingleTapUp中,这样就不会因为手势操作而影响item的onclick事件了,这 样问题基本都解决了,其实我想有简单的方法,只要把Touch事件弄懂,可惜啊...不给力啊...
效果和上面一样.
经过多次测试,目前没有发现问题,如有不妥我会给出提示.
第二种方法:ViewPager.
viewpager效果相比大家都熟知,因此我就省略显示的那部分,方法和上面一样,只是显示用的是viewpager而已.
但是这里面存在一个严重的问题:ViewPager和listview共存的问题,二者都有自身的滑动事件,必然要产生冲突。viewpager操作起来相当的不灵敏.
这里我重点说一下解决办法:我们需要自定义Listview,对其拦截事件进行处理.另外我们要用手势,判断上下左右滑动.
1 package com.jj.chage; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.view.GestureDetector; 7 import android.view.GestureDetector.SimpleOnGestureListener; 8 import android.view.MotionEvent; 9 import android.view.View; 10 import android.widget.ListView; 11 12 public class MyListView extends ListView { 13 private GestureDetector mGestureDetector; 14 View.OnTouchListener mGestureListener; 15 16 public MyListView(Context context) { 17 super(context); 18 } 19 20 public MyListView(Context context, AttributeSet attrs) { 21 super(context, attrs); 22 mGestureDetector = new GestureDetector(new YScrollDetector()); 23 setFadingEdgeLength(0); 24 } 25 26 public MyListView(Context context, AttributeSet attrs, int defStyle) { 27 super(context, attrs, defStyle); 28 } 29 30 @Override 31 public boolean onInterceptTouchEvent(MotionEvent ev) { 32 super.onInterceptTouchEvent(ev); 33 return mGestureDetector.onTouchEvent(ev); 34 } 35 36 class YScrollDetector extends SimpleOnGestureListener { 37 @Override 38 public boolean onScroll(MotionEvent e1, MotionEvent e2, 39 float distanceX, float distanceY) { 40 if (Math.abs(distanceY) >= Math.abs(distanceX)) { 41 Log.e("jj", "上下...."); 42 return true; 43 } 44 Log.e("jj", "左右...."); 45 return false; 46 } 47 } 48 }
这样viewpager滑动就不会受listview干扰了,listview上下也可以滑动.
由于自己对事件分发不是很了解,所以不过多介绍,想知道的话,自己慢慢研究吧,我这里只是提供一个解决方法,我也在学习中...
其他部分不难,这里就不讲解了.
滑动ing 滑动ing 点击
感觉还是第二种方法好,这也是为什么那么多客户端都是这么搞,不过各有千秋,因人而异.
对第二种方法实现简单讲解:
我们的目的是:我们左右滑动ViewPager的时候ListView不影响,而当ViewPager上下滑动的时候可以随意滑动.
我们可以这样做:我们把onInterceptTouchEvent返回值更改为fase,那么意味着,如果孩子存在onInterceptTouchEvent那么会继续传递给孩子的onInterceptTouchEvent...后面我们不管(此时ListView失去touch事件),这个时候ViewPager获取Touch事件. 这个时候ViewPager就可以左右滑动(不可以上下滑动)。 如果孩子不存在onInterceptTouchEvent,ListView执行本身ontouch.
那么把onInterceptTouchEvent返回值更改为true.意思就是:我对touch事件进行拦截,不进行向下传递,直接执行自身的Ontouch事件,这个时候ViewPager就可以上下滑了(不可以左右滑动切换).
根据实情,那么我们如何动态控制这个onInterceptTouchEvent的返回值,这个时候我们可以借助:GestureDetector手势来实现.
1 /*** 2 * 3 * @author zhangjia 4 * 5 */ 6 class YScrollDetector extends SimpleOnGestureListener { 7 @Override 8 public boolean onScroll(MotionEvent e1, MotionEvent e2, 9 float distanceX, float distanceY) { 10 if (Math.abs(distanceY) >= Math.abs(distanceX)) { 11 Log.e("jj", "上下...."); 12 return true; 13 } 14 Log.e("jj", "左右...."); 15 return false; 16 }
上面这个方法可以根据手势来判断我们手的滑动方向.而:boolean b = mGestureDetector.onTouchEvent(ev);
这个值就是onScroll返回的值.这个值是代表我们手势mGestureDetector消费了没,为什么这么说呢,因为这个和我们外界的touch分开了,就算我们在这里消费了那么外面该怎么执行就怎么执行。经过测试觉得mGestureDetector.onTouchEvent(ev)这个方法就是执行手势相应方法,然后返回的是onScroll的返回值.
而当我们上下滑动的时候mGestureDetector.onTouchEvent(ev)返回true,而ViewPager需要上下滑动的时候只需要将onInterceptTouchEvent的返回值更改为true,左右滑动同理.
那么这样我们就实现了ViewPager与ListView滑动的冲突.
源码一
源码二
转载于:https://www.cnblogs.com/liangstudyhome/p/3987172.html
【转】Android android listview的HeadView左右切换图片(仿新浪,网易,百度等切换图片)...相关推荐
- 仿新浪公益四色主题切换文章模板(齐博V7模板)
=================================== 模板名称:仿新浪公益四色切换风格模板 程序内核:齐博V7 模板内容:首页 文章模型列表 内容 模板制作:奋斗的十二 技术支持:w ...
- android仿新浪引导界面
最近在研究如何做出仿微信,仿新浪等应用,第一次安装使用的使用展示应用程序的新特性和用法. 实现功能:左右手势滑屏 底部小圆点随当前显示页跳动 浮动按钮显示.当触屏事件发生显示,否则就渐渐消失 先转个文 ...
- selenium新浪邮箱注册句柄切换实战
多窗口切换,新浪邮箱注册界面 from selenium import webdriver import time as t driver = webdriver.Chrome() driver.ma ...
- android 在 ListView 的 item 中插入 GridView 仿微信朋友圈图片显示。
转载请声明出处(http://www.cnblogs.com/linguanh/) 先上张效果图: 1,思路简述 这个肯定是要重写 baseAdapter的了,这里我分了两个数据适配器,一个是自定义的 ...
- android 仿相册,Android 仿新浪相册选择器 PhotoSelector
软件介绍 仿新浪相册选择器,支持相册选择.视频选择 一.使用方法 1.选择相册.支持拍照 启动PhotoSelectorActivity并传入已选照片路径List.若包含已选照片路径则被选照片会被选I ...
- 模仿新浪手机频道焦点广告图片切换的代码
下面的代码,将var pics注释掉的部分去掉,然后到http://auto.qq.com/flash/playswf.swf 去将flashplayer存下来,将下面的代码放到一个html文件中,和 ...
- android博客排行榜,新浪博文排行_新浪博客 新浪博客Android客户端
新浪博客 新浪博客Android客户端 JPG,330x294,231KB,281_250 醉 是春花烂漫时 JPG,480x800,191KB,250_417 新浪博客 JPG,472x216,23 ...
- android listview下拉刷新动画,android 安卓 listview 支持下拉刷新 上拉加载更多
[1]重写listViewimport java.text.SimpleDateFormat; import java.util.Date; import com.example.testdddlea ...
- Android 实现ListView的展开式动画ExpandAnimation
2019独角兽企业重金招聘Python工程师标准>>> 注意:本次修改,修补了之前的部分bug android中展开动画主要有2中,Translate和Scale,但运行效果并不像j ...
最新文章
- python基础学习语法和函数
- CPU步进号(版本号)
- 22考生这些院校计算机专业改考408
- a programmer should know...
- SAP UI5 manifest.json 和 i18n 多语言文本的解析逻辑
- python twisted教程 三–开始twisted
- 一个整合SQL语句的类
- 容器化之路:谁偷走了我的构建时间
- 【推荐算法】协同过滤算法介绍
- vue json对象转数组_vue面试题汇总
- 《物联网开发实战》05 系统实例:怎样设计一个简易物联网系统?(学习笔记)
- Day.js 常用方法
- #微软MVP分享# WP手机使用记录
- 为何计算机CPU技术不被公布呢
- Win7电脑开机的速度非常慢怎么解决?
- TOP-K问题(清晰,巨全)
- 在面试时遇到不了解的问题,如何顺畅的与面试人员交流?
- 周哲_java软件工程师 简历
- Web前端技术 Web学习资料 Web学习路线 Web入门宝典
- VUE的十一个生命周期详解
热门文章
- 面试题 03.02. 栈的最小值
- C语言程序项目计划书,(C语言程序设计课程设计计划书.doc
- 你们要的二维码测试点来了,扫它!
- homebrew安装
- 灰度董事总经理:BTC突破2万美元并不令人惊讶
- SAP License:工程质保金业务
- SAP License:用科学发展观认识会计
- SAP License:玩转SAP中的凭证冲销
- 后台管理系统、商品管理、商品发布、商品回收、订单管理、退款管理、运营管理、商城设置、导航分类、营销管理、优惠券套餐、数据统计、活跃用户、数据埋点、财务管理、对账单、财务数据、账户资产、电商后台
- 如何在Smartphone模拟器上测试短信和电话