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

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

下面我简单的介绍下实现方法:其实就是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>[/mw_shl_code]
push_left_out.xml
[mw_shl_code=java,true]<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>[/mw_shl_code]
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>
我简单介绍下这些布局:

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

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

下面重点是如何实现.

代码:

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);
                        Bitmap bitmap2 = getBitmap(bitmap, window_width);
                        frameheight = bitmap2.getHeight();// 获取要显示的高度
                        imageView.setImageResource(image_id);
                        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;
        }

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

效果:


可以手势左右滑动图片切换,由于我们加入了动画,则在切换图片效果会比较人性,这一点比较不错.另外一点,我开启了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 listview的HeadView左右切换图片(仿新浪,网易,百度等切换图片)的更多相关文章

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

    首先我们还是看一些示例:(网易,新浪,百度)      下面我简单的介绍下实现方法:其实就是listview addHeaderView.只不过这个view是一个可以切换图片的view,至于这个vie ...

  2. android仿新浪引导界面

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

  3. jquery实现隐藏显示层动画效果、仿新浪字符动态输入、tab效果

    已经有两年多没登陆csdn账号了,中间做了些旁的事,可是现在却还是回归程序,但改做前端了,虽然很多东西都已忘得差不多了,但还是应该摆正心态,慢慢来,在前端漫游,做一只快乐双鱼. 路是一步一步走出来的, ...

  4. 仿新浪首页、主题、详情页,纯html静态页面

    仿新浪首页.主题.详情页.纯html静态页面,下载地址: http://download.csdn.net/detail/sweetsuzyhyf/8085535

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

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

  6. Android 高级UI设计笔记06:仿微信图片选择器(转载)

    仿微信图片选择器: 一.项目整体分析: 1. Android加载图片的3个目标: (1)尽可能的去避免内存溢出. a. 根据图片的显示大小去压缩图片 b. 使用缓存对我们图片进行管理(LruCache ...

  7. [Android]ListView的Adapter.getView()方法中延迟加载图片的优化

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4139998.html 举个例子吧,以好友列表为例 ListVi ...

  8. Android ListView滑动过程中图片显示重复错乱闪烁问题解决

    最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...

  9. Android ListView分页加载时图片显示问题

    场景:Android ListView需要分页加载,每个item中会有图片,图片又是从网络下载的. 问题:在滑动加载下一页时,上一页的图片明明已经下载完成了,但是无法显示出来. Bug重现: 1,加载 ...

随机推荐

  1. UNDFTD x Nike Air Max 97 OG Black

    The UNDFTD x Nike Air Max 97 OG Black is releasing way sooner than anticipated. This collaborative r ...

  2. 9/24matplotlib简介

    Matplotlib是一个在python下实现的类matlib的纯python的三方库,旨在用python实现matlib的功能,是python下最出色的绘图库,功能很完善,其风格根matlib很相似 ...

  3. !! A股历史平均市盈率走势图

    http://value500.com/PE.asp 一. A股历史平均市盈率走势图 *数据来源:上海证券交易所 分享到: 354 - 上海A股 深圳A股更新时间 2017年6月7日 2017年6月7 ...

  4. SV中的线程

    SV中线程之间的通信可以让验证组件之间更好的传递transaction. SV对verilog建模方式的扩展:1) fork.....join 必须等到块内的所有线程都执行结束后,才能继续执行块后的语 ...

  5. 2016-2017-2 20155309南皓芯java第五周学习总结

    教材内容总结 这一周学习的进度和前几周比较的话是差不多的,都是学习两章. 异常处理 1.理解异常架构 2.牚握try...catch...finally处理异常的方法 3.会用throw,throws ...

  6. Python正则处理多行日志一例(可配置化)

    正则表达式基础知识请参阅<正则表达式基础知识>,本文使用正则表达式来匹配多行日志并从中解析出相应的信息. 假设现在有这样的SQL日志: SELECT * FROM open_app WHE ...

  7. 全局监听SCREEN_ON和SCREEN_OFF的替代方法--监听屏幕解锁事件

    在做一个程序的时候,需要时刻保持某一服务是启动的,因此想到了通过监听屏幕SCREEN_ON和SCREEN_OFF这两个action.奇怪的是,这两个action只能通过代码的形式注册,才能被监听到,使 ...

  8. python 模拟windows键盘按键的封装

    代码:在执行的时候,把光标放在指定的地方,在此例中,点击运行后把光标放到结果区域,粘贴的时候是粘贴到光标所在的问题,如过是运行脚本在web元素输入框中输入的话,不能移动光标到其他位置 #encodin ...

  9. php array 根据value获取key,in_array()判断是否在数组内实例

    php array 根据value获取key,in_array()判断是否在数组内实例 <?php header("Content-type: text/html; charset=u ...

  10. C/C++之面向对象

    面向对象的三个基本特征(讲解) 面向对象的三个基本特征是:封装.继承.多态. 封装 封装最好理解了.封装是面向对象的特征之一,是对象和类概念的主要特性. 封装,也就是把客观事物封装成抽象的类,并且类可 ...