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

最后的效果如下:

下面逐步上代码:

布局文件 activity_main.xml 如下:

xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"

android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

android:layout_height="wrap_content" />

android:id="@+id/hsv"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:scrollbarStyle="outsideInset">

android:id="@+id/avatar_layout"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/hsv"

android:layout_marginTop="12dp"

android:id="@+id/scrollx_tv"/>

android:onClick="onClickScrollX"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@id/scrollx_tv"

android:layout_marginTop="12dp"

android:text="滚动位置"/>

上面的 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

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 如下:

android:orientation="vertical"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center">

android:layout_width="64dp"

android:layout_height="64dp"

android:src="@drawable/avatar"/>

android:id="@+id/index_tv"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center" />

最后看一下主页面 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

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()));

}

}

android scrollview居中,使用 HorizontalScrollView 实现滚动控制相关推荐

  1. Android ScrollView嵌套ScrollView滚动的问题解决办法

    引用:http://mengsina.iteye.com/blog/1707464 http://fenglog.com/article.asp?id=449 Android ScrollView嵌套 ...

  2. android ScrollView滚动距离和判断滚动停止状态

    今天很高兴,自己解决了判断ScrollView滚动停止的监听,现在分享给大家. 因为ScrollView没有像listView中的setOnScrollListener()监听,当然也就没有SCROL ...

  3. android图片保存形式,Android应用开发之Android ScrollView截图和图片保存到相册的方式...

    本文将带你了解Android应用开发之Android ScrollView截图和图片保存到相册的方式,希望本文对大家学Android有所帮助. 1.1首先来看你一种截取屏幕,这种代码有缺陷,只能截取一 ...

  4. Android TabHost中实现标签的滚动以及一些TabHost开发的奇怪问题

    最近在使用TabHost的时候遇到了一些奇怪的问题,在这里总结分享备忘一下. 首先说一点TabActivity将会被FragmentActivity所替代,但是本文中却是使用的TabActivity. ...

  5. Android ScrollView

    Android ScrollView allows us to create a scrollable layout on the android screen. Android ScrollView ...

  6. Android ScrollView、NestedScrollView、Horizo​​ntalScrollView 等

    在这篇文章中,我们想看看几个滚动视图的变体或子类以及它们是如何使用的.以下是我们迄今为止涵盖的变体: ScrollView - 超类 NestedScrollView - 子类 Horizo​​nta ...

  7. Android两个tab吸顶,Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每

    Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每 Android scrollView和viewpager嵌套 指示器吸顶 根据viewpager每个 ...

  8. Android ScrollView嵌套GridView导致GridView只显示一行item

    Android ScrollView嵌套GridView导致GridView只显示一行item Android ScrollView在嵌套GridView时候,会导致一个问题发生:GridView只显 ...

  9. Android——仿淘宝头条垂直滚动广告

    淘宝App大家用的都比较多了哈,最近看淘宝头条比较多,就来写个小例子吧. 垂直滚动广告的实现原理其实比较简单,就是定时更新列表内容嘛,然后列表切换的时候再加点炫酷的动画就OK了.如果对Android控 ...

最新文章

  1. 如何定义带有可选参数的函数python_Python如何定义有可选参数的元类
  2. Scala模式匹配的亮点——Martin Odersky访谈(四)
  3. linux mysql忘记root_linux下mysql-5.6忘记root密码,重置root密码详细过程
  4. 怎么在电脑上使用python-开始在 Windows 上使用 Python(初学者)
  5. c# 串口最简单接收十六进制
  6. 我的RHCA之路随想
  7. (Sql Server)SQL FOR XML PATH
  8. harris角点检测的学习
  9. 3.eclipse对mysql云数据库编程增删改查
  10. Hadoop--xsync分发脚本
  11. Android演示Stack(课下作业)
  12. 面试官竟让我用Redis实现一个消息队列!
  13. EF性能优化-有人说EF性能低,我想说:EF确实不如ADO.NET
  14. php odbc 结果集处理,php常用ODBC函数集的简单示例
  15. 蒟蒻7.16题解(选值+遛狗+树上博弈)
  16. C语言实现约瑟夫环代码
  17. 软件测试行业前景,人才稀缺
  18. python if return_python - 使用if-return-return或if-else-return更有效?
  19. Vue源码笔记之项目架构
  20. kernel/Makefile:971: recipe for target ‘prepare3‘ failed

热门文章

  1. 使用ngModel创建组件
  2. Java 注解:@PostConstruct和@PreConstruct
  3. hadoop碰到的 一个问题
  4. Windows中使用wget整站下载
  5. 不同浏览器隐藏默认表单样式
  6. [vagrant]vagrant centos静态ip设置
  7. Android Binder 系统学习笔记(一)Binder系统的基本使用方法
  8. [BC Round#26] Card 【各种水】
  9. 在Windows 7解决GAC错误
  10. C++学习——构造函数,析构函数与虚函数关系