首先我们还是看一些示例:(网易,新浪,百度)

    

下面我简单的介绍下实现方法:其实就是listview addHeaderView.只不过这个view是一个可以切换图片的view,至于这个view怎么做,就要根据自己的喜爱了,实现有多种方法,下面我简单介绍一下.

第一种:ViewFlipper+GestureDetector

主布局就是一个listview,这里就不介绍了,我介绍下切换图片布局head_iamge.xml

 <span style="font-size:12px;"><?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" > <FrameLayout
android:id="@+id/fl_main"
android:layout_width="match_parent"
android:layout_height="wrap_content" > <ViewFlipper
android:id="@+id/ViewFlipper01"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ViewFlipper> <LinearLayout
android:id="@+id/ll_point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="10dp"
android:src="@drawable/indicator" />
</FrameLayout> </LinearLayout></span>

这里我就添加一系列切换点,至于显示新闻标题,透明效果等等,大家可以自己布局,方法同理,不难实现.

接下来我们看动画布局.

push_left_in.xml

 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" > <translate
android:duration="500"
android:fromXDelta="-100%p"
android:toXDelta="0" /> <alpha
android:duration="500"
android:fromAlpha="0.1"
android:toAlpha="1.0" /> </set></span>

push_left_out.xml

 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" > <translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="-100%p" /> <alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.5" /> </set></span>

push_right_in.xml

 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" > <translate
android:duration="500"
android:fromXDelta="100%p"
android:toXDelta="0" /> <alpha
android:duration="500"
android:fromAlpha="0.1"
android:toAlpha="1.0" /> </set></span>

push_right_out.xml

 <span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" > <translate
android:duration="500"
android:fromXDelta="0"
android:toXDelta="100%p" /> <alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.5" /> </set></span>

我简单介绍下这些布局:

push_left_in:左边进入,则要进入的view初始位置在-100%p位置,终止位置在0,而push_left_out:左边出来,则此时view的位置在0,而终止位置在-100%p.

右进右出同理,至于alpha渐变,很简单,动画就说道这里,相信了解动画的同学们不用看就ok了.

下面重点是如何实现.

代码:

 <span style="font-size:12px;">package com.jj.chage2;

 import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask; import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper; public class MainActivity extends Activity implements
