作为一个刚毕业的大学生,我要提醒自己时时刻刻要学习。

最近做listview看到很久以前的一个demo,高手如云啊,我们就只有好好加油了。

这是索尼公司的一个员工写的学习博客,由于本人英文能力有限是按照自己的理解来的,可能有些地方是错误的,还请各位勘正。

原文链接

The standard Android list view has support for quite a lot of things and covers almost all the use-cases you could think of. However, the look of the list is quite ordinary and while you can do some things by extending it, you will not be able to do that much in the end. Another disadvantage of the standard ListView is the lack of good physics (and the ability to change it). Therefore, if you want your UI to be a bit less ordinary looking, you simply need to implement your own view.

android官方提供的ListView已经支持了好多功能和满足了几乎全部的你可以想到的需求。但是,Listview的外观在拓展时还是显得很一般,且我们也不能在最后能做什么。另一个标准的LIstview缺乏好的控制。因此,若是你不想的你的UI显得很大众,那就要你来实现你自己的View。

Hello AdapterView

Since we’re aiming for a list (that will show other views) we need to extend a ViewGroup and the most fitting of those are AdapterView. (The reason, or rather one reason, we’re not extending AbsListView is that it will not allow us to do bounce effects on the list.) So let’s start by creating a new Android project and create a class, MyListView, that extends AdapterView<Adapter>. AdapterView has four abstract methods that we need to implement: getAdapter(), setAdapter(), getSelectedView() and setSelection(). getAdapter() and setAdapter() are straight forward to implement. The other two will for the moment just throw an exception.

因为我们是要展示一系列数据,我们需要自己来拓展ViewGroup并且最合适的是AdapterView了。(不拓展AbsListview的一个理由就是它不允许我们在listview的每一个边界上来设置一些特效。)就让我们来创建一个ANdroid工程和一个继承了AdapterView<Adapter>. Mylistview类。AdapterView<Adapter>这个类有四个我们必须要实现的函数,那就是getAdapter(), setAdapter(), getSelectedView() and setSelection(). 其中前两个就直接来实现,后两个就直接抛出异常。

package com.sonyericsson.tutorial.list;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView; public class MyListView extends AdapterView { /** The adapter with all the data */
private Adapter mAdapter; public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
removeAllViewsInLayout();
requestLayout();
} @Override
public Adapter getAdapter() {
return mAdapter;
} @Override
public void setSelection(int position) {
throw new UnsupportedOperationException("Not supported");
} @Override
public View getSelectedView() {
throw new UnsupportedOperationException("Not supported");
}
}

The only thing here worth mentioning is the setAdapter method. When we get a new adapter we clear all the views we might have had previously and then we request a layout to get and position the views from the adapter. If we at this point create a test activity and an adapter with some fake data and use our new view, we will not get anything on the screen. This is because if we want to get something on the screen we need to override the onLayout() method.

这个仅有的我们需要注意的是setAdapter方法。当我们得到一个新的adapter对象,我们要清除掉前面添加的所有的view,并且为每一个在Adapter里的view请求重新布局。如果此时我们创建一个测试的Activity和一个Adapter

用一些模拟数据和新的视图View,在屏幕上会什么也不会显示,这是因为,要想在屏幕上显示,我们必须实现OnLayout方法。

Showing our first views

It is in onLayout where we get the views from the adapter and add them as child views.

就是在onLayout方法里,我们从Adapter对象里得到了每个view,并把他们都加到list视图里。

 
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom); // if we don't have an adapter, we don't need to do anything
if (mAdapter == null) {
return;
} if (getChildCount() == 0) {
int position = 0;
int bottomEdge = 0;
while (bottomEdge< getHeight() && position< mAdapter.getCount()) {
View newBottomChild = mAdapter.getView(position, null, this);
addAndMeasureChild(newBottomChild);
bottomEdge += newBottomChild.getMeasuredHeight();
position++;
}
} positionItems();
}

