Android实现局部图片滑动指引效果示例

Android实现局部图片滑动指引效果示例,第1张

概述今天发布本文的原因是应一个网友要求,就是实现局部的图片滑动指引效果。这种效果一般是在新闻客户端上比较常见,其功能是:

今天发布本文的原因是应一个网友要求,就是实现局部的图片滑动指引效果。这种效果一般是在新闻客户端上比较常见,其功能是:

1、顶部单张图片左右拖拉滑动;

2、带指引;

3、仅滑动顶部单张图片,不滑动页面,下面的图文内容不动;

4、类似于新闻客户端的功能

为了大家能更好的理解,我们先来看下要实现的效果图:

以上便是实现的效果图,其实实现原理也并不难,我们只需要将androID-support-v4.jar包中VIEwPager控件设置成局部就可以,只是处理界面时稍微有点麻烦,不过看完本篇之后,大家以后使用时直接调用就行。也希望本篇能够对大家有所帮助。

好了,下面让我们开始我们的实现过程,主要给大家介绍一下实现步骤和一些核心代码。首先我们需要将androID-support-v4.jar添加到工程当中,然后让我们看一下程序结构:

我先简要介绍其实现原理:

在布局页面中将设置成局部,限制其高度,然后为滑动的图片集合生成布局界面,并在代码中设置相应的数据适配器和监听事件。在切换事件监听器中更改相应的圆点图片和显示标题,由于滑动图片下方的界面不需要改变内容,所以很很容易内容超过屏幕,所以需要设置ScrollVIEw以在内容比较多时显示滚动条,我会在下面介绍如何让VIEwPager和ScrollVIEw结合使用。

先看下androID.support.v4.vIEw.VIEwPager在布局界面中的核心代码:

<androID.support.v4.vIEw.VIEwPager    androID:ID="@+ID/image_slIDe_page"    androID:layout_wIDth="fill_parent"    androID:layout_height="180dip"    androID:focusable="true" />

在程序结构中,MainActivity.java是启动的Activity,而topicNews.java是显示头条的Acitivity。在显示时,我们需要将topicNews.java中的对象进行初始化设置,如下代码:

