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

最近做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. node-mysql中的连接池代码学习

    node-mysql是一个node.js下的mysql驱动,前段时间在处理连接池的问题上遇到了连接不释放的疑难杂症,虽已解决,但仍需总结经验避免下次重蹈覆辙.下面是node-mysql中的连接池的部分 ...

  2. Python覆盖率分析工具_Coverage

    easy_install安装: easy_install coverage 运行: coverage run test.py coverage report

  3. 如何学习java ee

    来看看Sun给出的J2EE 相关技术主要分为几大块. 1. Web Service技术 -  Java API for XML Processing (JAXP) -  Java API for XM ...

  4. Cocos2dx-截屏并设置图片尺寸

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=522 前几天添加微信图片分享的时 ...

  5. homework-01 "最大子数组之和"的问题求解过程

    写在前面:我的算法能力很弱,并且也是第一次写博文,总之希望自己能在这次的课程中学到很多贴近实践的东西吧. 1.这次的程序是python写的,这也算是我第一次正正经经地拿python来写东西,结果上来说 ...

  6. homework 08_2 C++11新特性作业之二

    ---恢复内容开始--- 1.使用Lambda表达式计算“hello world!”中字母e和i的数量 下面是代码: #include "stdafx.h" #include< ...

  7. 扩展KMP--求字符串S的所有后缀和字符串T的最长公共前缀

    在解上面这个问题前我们要先解决一个类似的问题:求字符串s的所有后缀和s本身的最长公共前缀: 我们用next[]数组保存这些值: 现在我们假设要求next[ x ],并且next[ i ] 0<i ...

  8. codeforces 651B Beautiful Paintings

    B. Beautiful Paintings time limit per test 1 second memory limit per test 256 megabytes input standa ...

  9. POJ 2777 Count Color (线段树成段更新+二进制思维)

    题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的 ...

  10. [置顶] 很荣幸被选为2013年度 CSDN博客之星评选,如果觉得我的文章可以,请投我一票!

    亲爱的小伙伴们,很荣幸我被选为<2013年度CSDN博客之星候选人>,希望大家多多支持,geekguy会继续努力,为大家奉献更好的文章. 投票地址:http://vote.blog.csd ...