So, what happens here? First a call to super and a null check are performed, and then we continue with the actual code. If we haven’t added any children yet, we start by doing that. The while statement loops through the adapter until we’ve added enough views to cover the screen. When we get a view from the adapter, we start by adding it as a child and then we need to measure it in order for the view to get it’s correct size. After we’ve added all the views, we position them in the correct place.

嗯,这是干嘛呢?首先是调用super()函数,检查adapter是否为空,若不是就执行相关代码。若是没有子view可加入到listview中,有子view时就通过Adapter来循环获取子view知道我们将所有的子view填充到屏幕中。当我们从adapter获取一个view时,我们就将他加入到listview中并计算获取其正确的尺寸,而后就将他们有序地放到正确的位置上。

/**
* Adds a view as a child view and takes care of measuring it
*
* @param child The view to add
*/
private void addAndMeasureChild(View child) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
addViewInLayout(child, -1, params, true); int itemWidth = getWidth();
child.measure(MeasureSpec.EXACTLY | itemWidth, MeasureSpec.UNSPECIFIED);
} /**
* Positions the children at the &quot;correct&quot; positions
*/
private void positionItems() {
int top = 0; for (int index = 0; index< getChildCount(); index++) {
View child = getChildAt(index); int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
int left = (getWidth() - width) / 2; child.layout(left, top, left + width, top + height);
top += height;
}
}
 

The code here is straight forward and self-explanatory so I won’t go into details. I’ve taken some shortcuts when measuring the child view but the code works quite well in most cases. positionItems() starts at the top (0) and layouts the child views one after the other without any padding between them. Also worth noting is that we’re ignoring the possible padding that the list can have.

Scrolling

If we run this code we will now get something on the screen. However, it’s not very interactive. It does not scroll when we touch the screen and we can’t click on any item. To get touch working in the list we need to overrideonTouchEvent().

The touch logic for just scrolling is pretty simple. When we get a down event, we save both the position of the down event and the position of the list. We will use the top of the first item to represent the list position. When we get a move event we calculate how far we are from the down event and then re-position the list using the difference in distance from the start position. If we have

no child views, we just return false.

@Override
public boolean onTouchEvent(MotionEvent event) {
if (getChildCount() == 0) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchStartY = (int)event.getY();
mListTopStart = getChildAt(0).getTop();
break; case MotionEvent.ACTION_MOVE:
int scrolledDistance = (int)event.getY() - mTouchStartY;
mListTop = mListTopStart + scrolledDistance;
requestLayout();
break; default:
break;
}
return true;
}
 

The position of the list is now determined by mListTop and whenever it changes we need to request a layout in order to actually re-position the views. Our previous implementation of positionItems() always started to layout from 0. Now we need to change it so that it starts from mListTop.

If we try this out now the scrolling will work fine but we can also spot some obvious problems with our list. First, the scrolling has no limits so we can scroll the list so that all items are outside of the screen. We will need some kind of limits check to prevent us from doing that. Second, if we scroll down we also see that only the items that we had from the beginning are displayed. No new items are displayed even though the adapter contains more items. We postpone the fix of the first problem to a later tutorial but let’s fix the second problem right away.