GestureDetector.OnGestureListener {
private GestureDetector detector;
private ViewFlipper flipper;
private int image_id[] = { R.drawable.a, R.drawable.b, R.drawable.c };
private ListView lv_main;
private LayoutInflater layoutInflater;
private LinearLayout ll_point;
private FrameLayout frameLayout;
private final String msg[] = { "one", "two", "three", "four", "five",
"six", "seven" };
private int frameheight;// 图片的高度
private int window_width;// 屏幕宽度
private ArrayList<ImageView> imageViews;// ponit 集合
private ArrayList<View> views;// flipper的孩子
private Timer timer; /***
* 初始化 point
*/
void initPoint() {
imageViews = new ArrayList<ImageView>();
ImageView imageView;
for (int i = 0; i < image_id.length; i++) {
imageView = new ImageView(this);
imageView.setBackgroundResource(R.drawable.indicator);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
layoutParams.leftMargin = 10;
layoutParams.rightMargin = 10;
ll_point.addView(imageView, layoutParams);
imageViews.add(imageView);
} } /***
* ChildView
*/
void initChildView(ViewFlipper flipper) {
views = new ArrayList<View>();
LayoutParams layoutParams = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
for (int i = 0; i < image_id.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setScaleType(ScaleType.FIT_XY);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
image_id[i]);
Bitmap bitmap2 = getBitmap(bitmap, window_width);
frameheight = bitmap2.getHeight();// 获取要显示的高度
imageView.setImageResource(image_id[i]);
flipper.addView(imageView, layoutParams);
views.add(imageView);
}
initPoint();
} /***
* 初始化 HeadImage
*/
void initHeadImage() {
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View headview = layoutInflater.inflate(R.layout.head_image, null); flipper = (ViewFlipper) headview.findViewById(R.id.ViewFlipper01); ll_point = (LinearLayout) headview.findViewById(R.id.ll_point);
frameLayout = (FrameLayout) headview.findViewById(R.id.fl_main);
initChildView(flipper); LayoutParams layoutParams = (LayoutParams) frameLayout
.getLayoutParams();
layoutParams.height = frameheight;
frameLayout.setLayoutParams(layoutParams);
draw_Point(0);// 默认首次进入
lv_main.addHeaderView(headview);// 要卸载setAdapter前面
lv_main.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, msg)); } /***
* init view
*/
void initView() {
setTitle("jjhappyforever...");
setContentView(R.layout.main);
lv_main = (ListView) findViewById(R.id.lv_main);
lv_main.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) { if (position != 0)
Toast.makeText(MainActivity.this, msg[position - 1], 1)
.show();
else {
int index = getPageIndex(flipper.getCurrentView());
Toast.makeText(MainActivity.this, "图" + index, 1).show(); } }
});
initHeadImage();
} /***
* 更新选中点
*
* @param index
*/
private void draw_Point(int index) {
for (int i = 0; i < imageViews.size(); i++) {
imageViews.get(i).setImageResource(R.drawable.indicator);
}
imageViews.get(index).setImageResource(R.drawable.indicator_focused);
} @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取屏幕的宽度
window_width = (int) getResources().getDimension(R.dimen.window_width);
detector = new GestureDetector(this);
initView(); timer = new Timer(true);
timer.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() { int pageIndex = getPageIndex(flipper.getCurrentView()); if (pageIndex == flipper.getChildCount() - 1)
pageIndex = 0;
else
pageIndex++; flipper.setInAnimation(AnimationUtils.loadAnimation(
MainActivity.this, R.anim.push_right_in));
flipper.setOutAnimation(AnimationUtils.loadAnimation(
MainActivity.this, R.anim.push_left_out));
flipper.showNext();
draw_Point(pageIndex); }
});
}
}, 5000, 5000); } /***
* 对图片处理
*
* @author zhangjia
*
*/
Bitmap getBitmap(Bitmap bitmap, int width) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scale = (float) width / w;
// 保证图片不变形.
matrix.postScale(scale, scale);
// w,h是原图的属性.
return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
this.detector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
} @Override
public boolean onDown(MotionEvent e) {
return true;
} /***
* 返回当前第几屏
*/
int getPageIndex(View view) {
for (int i = 0; i < views.size(); i++) {
if (view == views.get(i))
return i;
}
return 0; } /**
* 监听滑动
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
int pageIndex = getPageIndex(flipper.getCurrentView()); // 左划
if (e1.getX() - e2.getX() > 120) {
this.flipper.setInAnimation(AnimationUtils.loadAnimation(this,
R.anim.push_right_in));
this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this,
R.anim.push_left_out));
this.flipper.showNext();
if (pageIndex == flipper.getChildCount() - 1)
draw_Point(0);
else
draw_Point(++pageIndex);
return true;
// 右划
} else if (e1.getX() - e2.getX() < -120) {
this.flipper.setInAnimation(AnimationUtils.loadAnimation(this,
R.anim.push_left_in));
this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this,
R.anim.push_right_out));
this.flipper.showPrevious();
if (pageIndex == 0)
draw_Point(flipper.getChildCount() - 1);
else
draw_Point(--pageIndex);
return true;
}
return true;
} @Override
public void onLongPress(MotionEvent e) { } @Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
} @Override
public void onShowPress(MotionEvent e) { } @Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
} }</span>

上诉代码写的有点小乱,别介意.

效果:

    

你可以手势左右滑动图片切换,由于我们加入了动画,则在切换图片效果会比较人性,这一 点比较不错.另外一点,我开启了timer,让它自己切换,感觉这点比较不错,可惜好多应用都没有这么搞,总之实现就行了,我们开发人员嘛,就是开发别人 想出来的东西,感慨程序员苦逼...

如果你按照上诉操作的话会有几个问题:1,我移动图片下面的item图片也会切换,2,我在滑动切换图片的时候偶尔也会执行onclick事件,这两点bug严重不允许,为之我也煞费神经细胞啊,没办法因为基础不好,对触摸种种事件还是搞不明白,有时间了还得在看看研究研究,扯远了,下面我说下解决方法:

第一:我只让listview的第一项监听手势操作,其他的不执行.

方法很简单,自定义一个listview.重写其onTouchEvent事件.

@Override
public 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,对其拦截事件进行处理.另外我们要用手势,判断上下左右滑动.

 package com.jj.chage;

 import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView; public class MyListView extends ListView {
private GestureDetector mGestureDetector;
View.OnTouchListener mGestureListener; public MyListView(Context context) {
super(context);
} public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(new YScrollDetector());
setFadingEdgeLength(0);
} public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
return mGestureDetector.onTouchEvent(ev);
} class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (Math.abs(distanceY) >= Math.abs(distanceX)) {
Log.e("jj", "上下....");
return true;
}
Log.e("jj", "左右....");
return false;
}
}
}

这样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手势来实现.

 /***
*
* @author zhangjia
*
*/
class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (Math.abs(distanceY) >= Math.abs(distanceX)) {
Log.e("jj", "上下....");
return true;
}
Log.e("jj", "左右....");
return false;
}

上面这个方法可以根据手势来判断我们手的滑动方向.而:boolean b = mGestureDetector.onTouchEvent(ev);

这个值就是onScroll返回的值.这个值是代表我们手势mGestureDetector消费了没,为什么这么说呢,因为这个和我们外界的touch分开了,就算我们在这里消费了那么外面该怎么执行就怎么执行。经过测试觉得mGestureDetector.onTouchEvent(ev)这个方法就是执行手势相应方法,然后返回的是onScroll的返回值.