/**   * 初始化   */  private voID initeVIEws(){    // 滑动图片区域    imagePageVIEws = new ArrayList<VIEw>();    LayoutInflater inflater = getLayoutInflater();     main = (VIEwGroup)inflater.inflate(R.layout.page_topic_news,null);    vIEwPager = (VIEwPager) main.findVIEwByID(R.ID.image_slIDe_page);         // 圆点图片区域    parser = new NewsXmlParser();    int length = parser.getSlIDeImages().length;    imageCircleVIEws = new ImageVIEw[length];    imageCircleVIEw = (VIEwGroup) main.findVIEwByID(R.ID.layout_circle_images);    slIDeLayout = new SlIDeImageLayout(topicNews.this);    slIDeLayout.setcircleimageLayout(length);        for(int i = 0;i < length;i++){      imagePageVIEws.add(slIDeLayout.getSlIDeImageLayout(parser.getSlIDeImages()[i]));      imageCircleVIEws[i] = slIDeLayout.getcircleimageLayout(i);      imageCircleVIEw.addVIEw(slIDeLayout.getlinearLayout(imageCircleVIEws[i],10,10));    }        // 设置默认的滑动标题    tvSlIDeTitle = (TextVIEw) main.findVIEwByID(R.ID.tvSlIDeTitle);    tvSlIDeTitle.setText(parser.getSlIDeTitles()[0]);        setContentVIEw(main);        // 设置VIEwPager    vIEwPager.setAdapter(new SlIDeImageAdapter());     vIEwPager.setonPagechangelistener(new ImagePagechangelistener());  }

以上对象的声明代码如下所示:

// 滑动图片的集合  private ArrayList<VIEw> imagePageVIEws = null;  private VIEwGroup main = null;  private VIEwPager vIEwPager = null;  // 当前VIEwPager索引  private int pageIndex = 0;     // 包含圆点图片的VIEw  private VIEwGroup imageCircleVIEw = null;  private ImageVIEw[] imageCircleVIEws = null;     // 滑动标题  private TextVIEw tvSlIDeTitle = null;    // 布局设置类  private SlIDeImageLayout slIDeLayout = null;  // 数据解析类  private NewsXmlParser parser = null;

由于在显示头条的Activity即topicNews中,设置布局文件不是直接设置的,也就是通过inflate将Layout转化为VIEw控件的,所以在使用page_topic_news.xml中的VIEw时,需要通过main.findVIEwByID(),即如下代码所示:
 

main = (VIEwGroup)inflater.inflate(R.layout.page_topic_news,null);
 vIEwPager = (VIEwPager) main.findVIEwByID(R.ID.image_slIDe_page); 

而不能像这样直接使用:

vIEwPager = (VIEwPager) findVIEwByID(R.ID.image_slIDe_page);

这点大家在使用时需要注意。

NewsXmlParser类是用于对显示的数据进行解析,由于本示例只是一个演示示例,所以在这个类里我只是设置一些要显示的固定数据,没有设置动态数据,这点明白就可以,代码如下:

package com.image.indicator.parser;import java.io.inputStream;import java.util.HashMap;import java.util.List;import org.xmlpull.v1.XmlPullParser;import androID.util.Xml;import com.image.indicator.R;import com.image.indicator.entity.News;import com.image.indicator.utility.fileAccess;/** * 解析新闻数据列表 * @Description: 解析新闻数据列表,这里只是个示例,具体地不再实现。 * @file: NewsXmlParser.java * @Package com.image.indicator.parser * @Author Hanyonglu * @Date 2012-6-18 下午02:31:26 * @Version V1.0 */public class NewsXmlParser {  // 新闻列表  private List<HashMap<String,News>> newsList = null;    // 滑动图片的集合,这里设置成了固定加载,当然也可动态加载。  private int[] slIDeImages = {      R.drawable.image01,R.drawable.image02,R.drawable.image03,R.drawable.image04,R.drawable.image05};    // 滑动标题的集合  private int[] slIDeTitles = {      R.string.Title1,R.string.Title2,R.string.Title3,R.string.Title4,R.string.Title5,};    // 滑动链接的集合  private String[] slIDeUrls = {      "http://mobile.csdn.net/a/20120616/2806676.HTML","http://cloud.csdn.net/a/20120614/2806646.HTML","http://mobile.csdn.net/a/20120613/2806603.HTML","http://news.csdn.net/a/20120612/2806565.HTML","http://mobile.csdn.net/a/20120615/2806659.HTML",};    public int[] getSlIDeImages(){    return slIDeImages;  }    public int[] getSlIDeTitles(){    return slIDeTitles;  }    public String[] getSlIDeUrls(){    return slIDeUrls;  }    /**   * 获取XmlPullParser对象   * @param result   * @return   */  private XmlPullParser getXmlPullParser(String result){    XmlPullParser parser = Xml.newPullParser();    inputStream inputStream = fileAccess.String2inputStream(result);        try {      parser.setinput(inputStream,"UTF-8");    } catch (Exception e) {      // Todo: handle exception      e.printstacktrace();    }        return parser;  }    public int getNewsListCount(String result){    int count = -1;        try {      XmlPullParser parser = getXmlPullParser(result);      int event = parser.getEventType();//产生第一个事件            while(event != XmlPullParser.END_document){        switch(event){        case XmlPullParser.START_document:          break;        case XmlPullParser.START_TAG://判断当前事件是否是标签元素开始事件          if("count".equals(parser.getname())){//判断开始标签元素是否是count            count = Integer.parseInt(parser.nextText());          }                    break;        case XmlPullParser.END_TAG://判断当前事件是否是标签元素结束事件//          if("count".equals(parser.getname())){//判断开始标签元素是否是count//            count = Integer.parseInt(parser.nextText());//          }                    break;        }              event = parser.next();//进入下一个元素并触发相应事件      }    } catch (Exception e) {      // Todo: handle exception      e.printstacktrace();    }        // 无返回值,则返回-1    return count;  }}

关于NewsXmlParser这个类,实现比较简单,不再详述,有兴趣的朋友可以在开发过程中将其设置成动态数据并进行解析。

刚才在上面介绍其实现原理时,我提到需要设置滑动图片集合的布局界面,那么如何设置其布局呢?这里我们需要用到SlIDeImageLayout。

SlIDeImageLayout类是用于生成滑动图片区域布局和圆点图片布局的类。我在上面的代码中(即在topicNews.java的初始化方法initeVIEws())使用for循环设置滑动图片及圆点图片的布局。在循环中就用到了getSlIDeImageLayout()、getcircleimageLayout()和getlinearLayout()这几个方法。下面分别看下其功能,先看下getSlIDeImageLayout()实现代码:

/**   * 生成滑动图片区域布局   * @param index   * @return   */  public VIEw getSlIDeImageLayout(int index){    // 包含TextVIEw的linearLayout    linearLayout imagelinerLayout = new linearLayout(activity);    linearLayout.LayoutParams imagelinerLayoutParames = new linearLayout.LayoutParams(        linearLayout.LayoutParams.WRAP_CONTENT,linearLayout.LayoutParams.WRAP_CONTENT,1);        ImageVIEw iv = new ImageVIEw(activity);    iv.setBackgroundResource(index);    iv.setonClickListener(new ImageOnClickListener());    imagelinerLayout.addVIEw(iv,imagelinerLayoutParames);    imageList.add(iv);        return imagelinerLayout;  }

由于滑动图片一般需要设置其链接或是相应的ID,以便在点击时转向相应的Activity,显示相应的内容或详细信息。这里我没有过多的设置,只是在点击时显示标题及链接地址,代码如下:

// 滑动页面点击事件监听器  private class ImageOnClickListener implements OnClickListener{    @OverrIDe    public voID onClick(VIEw v) {      // Todo auto-generated method stub      Toast.makeText(activity,parser.getSlIDeTitles()[pageIndex],Toast.LENGTH_SHORT).show();      Toast.makeText(activity,parser.getSlIDeUrls()[pageIndex],Toast.LENGTH_SHORT).show();    }  }

getcircleimageLayout()方法主要是为圆点图片生成相应的ImageVIEw对象,代码如下:

/**   * 生成圆点图片区域布局对象   * @param index   * @return   */  public ImageVIEw getcircleimageLayout(int index){    imageVIEw = new ImageVIEw(activity);     imageVIEw.setLayoutParams(new LayoutParams(10,10));    imageVIEw.setScaleType(ScaleType.FIT_XY);        imageVIEws[index] = imageVIEw;         if (index == 0) {       //默认选中第一张图片      imageVIEws[index].setBackgroundResource(R.drawable.dot_selected);     } else {       imageVIEws[index].setBackgroundResource(R.drawable.dot_none);     }          return imageVIEws[index];  }

getlinearLayout()方法则是为圆点图片添加相应的linearLayout布局,以便设置圆点图片之间的距离,代码如下:

/**   * 获取linearLayout   * @param vIEw   * @param wIDth   * @param height   * @return   */  public VIEw getlinearLayout(VIEw vIEw,int wIDth,int height){    linearLayout linerLayout = new linearLayout(activity);    linearLayout.LayoutParams linerLayoutParames = new linearLayout.LayoutParams(        wIDth,height,1);    // 这里最好也自定义设置,有兴趣的自己设置。    linerLayout.setpadding(10,0);    linerLayout.addVIEw(vIEw,linerLayoutParames);        return linerLayout;  }

getcircleimageLayout()和getlinearLayout()方法在Newstopic.java中for循环的结构中结合代码如下:

imageCircleVIEws[i] = slIDeLayout.getcircleimageLayout(i);
imageCircleVIEw.addVIEw(slIDeLayout.getlinearLayout(imageCircleVIEws[i],10));

这两个方法结合使用便能优美地实现其圆点图片的布局。

以上是关于NewsXmlParser和SlIDeImageLayout两个类的介绍,下面让我们再回到topicNews类中继续介绍相关知识。在topicNews中进行对象初始化(initeVIEws()方法)以后,还需要设置VIEwPager对象中的数据适配器和监听事件。VIEwPager中数据适配器的代码如下:

// 滑动图片数据适配器  private class SlIDeImageAdapter extends PagerAdapter {     @OverrIDe     public int getCount() {       return imagePageVIEws.size();     }      @OverrIDe     public boolean isVIEwFromObject(VIEw arg0,Object arg1) {       return arg0 == arg1;     }      @OverrIDe     public int getItemposition(Object object) {       // Todo auto-generated method stub       return super.getItemposition(object);     }      @OverrIDe     public voID destroyItem(VIEw arg0,int arg1,Object arg2) {       // Todo auto-generated method stub       ((VIEwPager) arg0).removeVIEw(imagePageVIEws.get(arg1));     }      @OverrIDe     public Object instantiateItem(VIEw arg0,int arg1) {       // Todo auto-generated method stub       ((VIEwPager) arg0).addVIEw(imagePageVIEws.get(arg1));            return imagePageVIEws.get(arg1);     }      @OverrIDe     public voID restoreState(Parcelable arg0,ClassLoader arg1) {       // Todo auto-generated method stub      }      @OverrIDe     public Parcelable saveState() {       // Todo auto-generated method stub       return null;     }      @OverrIDe     public voID startUpdate(VIEw arg0) {       // Todo auto-generated method stub      }      @OverrIDe     public voID finishUpdate(VIEw arg0) {       // Todo auto-generated method stub      }   }

而VIEwPager的事件监听器代码如下:

// 滑动页面更改事件监听器  private class ImagePagechangelistener implements OnPagechangelistener {    @OverrIDe     public voID onPageScrollStateChanged(int arg0) {       // Todo auto-generated method stub      }      @OverrIDe     public voID onPageScrolled(int arg0,float arg1,int arg2) {       // Todo auto-generated method stub      }      @OverrIDe     public voID onPageSelected(int index) {       pageIndex = index;      slIDeLayout.setPageIndex(index);      tvSlIDeTitle.setText(parser.getSlIDeTitles()[index]);            for (int i = 0; i < imageCircleVIEws.length; i++) {         imageCircleVIEws[index].setBackgroundResource(R.drawable.dot_selected);                if (index != i) {           imageCircleVIEws[i].setBackgroundResource(R.drawable.dot_none);         }       }    }   }

事件监听器中主要在回调函数onPageSelected(int index)中变换标题和圆点图片。

由于滑动区域下方的内容是不变的,也就是不滑动的,正如在我在上面提到的,内容可能会超出屏幕的范围,所以我们需要使用ScrollVIEw以便内容过多的时候显示滚动条。可能一部分朋友会想到,要显示滚动条我也知道使用ScrollVIEw。我想在这里说的是,这里即有VIEwPager控件,也有ScrollVIEw,如果两个VIEw单独使用不会有什么问题。然而不幸的是,两个一结合使用就出现了问题。什么问题呢?就是在滑动图片时出现反d的现象,就是在滑动时很难滑动,我滑动时感觉很吃力,而且图片就是滑动不过去,这个就是两个VIEw之间的冲突,因为两个VIEw都是滑动的VIEw,都会计算相应的位置和判断相应的距离。

我们如何来解决这个冲突呢?这里我们需要重写ScrollVIEw的onIntercepttouchEvent()回调函数。需要在程序里新加一个ScrollVIEwExtend类并继承自ScrollVIEw,下面是其代码:

package com.image.indicator.control;import androID.content.Context;import androID.util.AttributeSet;import androID.vIEw.MotionEvent;import androID.Widget.ScrollVIEw;/** * 能够兼容VIEwPager的ScrollVIEw * @Description: 解决了VIEwPager在ScrollVIEw中的滑动反d问题 * @file: ScrollVIEwExtend.java * @Package com.image.indicator.control * @Author Hanyonglu * @Date 2012-6-18 下午01:34:50 * @Version V1.0 */public class ScrollVIEwExtend extends ScrollVIEw {  // 滑动距离及坐标  private float xdistance,ydistance,xLast,yLast;  public ScrollVIEwExtend(Context context,AttributeSet attrs) {    super(context,attrs);  }  @OverrIDe  public boolean onIntercepttouchEvent(MotionEvent ev) {    switch (ev.getAction()) {      case MotionEvent.ACTION_DOWN:        xdistance = ydistance = 0f;        xLast = ev.getX();        yLast = ev.getY();        break;      case MotionEvent.ACTION_MOVE:        final float curX = ev.getX();        final float curY = ev.getY();                xdistance += Math.abs(curX - xLast);        ydistance += Math.abs(curY - yLast);        xLast = curX;        yLast = curY;                if(xdistance > ydistance){          return false;        }     }    return super.onIntercepttouchEvent(ev);  }}

然后在我们的布局代码中添加这个扩展的VIEw,如下代码:

<com.image.indicator.control.ScrollVIEwExtend    androID:layout_wIDth="match_parent"    androID:layout_height="fill_parent">    ……</com.image.indicator.control.ScrollVIEwExtend>

以上的 *** 作便可解决VIEwPager和ScrollVIEw之间冲突问题,这样便可使用滚动条顺利显示下方不变的内容。在这里再次给大家说明一下,由于本示例只是个演示示例,所以在滑动图片的下方,我只是用了一张图片固定地显示头条Activity的下方。当然有需要的朋友,可以将其进行改造,将滑动图片的下方区域添加个ListVIEw等VIEw之类的以显示相应要求的信息。

一些朋友可能会注意到,在滑动图片区域的下方有一段透明的效果,如下图所示:

这个实现也不难,只是在相应的布局代码中添加background属性即可,如下:

androID:background="#55000000"

当然,透明度的设置有个范围,有兴趣的朋友到网上查找一下,这里不再详述。

本示例除了实现AndroID局部图片滑动指引效果以外,还实现了上方导航菜单切换的效果,关于这个效果并不稀奇,因为网上有一些人已经实现该功能。不过在这里,我跟他们做不太一样的是,点击上方的新闻分类时灵敏度比较好,也就是说点中的概率比较大。因为上方的新闻分类文字比较小,要想点中有时不是件容易的事。下面简要说一下其实现过程及相应的代码。

由于要在点击新闻类别时背景图片需要动画效果,所以我添加了一个类:ImageAnimatioin,用于处理图片移动时动画效果。其

代码如下:

/**   * 设置图像移动动画效果   * @param v   * @param startX   * @param toX   * @param startY   * @param toY   */  public static voID SetimageSlIDe(VIEw v,int startX,int toX,int startY,int toY) {    TranslateAnimation anim = new TranslateAnimation(startX,toX,startY,toY);    anim.setDuration(100);    anim.setFillAfter(true);    v.startAnimation(anim);  }

下面展示一下点击新闻类别时的事件监听器中的代码,因为在这个过程中需要计算移动图片的位置和切换下面的主体内容,如下:

 // 新闻分类事件监听器  private class ItemOnclickListener implements OnClickListener{    @OverrIDe    public voID onClick(VIEw v) {      // Todo auto-generated method stub      itemWIDth = findVIEwByID(R.ID.layout).getWIDth();            switch (v.getID()) {      case R.ID.tv_Title_news:        ImageAnimatioin.SetimageSlIDe(tvSelectedItem,startX,0);        startX = 0;        tvSelectedItem.setText(R.string.Title_news_category_tops);                // 显示头条信息        intent.setClass(MainActivity.this,topicNews.class);        vNewsMain = getLocalActivityManager().startActivity(            "topicNews",intent).getDecorVIEw();        break;      case R.ID.tv_Title_info:        ImageAnimatioin.SetimageSlIDe(tvSelectedItem,itemWIDth,0);        startX = itemWIDth;        tvSelectedItem.setText(R.string.Title_news_category_info);                // 显示资讯信息        intent.setClass(MainActivity.this,InfoNews.class);        vNewsMain = getLocalActivityManager().startActivity(            "InfoNews",intent).getDecorVIEw();        break;      case R.ID.tv_Title_blog:        ImageAnimatioin.SetimageSlIDe(tvSelectedItem,itemWIDth * 2,0);        startX = itemWIDth * 2;        tvSelectedItem.setText(R.string.Title_news_category_blog);                // 显示博客信息        intent.setClass(MainActivity.this,BlogNews.class);        vNewsMain = getLocalActivityManager().startActivity(            "BlogNews",intent).getDecorVIEw();        break;      case R.ID.tv_Title_magazine:        ImageAnimatioin.SetimageSlIDe(tvSelectedItem,itemWIDth * 3,0);        startX = itemWIDth * 3;        tvSelectedItem.setText(R.string.Title_news_category_magazine);                // 显示杂志信息        intent.setClass(MainActivity.this,MagazineNews.class);        vNewsMain = getLocalActivityManager().startActivity(            "MagazineNews",intent).getDecorVIEw();        break;      case R.ID.tv_Title_domain:        ImageAnimatioin.SetimageSlIDe(tvSelectedItem,itemWIDth * 4,0);        startX = itemWIDth * 4;        tvSelectedItem.setText(R.string.Title_news_category_domain);        // 显示业界信息        intent.setClass(MainActivity.this,DomainNews.class);        vNewsMain = getLocalActivityManager().startActivity(            "DomainNews",intent).getDecorVIEw();        break;      case R.ID.tv_Title_more:        ImageAnimatioin.SetimageSlIDe(tvSelectedItem,itemWIDth * 5,0);        startX = itemWIDth * 5;        tvSelectedItem.setText(R.string.Title_news_category_more);                // 显示更多信息        intent.setClass(MainActivity.this,MoreNews.class);        vNewsMain = getLocalActivityManager().startActivity(            "MoreNews",intent).getDecorVIEw();        break;      default:        break;      }            // 更换Layout中的新闻主体      rlNewsMain.removeAllVIEws();      rlNewsMain.addVIEw(vNewsMain,params);    }  }

这里设置时是在一个主框架中变换新闻类别的布局,而不是直接显示,所以需要注意下。另外,在点击除头条之外的新闻类别时,下方展示的也只是个图片而已,有需要的朋友将其进行改造,这点不再多说。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android实现局部图片滑动指引效果示例全部内容,希望文章能够帮你解决Android实现局部图片滑动指引效果示例所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1147925.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存