3d ListView翻译的更多相关文章

  1. Unity3D基础知识梳理

    这段时间在做Unity的项目,这差不多是我的第一次实战啊~然后公司来了实习的童鞋要学Unity,但是我一向不靠谱啊,所以只能帮他们稍微梳理下基础的东西了啊,唉~学长只能帮你们到这里了~顺便就把自己这两 ...

  2. 13号中断 int 13(转)

    第一部分      简      介      1,1      一.    硬盘结构简介              1.    硬盘参数释疑              到目前为止,    人们常说的 ...

  3. Unity3D用户手册

    Unity Manual 用户手册 Welcome to Unity. 欢迎使用Unity. Unity is made to empower users to create the best int ...

  4. 网页3D引擎“Babylon.JS”入门教程翻译总结

    使用三个月的业余时间把官方教程的入门部分译为中文并上传到github,在下一步编程前做一个总结. 历程: 最早接触游戏编程是在大三下学期,用汇编语言和实验室里的单片机.触摸屏.电机(提供声效)编的打地 ...

  5. 【翻译】西川善司的「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,后篇

    http://www.4gamer.net/games/216/G021678/20140714079/     连载第2回的本回,  Arc System Works开发的格斗游戏「GUILTY G ...

  6. 使用定制的ArrayAdapter制作ListView的Items(翻译)

    Translated by:AcerWang    原文出自:customizing-android-listview-items-with-custom-arrayadapter  背景介绍 对于现 ...

  7. 《Programming WPF》翻译 第7章 6.视频和3-D

    原文:<Programming WPF>翻译 第7章 6.视频和3-D 虽然详细地讨论视频和3-D超越了这本书的范围,但是获得这些特征的支持是值得的. 视频由MediaElement类型支 ...

  8. (翻译) Android ListView 性能优化指南

    本文翻译了Lucas Rocha的Performance Tips for Android’s ListView.这是一篇关于介绍如何提升ListView性能的文章,非常的优秀.使得我拜读之后,忍不住 ...

  9. 【翻译】基于web创建逼真的3D图形 | CSS技巧

    个人翻译小站:http://www.zcfy.cc/article/creating-photorealistic-3d-graphics-on-the-web-css-tricks-4039.htm ...

随机推荐

  1. Codeforces 372

    A (被装的袋鼠不可以装的袋鼠)贪心,排序,从n/2分成两部分. B 好一道前缀和的题目. C 标准算法不难想,m^2的算法见http://codeforces.com/blog/entry/9907 ...

  2. 第二百六十七天 how can I 坚持

    晚上有点小郁闷,小纠结,感觉不应该买房,不知道什么吸引着我一定要买呢,曾经坚持不买房的我,为什么成了这个样子. 搞不懂啊. 元旦就要就看房了, 如果真的要买了,明年的压力就会很大了. 经济到底会成为啥 ...

  3. 第二百四十天 how can I 坚持

    在家待了一天,晚上出去买了个帽子,还有买了点排骨炖着吃了... 玩了好多局游戏. 想搞个直播,不知道能不能玩的起来. 水平太菜了,明天去小米之家玩玩. 睡觉.

  4. CoffeeScript学习(3)—— 函数

    CoffeeScript函数 如果大家有看我之前关于ES6的箭头函数的话,这一篇也不会很难理解.我们这一次可以说一下,关于两者的一些细微差别. 基本 在CoffeeScript中,任何函数都是用箭头函 ...

  5. 关于INTRAWEB ISAPI DLL发布

    怎样将Stand Alone App变为ISAPI Dll? 一是将工程文件中的program改成library,二是将uses里的IWInitStandAlone改成IWInitISAPI,没有该文 ...

  6. redis的使用

    phpredis是php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系 很有用;以下是redis官方提供的命令使用技巧: 下载地址如下: https://github.com/ow ...

  7. radio select的 option使用

    1  radio的使用 <td id="sex">性别:              <input type="radio" name=&quo ...

  8. sgu - 274 - Spam-filter

    题意:判断一个字符串是不是有效的邮件地址. 题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=274 ——>>照着题目做. ...

  9. 利用tcpdump抓取mysql sql语句

    这个脚本是我之前在网上无意间找个一个利用tcpdump 抓包工具获取mysql流量,并通过过滤把sql 语句输入. 脚本不是很长,但是效果很好. #!/bin/bash #this script us ...

  10. 解决ccSvcHst.exe CPU占用超50%的问题,及其缘由

    无意中发现任务管理器中一个非常奇特的进程,迅速吃掉了我50%的cpu资源,并且是持续性的,于是上google一番查找,终于有了新的发现. 非常多问答产品所有都是清一色的 错误解决方式: 正常情况下,系 ...