而当我们上下滑动的时候mGestureDetector.onTouchEvent(ev)返回true,而ViewPager需要上下滑动的时候只需要将onInterceptTouchEvent的返回值更改为true,左右滑动同理.

那么这样我们就实现了ViewPager与ListView滑动的冲突.

源码一

源码二

【转】Android android listview的HeadView左右切换图片(仿新浪,网易,百度等切换图片)的更多相关文章

  1. android listview的HeadView左右切换图片(仿新浪,网易,百度等切换图片)

    首先我们还是看一些示例:(网易,新浪,百度) 显示效果都不错,可是手感就不一样了,百度最棒,网易还行,新浪就操作很不好,这里我说的是滑动切换图片.自己可以测试一下.不得不说牛叉的公司确实有哦牛叉的道理 ...

  2. android仿新浪引导界面

    最近在研究如何做出仿微信,仿新浪等应用,第一次安装使用的使用展示应用程序的新特性和用法. 实现功能:左右手势滑屏 底部小圆点随当前显示页跳动 浮动按钮显示.当触屏事件发生显示,否则就渐渐消失 先转个文 ...

  3. Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解

    Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解 (本文转自: http://blog.csdn.net/yinhaide/article/details/44756 ...

  4. android 在 ListView 的 item 中插入 GridView 仿微信朋友圈图片显示。

    转载请声明出处(http://www.cnblogs.com/linguanh/) 先上张效果图: 1,思路简述 这个肯定是要重写 baseAdapter的了,这里我分了两个数据适配器,一个是自定义的 ...

  5. Android仿新浪新闻SlidingMenu界面的实现 .

    先看看原图: 如图所示,这种侧滑效果以另一种方式替代了原先tab导航的那种用户体验方式 给人耳目一新的感觉,现已被广大知名应用所效仿,如新浪新闻,网易新闻,人人网等 那么这种效果该如何实现呢?那就需要 ...

  6. Android之ListView&ViewPager模拟新闻界面

    模拟新闻 APP 的界面 1)写 ListView 之前先写布局: 这里有两种 Item 的布局: <?xml version="1.0" encoding="ut ...

  7. 【转载】Android中ListView下拉刷新的实现

    在网上看到一个下拉刷新的例子,很的很棒,转载和更多的人分享学习 原文:http://blog.csdn.net/loongggdroid/article/details/9385535 ListVie ...

  8. Android中ListView下拉刷新的实现

    ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考.那我就不解释,直接上代码了. 这里需要自己重写一下ListView,重写代码如下: packa ...

  9. Android TV listView焦点平滑移动

    先上TV上效果图 Mark下思路: package com.test.ui; import java.lang.reflect.Method; import android.annotation.Su ...

随机推荐

  1. linux下安装ZipArchive扩展和libzip扩展

    在项目开发的时候,由于要下载多个录音文件,我就需要打包下载这个功能 学习源头: https://www.landui.com/help/show-8079 https://www.aliyun.com ...

  2. What’s that ALUA exactly?

    What’s that ALUA exactly? 29 September, 20098 Comments Of course by now we have all read the excelle ...

  3. 安装并配置工具以使用iOS进行构建

    Visual Studio 2015   Visual Studio文档的新家是docs.microsoft.com上的Visual Studio 2017文档 . 有关Visual Studio 2 ...

  4. php解析base64数据成图片

    $base64 = "/9j/4AAQSkZJRgABAQEAkACQAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAA ...

  5. Spring Cloud与分布式系统

    本文不是讲解如何使用spring Cloud的教程,而是探讨Spring Cloud是什么,以及它诞生的背景和意义. 背景 2008年以后,国内互联网行业飞速发展,我们对软件系统的需求已经不再是过去” ...

  6. Linux - 目录结构及文件操作

    根目录 “/”:Linux 系统中最高层的目录 这个就是根目录 用 / 表示根目录 bin 目录:存放可执行文件 bin 目录下的文件都是平常使用的命令 在 Linux 系统中,一切都是文件 sbin ...

  7. java成神之——集合框架之Maps,Hashtable

    集合 Maps HashMap 创建和初始化map 遍历方式 LinkedHashMap WeakHashMap TreeMap 线程锁 Hashtable 结语 集合 Maps HashMap Ma ...

  8. IT_Qestion

    1. Javascript 回调 Promise 2. Angularjs $parent 3. CSS margin padding border 4. Angularjs $filter 5. D ...

  9. MATLAB和C语言混合编程-----Matlab7.0 编译器设置

    (1) mex 命令设置 (a) 运行 Matlab ,在 Matlab 的命令窗口 (Command Window) 键入“ mex -setup ”命令后,按回车键,安装 Matlab 编译器: ...

  10. C#向pdf 添加水印

    调用直接这样用: //PDFHelper.AddImageWatermarkPDF(path, "D://my.pdf", Server.MapPath("/HtmlTo ...