自定义左右滑动图片列表

xml引用

代码初始化

控件代码

package com.feilu.investadviser.ui.main.widget;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

import com.feilu.investadviser.ui.main.adapter.HorizontalScrollViewAdapter;

import java.util.HashMap;
import java.util.Map;

public class HzScrollView extends HorizontalScrollView implements View.OnClickListener {

    /**
     * 图片滚动时的回调接口
     *
     */
    public interface CurrentImageChangeListener {
        void onCurrentImgChanged(int position, View viewIndicator);
    }

    /**
     * 条目点击时的回调
     *
     */
    public interface OnItemClickListener {
        void onClick(View view, int pos);
    }

    private CurrentImageChangeListener mListener;

    private OnItemClickListener mOnClickListener;

    private static final String TAG = "HzScrollView";

    /**
     * HorizontalListView中的LinearLayout
     */
    private LinearLayout mContainer;
    /**
     * 子元素的宽度
     */
    private int mChildWidth;
    /**
     * 子元素的高度
     */
    private int mChildHeight;
    /**
     * 当前最后一张图片的index
     */
    private int mCurrentIndex;
    /**
     * 当前第一张图片的下标
     */
    private int mFristIndex;
    /**
     * 当前第一个View
     */
    private View mFirstView;
    /**
     * 数据适配器
     */
    private HorizontalScrollViewAdapter mAdapter;
    /**
     * 每屏幕最多显示的个数
     */
    private int mCountOneScreen;
    /**
     * 屏幕的宽度
     */
    private int mScreenWitdh;

    /**
     * 保存View与位置的键值对
     */
    private Map<View, Integer> mViewPos = new HashMap<View, Integer>();

