使用HorizontalScrollView实现滚动控制

功能要求是屏幕上固定显示 3 个 Layout 项(图片+文字),支持点击切换到选择的 Layout 项,并支持滑动切换到最近的 Layout 项。

专注于为中小企业提供成都做网站、网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业永清免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了1000多家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

最后的效果如下:

使用 HorizontalScrollView 实现滚动控制

 

下面逐步上代码:

 

布局文件 activity_main.xml 如下:

 



    
    
    
        
    

    
    

 

上面的 HorizontalScrollView 中使用了自定义的 HSVLayout 布局,定义(HSVLayout.java)如下:

 

public class HSVLayout extends LinearLayout {

    private HSVAdapter adapter;
    private Context context;

    public HSVLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    /**
     * 设置布局适配器
     *
     * @param layoutWidthPerAvatar 指定了每一个 item 的占用宽度
     * @param adapter 适配器
     * @param notify 在点击某一个 item 后的回调
     */
    public void setAdapter(int layoutWidthPerAvatar, HSVAdapter adapter,
                           final INotifySelectItem notify) {
        this.adapter = adapter;

        for (int i = 0; i < adapter.getCount(); i++) {
            final Map map = adapter.getItem(i);
            View view = adapter.getView(i, null, null);

            // 为视图设定点击监听器
            final int finalI = i;
            view.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 点击选择了某一个 Item 视图
                    notify.select(finalI);
                }
            });

            this.setOrientation(HORIZONTAL);

            // 设置固定显示的每个 item 布局的宽度
            this.addView(view, new LinearLayout.LayoutParams(
                    layoutWidthPerAvatar, LayoutParams.WRAP_CONTENT));
        }
    }
}

 

HSVLayout 中的每一个 视图 item 都是由 HSVAdapter 进行设置的,这个比较简单,只控制了每一个 item 的展示,不影响整个水平滚动视图:

 

public class HSVAdapter extends BaseAdapter {

    private static final String TAG = "HSV";

    private List> lstAvatars;
    private Context context;
    private int layoutWidthPerAvatar;

    public HSVAdapter(Context context, int layoutWidthPerAvatar){
        this.context=context;
        this.lstAvatars =new ArrayList>();
        this.layoutWidthPerAvatar = layoutWidthPerAvatar;
    }
    @Override
    public int getCount() {
        return lstAvatars.size();
    }

    @Override
    public Map getItem(int location) {
        return lstAvatars.get(location);
    }

    @Override
    public long getItemId(int arg0) {
        return arg0;
    }

    public void addObject(Map map){
        lstAvatars.add(map);
        notifyDataSetChanged();
    }

    @Override
    public View getView(int location, View arg1, ViewGroup arg2) {
        View view = LayoutInflater.from(context).inflate(R.layout.user_avatar,null);
        view.setLayoutParams(new ViewGroup.LayoutParams(layoutWidthPerAvatar,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        TextView tvIndex = (TextView) view.findViewById(R.id.index_tv);
        tvIndex.setText("index-" + String.valueOf(location));
        return view;
    }
}

 

其对应的布局文件 user_avatar.xml 如下:

 



    
    

 

最后看一下主页面 MainActivity:

 

public class MainActivity extends ActionBarActivity
    implements INotifySelectItem {

    private static final String TAG = "Main";

    private HorizontalScrollView hsv;
    private HSVLayout layoutAvatar;
    private HSVAdapter adapterAvatar;

    private TextView tvScrollX;

    private int layoutWidthPerAvatar = 0;

    private Integer[] p_w_picpaths = {
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar,
            R.drawable.avatar
    };

    // 记录当前居中的头像索引
    private int currentIndex = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int width = DisplayUtil.getScreenWidth(this);
        int layoutWidth = (int) (width - getResources().getDimension(R.dimen.activity_horizontal_margin) * 2);

        // 每一个头像占用的宽度
        layoutWidthPerAvatar = layoutWidth / 3;

        hsv = (HorizontalScrollView) findViewById(R.id.hsv);
        hsv.setOnTouchListener(new View.OnTouchListener() {

            private int lastScrollX = 0;
            private int TouchEventId = -9987832;

            Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    if (msg.what == TouchEventId) {
                        if (lastScrollX == hsv.getScrollX()) {
                            // 停止滚动,计算合适的位置(采用四舍五入)
                            int indexScrollTo = Math.round(lastScrollX/(layoutWidthPerAvatar*1.0f));
                            Log.d(TAG, "stop scroll - " + lastScrollX
                                    + "|" + layoutWidthPerAvatar
                                    + "|" + lastScrollX/(layoutWidthPerAvatar*1.0f)
                                    + "|" + indexScrollTo);
                            if (indexScrollTo > 0) {
                                hsv.smoothScrollTo(indexScrollTo*layoutWidthPerAvatar, 0);
                            } else {
                                hsv.smoothScrollTo(0, 0);
                            }
                        } else {
                            handler.sendMessageDelayed(
                                    handler.obtainMessage(TouchEventId), 100);
                            lastScrollX = hsv.getScrollX();
                        }
                    }
                }
            };

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.d(TAG, "touch event - action: " + event.getAction()
                        + "|" + event.getX()
                        + "|" + event.getY()
                        + "|" + hsv.getScrollX()
                        + "|" + hsv.getScrollY());
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    handler.sendMessageDelayed(handler.obtainMessage(TouchEventId), 100);
                }
                return false;
            }
        });

        layoutAvatar = (HSVLayout) findViewById(R.id.avatar_layout);
        adapterAvatar = new HSVAdapter(this, layoutWidthPerAvatar);
        for (int i = 0; i < p_w_picpaths.length; i++) {
            Map map = new HashMap();
            map.put("p_w_picpath", p_w_picpaths[i]);
            map.put("index", (i+1));
            adapterAvatar.addObject(map);
        }
        layoutAvatar.setAdapter(layoutWidthPerAvatar, adapterAvatar, this);

        tvScrollX = (TextView) findViewById(R.id.scrollx_tv);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void select(int position) {
        Toast.makeText(this, "select " + String.valueOf(position),
                Toast.LENGTH_SHORT).show();
        if (position > 0) {
            if (currentIndex != position) {
                hsv.smoothScrollTo((position-1)*layoutWidthPerAvatar, 0);
                currentIndex = position;
            }
        }
    }

    public void onClickScrollX(View view) {
        tvScrollX.setText("Scroll.x = " + String.valueOf(hsv.getScrollX()));
    }
}

 


文章题目:使用HorizontalScrollView实现滚动控制
文章来源:http://azwzsj.com/article/pjhdhg.html