    public HzScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 获得屏幕宽度
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        mScreenWitdh = outMetrics.widthPixels;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mContainer = (LinearLayout) getChildAt(0);
    }

    /**
     * 加载下一张图片
     */
    protected void loadNextImg() {
        // 数组边界值计算
        if (mCurrentIndex == mAdapter.getCount() - 1) {
            return;
        }
        // 移除第一张图片,且将水平滚动位置置0
        scrollTo(0, 0);
        mViewPos.remove(mContainer.getChildAt(0));
        mContainer.removeViewAt(0);

        // 获取下一张图片,并且设置onclick事件,且加入容器中
        View view = mAdapter.getView(++mCurrentIndex, null, mContainer);
        view.setOnClickListener(this);
        mContainer.addView(view);
        mViewPos.put(view, mCurrentIndex);

        // 当前第一张图片小标
        mFristIndex++;
        // 如果设置了滚动监听则触发
        if (mListener != null) {
            notifyCurrentImgChanged();
        }

    }

    /**
     * 加载前一张图片
     */
    protected void loadPreImg() {
        // 如果当前已经是第一张,则返回
        if (mFristIndex == 0)
            return;
        // 获得当前应该显示为第一张图片的下标
        int index = mCurrentIndex - mCountOneScreen;
        if (index >= 0) {
            // mContainer = (LinearLayout) getChildAt(0);
            // 移除最后一张
            int oldViewPos = mContainer.getChildCount() - 1;
            mViewPos.remove(mContainer.getChildAt(oldViewPos));
            mContainer.removeViewAt(oldViewPos);

            // 将此View放入第一个位置
            View view = mAdapter.getView(index, null, mContainer);
            mViewPos.put(view, index);
            mContainer.addView(view, 0);
            view.setOnClickListener(this);
            // 水平滚动位置向左移动view的宽度个像素
            scrollTo(mChildWidth, 0);
            // 当前位置--,当前第一个显示的下标--
            mCurrentIndex--;
            mFristIndex--;
            // 回调
            if (mListener != null) {
                notifyCurrentImgChanged();

            }
        }
    }

    /**
     * 滑动时的回调
     */
    public void notifyCurrentImgChanged() {
        // 先清除所有的背景色,点击时会设置为蓝色
        for (int i = 0; i < mContainer.getChildCount(); i++) {
            mContainer.getChildAt(i).setBackgroundColor(Color.WHITE);
        }

        mListener.onCurrentImgChanged(mFristIndex, mContainer.getChildAt(0));

    }

    /**
     * 初始化数据,设置数据适配器
     *
     */
    public void initDatas(HorizontalScrollViewAdapter mAdapter) {
        this.mAdapter = mAdapter;
        mContainer = (LinearLayout) getChildAt(0);
        // 获得适配器中第一个View
        final View view = mAdapter.getView(0, null, mContainer);
        mContainer.addView(view);

        // 强制计算当前View的宽和高
        if (mChildWidth == 0 && mChildHeight == 0) {
            int w = View.MeasureSpec.makeMeasureSpec(0,
                    View.MeasureSpec.UNSPECIFIED);
            int h = View.MeasureSpec.makeMeasureSpec(0,
                    View.MeasureSpec.UNSPECIFIED);
            view.measure(w, h);
            mChildHeight = view.getMeasuredHeight();
            mChildWidth = view.getMeasuredWidth();
            Log.e(TAG, view.getMeasuredWidth() + "," + view.getMeasuredHeight());
            mChildHeight = view.getMeasuredHeight();
            // 计算每次加载多少个View
            mCountOneScreen = mScreenWitdh / mChildWidth + 2;

            Log.e(TAG, "mCountOneScreen = " + mCountOneScreen
                    + " ,mChildWidth = " + mChildWidth);

        }
        // 初始化第一屏幕的元素
        initFirstScreenChildren(mAdapter.getCount());
    }

    /**
     * 加载第一屏的View
     *
     * @param mCountOneScreen
     */
    public void initFirstScreenChildren(int mCountOneScreen) {
        mContainer = (LinearLayout) getChildAt(0);
        mContainer.removeAllViews();
        mViewPos.clear();

        for (int i = 0; i < mCountOneScreen; i++) {
            View view = mAdapter.getView(i, null, mContainer);
            view.setOnClickListener(this);
            mContainer.addView(view);
            mViewPos.put(view, i);
            mCurrentIndex = i;
        }

        if (mListener != null) {
            notifyCurrentImgChanged();
        }

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                // Log.e(TAG, getScrollX() + "");

                int scrollX = getScrollX();
                // 如果当前scrollX为view的宽度,加载下一张,移除第一张
                if (scrollX >= mChildWidth) {
                    loadNextImg();
                }
                // 如果当前scrollX = 0, 往前设置一张,移除最后一张
                if (scrollX == 0) {
                    loadPreImg();
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    @Override
    public void onClick(View v) {
        if (mOnClickListener != null) {
            for (int i = 0; i < mContainer.getChildCount(); i++) {
                mContainer.getChildAt(i).setBackgroundColor(Color.WHITE);
            }
            mOnClickListener.onClick(v, mViewPos.get(v));
        }
    }

    public void setOnItemClickListener(OnItemClickListener mOnClickListener) {
        this.mOnClickListener = mOnClickListener;
    }

    public void setCurrentImageChangeListener(
            CurrentImageChangeListener mListener) {
        this.mListener = mListener;
    }

}

adapter

package com.feilu.investadviser.ui.main.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.feilu.investadviser.R;
import com.feilu.investadviser.ui.main.bean.RanksRenQiEntity;

import java.util.List;

public class HorizontalScrollViewAdapter {

    private Context context;
    private LayoutInflater mInflater;
    private List<RanksRenQiEntity.DataBean> mDatas;

    public HorizontalScrollViewAdapter(Context context, List<RanksRenQiEntity.DataBean> mDatas) {
        this.context = context;
        mInflater = LayoutInflater.from(context);
        this.mDatas = mDatas;
    }

    public int getCount() {
        return mDatas.size();
    }

    public RanksRenQiEntity.DataBean getItem(int position) {
        return mDatas.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public void setList(List<RanksRenQiEntity.DataBean> mDatas){
        this.mDatas.clear();
        this.mDatas.addAll(mDatas);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.item_ranks_scroll,
                    parent, false);
//            holder.mImg = (ImageView) convertView.findViewById(R.id.img);
//            holder.del = (ImageView) convertView.findViewById(R.id.del);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        return convertView;
    }

    static class ViewHolder {

    }

}

时间: 2024-08-01 12:20:17

自定义左右滑动图片列表的相关文章

WP8_区分滑动和点击(在图片列表中)

在windows phone中,对于一个页面中 有图片列表的,滑动的时候,很容易被误认为是点击了图片,而打开图片详细信息等,原意是滑动列表,由此对图片添加2个事件,来控制其点击行为(滑动的时候,基本不会执行到do clicked something处)   private bool _isClickEnable = false; private DateTime _clickedTime;   private void Img1_OnMouseLeftButtonDown(object send

WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表

原文:WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表 一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目开发中图片的各种使用问题,经过总结,把一些经验分享一下.内容包括: WPF常用图像数据源ImageSource的创建: 自定义缩略图控件ThumbnailImage,支持网络图片.大图片.图片异步加载

WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果

原文:WPF技术触屏上的应用系列(五): 图片列表异步加载.手指进行缩小.放大.拖动 .惯性滑入滑出等效果 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶鸭子上架了,经过努力

实现一个最简单图片列表所引发的问题

前一阵看了些Universal-Image-Loager的源码.我觉得看源码很累的一个原因就是除了看怎么实现,就是去揣测为什么这么实现.这个揣测的过程很容易走马观花,看到后面似懂非懂. 人懒到一个地步一句话来说是能躺着就绝对不坐着,能坐着就绝对不蹲着,能蹲着就绝对不站着.有时候看源码也是,能看懂就不会想着去debug,debug能看明白的就懒得去动手写写. 看和写的感受是不一样的.看的是结果,写的是过程. 第三方库的使用让开发变得很方便,大量图片请求的实现,大多数不再是说实现的核心,而是直接说使

[读码时间] 图片列表:鼠标移入/移出改变图片透明度

说明:代码来自网络.注释为笔者学习时添加. <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>图片列表:鼠标移入/移出改变图片透明度</title> <style> ul,li{ /*去除内外边距,去除列表默认样式*/ margin:0; padding:0; list-style-type:none; } #imgList{ /

Android 自定义Gallery浏览图片

之前写的<Android ImageSwitcher和Gallery的使用>一文中提到我在教室一下午为实现那个效果找各种资料.期间在网上找了一个个人觉得比较不错的效果,现在贴图上来: 其实这个效果使用的知识点就是图像的获取.创建.缩放.旋转.Matrix类.Canvas类等,另外就是自定义的Gallery控件. 相信大家都期待马上上代码了吧,嘻嘻.(注释比较多,相信大家都能看懂.) main.xml: <?xml version="1.0" encoding=&quo

非等宽图片列表的布局

各大搜索引擎的图片频道的搜索结果页,搜索出来的结果都是较零碎的图片,图片质量.尺寸都是参差不齐的,并限定了每一行的总宽度.这种非等宽的图片列表,在Google+.flickr也都有用到. 最近刚好对360搜索的图片搜索结果页进行了一次重构和改版,对于这种图片布局也花心思研究了一番,接下来说说我的一些处理思路. 非等宽的单个图片要排列到一个固定了宽度的容器中,那么这个等宽的容器就是最大的限制和障碍,开始怀念那种常见等宽瀑布流的布局(没有限制真好). 先理下基本的需求: 1.图片的宽度是不固定的:

jQuery演示10种不同的切换图片列表动画效果

经常用到的图片插件演示jQuery十种不同的切换图片列表动画效果 在线演示 下载地址 实例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <!DOCTYPE html> <html lang="en" class="no-

函数传参,改变Div任意属性的值&amp;&amp;图片列表:鼠标移入/移出改变图片透明度

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-