当前位置:  编程技术>移动开发
本页文章导读:
    ▪listview反弹兑现详解        listview反弹实现详解 重写listview,通过监听滑动事件,根据滑动时所处的位置,以及滑动的方向,使用view的内置scrollTo或scrollBy函数来移动view到你手势互动的距离(此处为一半),然后当确定.........
    ▪ NDK进阶范例        NDK进阶实例 网上也有一些对NDK的介绍,不过都是很简单的把sample里面的例子讲解一下,并不深入,我这里把我的所得分享一下。我下载的是Android Native Developer Kit (NDK) R4版本,当前的最新版。.........
    ▪ Activity(Intent)来传数据详解 startActivityForResult()       Activity(Intent)回传数据详解 startActivityForResult() startActivityForResult()的用法其实很简单,弄清楚API文档中的传递流程和参数一般不会出错。 (1)startActivity()是异步操作,开启新的A.........

[1]listview反弹兑现详解
    来源: 互联网  发布时间: 2014-02-18
listview反弹实现详解

重写listview,通过监听滑动事件,根据滑动时所处的位置,以及滑动的方向,使用view的内置scrollTo或scrollBy函数来移动view到你手势互动的距离(此处为一半),然后当确定消费了给事件后,又回滚到(0,0)点。当然只有在超出了边界时才回滚。而且回滚的过程由TranslateAnimation来控制,这样的好处在代码的解释中。我是基于网络上的listviewpress改了一些(有几处好像是被篡改了,我又按我的理解将它改正过来,运行后没问题)。一下是关键的代码,整个代码见附件中。有不懂的可以问问,大家互相学习。

 

 

 

package com.listview.test;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.animation.TranslateAnimation;
import android.widget.ListView;

public class CustomerListView extends ListView {

	private Context mContext;
	private boolean outBound = false;
	private int distance;
	private int firstOut;

	public CustomerListView(Context c) {
		super(c);
		this.mContext = c;
	}

	public CustomerListView(Context c, AttributeSet attrs) {
		super(c, attrs);
		this.mContext = c;
	}

	public CustomerListView(Context c, AttributeSet attrs, int defStyle) {
		super(c, attrs, defStyle);
		this.mContext = c;
	}

	GestureDetector gestureDetector = new GestureDetector(
			new OnGestureListener() {

				public boolean onDown(MotionEvent e) {
					// TODO Auto-generated method stub
					return false;
				}

				public boolean onFling(MotionEvent e1, MotionEvent e2,
						float velocityX, float velocityY) {
					// TODO Auto-generated method stub
					return false;
				}

				public void onLongPress(MotionEvent e) {
					// TODO Auto-generated method stub

				}
/**捕捉滑动事件  e1为此处为的ACTION_DOWN事件(无论什么动作,起始都是该动作),而e2是触发调用onScroll的事件。而在此期间,可能已经
 * 触发了多次的onScroll,因为我们滑动过程可能比较长,一旦长于某个值,就会触发一次(即一个Move应该是由多个
 * move事件组成的,开头当然是个ACTION_DOWN事件),也就会发出一个移动的MotionEvent。但是期间开始此次
 * scroll的e1是唯一的。而distance是最近一次调用onScroll以来的距离(前一个e2和现在e2的距离:比如上次是-30,这次是-60(比如向下拉),
 * 那么 distanceY=-60-(-30)=-30)。
 */

				public boolean onScroll(MotionEvent e1, MotionEvent e2,
						float distanceX, float distanceY) {
					/**
					 * firstPos和lastPos是adapter中元素的Id
					 */
					int firstPos = getFirstVisiblePosition();
					int lastPos = getLastVisiblePosition();
					int itemCount = getCount();
					
					/**
					 * 滑出边界,而且是一个极点,即可视部分已经已经不存在了,那么直接回到原点
					 */
					if (outBound && firstPos != 0 && lastPos != (itemCount - 1)) {
						scrollTo(0, 0);
						return false;
					}
					/**
					 * getChildAt是屏幕上可见的元素的id,比如现在屏幕上可见的是adapter中的
					 * 4号到10号,那么你调用getChildAt应该是0~6号 
					 * listView.getChildAt(i) works where 0 is the very first visible row and
					 *  (n-1) is the last visible row (where n is the number of visible views you see).
					 *  进入该onScroll有4种可能,第一种是刚开始的时候,此时firstPos==0,而且可视的item在getChildAt的
					 *  返回也是第一个元素,即adapter元素的index和可视的view的编号一致,所以firstview不为空(lastview也一样)。
					 *  当你向上 滑动时,distanceY是大于0的。此时将不消费此次事件,那么将正常地在没有超出边际出滚动。
					 *  第二种是,若以上是向下拉,那么应该属于超出范围的情况,则要消费此时事件。
					 *  第三种和第一种类似,只是到了当刚好显示最后一个item时,显然firstView和lastView都将是null,因为
					 *  此时的adapter的index和getChildAt的index不是相等的,而是成对应关系,
					 *  即index_adp-firstPos=index_getChild,此时你若使用getChildAt(firstpos-firstpos),那返回的
					 *  将是非null。同理在lastView。第四种是当在第三情况下,向上拉,那么属于超出边界。那么lastView是null这个特征
					 *  将可以判断是否进入了下临界区。
					 *  总结以上四种情况,每当触发临界区时(dispatchTouchEvent时getFirstVisiblePosition()==0
					 *  和getLastVisiblePosition()==getCount()-1),就可以通过distanceY的方向性判断是正常的滑动
					 *  还是将要滑出临界区。若是滑出临界区,说明此次将消费该事件,所以返回true,那么在dispatchTouchEvent
					 *  将设置outBand为true,那么第二次再进入时,将可以通过outBand来确定是否出了临界区。
					 *  
					 *  带方向的函数:onScrollBy/To和onScroll
					 */
					View firstView = getChildAt(firstPos);
					View lastView = getChildAt(lastPos-1);
				/**
				 * 记录下第一次的e2的y轴距离,此次过后outBound就变为了true。这样distance就是跟踪最近的一次e2
				 * 和最开始一次的e2的距离。
				 */
					if (!outBound) {
						firstOut = (int) e2.getRawY();
					}
					if (firstView != null
							&& (outBound || (firstPos == 0
									&& firstView.getTop() == 0 && distanceY < 0))) {
						distance = (int) (firstOut - e2.getRawY());//此处应为负值,即view向下滑动
				/**
				 * scrollBy中的值带有方向,x若为正,则应该以view中该x点显示在新的原点上,即拿新的点去
				*重合y轴,就好像整个布局被往左拉动。
				 * y为正,则向上滑动|y|距离。负则相反。
				 */
						scrollBy(0, distance / 2);
						Log.v("onScroll", "e2.getRawY():"+e2.getRawY());
						Log.v("onScroll", "distance:"+distance);
						Log.v("onScroll", "distanceY:"+distanceY);
						return true;
					}
					if (lastView == null&&(outBound || (lastPos == itemCount - 1 && distanceY > 0))) {
						Log.d("bottom", "bottom");
						distance = (int) (firstOut - e2.getRawY());//此处应为正直,因为view向上滑动
						scrollBy(0, distance/2);
						return true;
					}
					return false;
				}

				public void onShowPress(MotionEvent e) {
					// TODO Auto-generated method stub

				}

				public boolean onSingleTapUp(MotionEvent e) {
					// TODO Auto-generated method stub
					return false;
				}
			});

	/**
	 * 最早响应触屏事件,按下和释放响应两次
	 */
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if(getFirstVisiblePosition()==0){
			int act = ev.getAction();
			if ((act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_CANCEL)
					&& outBound) {
				outBound = false;
			}
			if (!gestureDetector.onTouchEvent(ev)) {
				outBound = false;
			} else {
				outBound = true;
			}
			Rect rect = new Rect();
			getLocalVisibleRect(rect);
			/**
			 * rect.top是个正的距离值,而TanslateAnimation填的是坐标值(有方向的);
			 */
			TranslateAnimation am = new TranslateAnimation(0, 0, -rect.top, 0);
			/**
			 * 若此处时间设为0,将导致一阵的抖动,因为完成回滚的速度不是分步,而是直接到终点
			 * 因为每次触发onScroll时都会做一次回滚,而当传进又一次move时,上一次的move还没作完
			 * 就将被新的一次覆盖,所以不用担心产生抖动。所以此处给它设时间就是抓住它需要时间来完成回滚的目标,相当
			 * 于给它一个时间的缓冲来实现移动,因为当你在移动时,实际是不需要回滚的,只有你释放了手指还才需要回滚。
			 * 注意,此时调用scrollTo已经将位置返回了0(可以把animation当成是模型,只有使用scrollTo才
			 * 能真正触发该移动,结果是已经知道了的,即移动到原点,而过程是TranslateAnimation参谋的,即
			 * scrollTo在移动时会调用onScrollChange来实际移动,而onScrollChange则根据传入的参数来移动
			 * 而TranslateAnimation则可以控制该参数。可以把scrollTo先去掉,就可以发现new top 和
			 * after scrollBy是一样的值)。也就是new Top=0。所以每次迭代相减都是现在的e2减去最初的e2在y轴上的值,
			 * 这样通过scrollBy就可以将view移动到新的位置,而此时top也就又被写成了新的滑动的位置(是滑动距离的一半位置)。
			 * 11-19 23:51:11.101: V/onScroll(18396): after scrollBy top:0
				11-19 23:51:11.101: V/onScroll(18396): new top:0
				11-19 23:51:11.249: V/onScroll(18396): after scrollBy top:0
				11-19 23:51:11.249: V/onScroll(18396): new top:0
				11-19 23:51:11.288: V/onScroll(18396): after scrollBy top:-6
				11-19 23:51:11.288: V/onScroll(18396): new top:0
				11-19 23:51:11.319: V/onScroll(18396): after scrollBy top:-16
				11-19 23:51:11.319: V/onScroll(18396): new top:0
				11-19 23:51:11.358: V/onScroll(18396): after scrollBy top:-20
				11-19 23:51:11.358: V/onScroll(18396): new top:0
				11-19 23:51:11.374: V/onScroll(18396): after scrollBy top:-27
				11-19 23:51:11.374: V/onScroll(18396): new top:0
			 */
			am.setDuration(300);
			startAnimation(am);
			Log.v("onScroll","after scrollBy top:"+rect.top);
			scrollTo(0, 0);
			getLocalVisibleRect(rect);
     		Log.v("onScroll", "new top:"+rect.top);
		}
		Log.d("getLastVisiblePosition()", getLastVisiblePosition()+"");
		Log.d("getCount()", getCount()+"");
		if(getLastVisiblePosition()==getCount()-1){
			int act = ev.getAction();
			if ((act == MotionEvent.ACTION_DOWN || act == MotionEvent.ACTION_CANCEL)
					&& outBound) {
				outBound = false;
			}
			if (!gestureDetector.onTouchEvent(ev)) {
				outBound = false;
			} else {
				outBound = true;
			}
			if(outBound){
				Rect rect1 = new Rect();
				getLocalVisibleRect(rect1);
				TranslateAnimation am1 = new TranslateAnimation(0, 0, rect1.top, 0);
				am1.setDuration(300);
				startAnimation(am1);
				scrollTo(0, 0);
			}
		}
		return super.dispatchTouchEvent(ev);
	};
}
1 楼 真心等候 2012-06-09  
想做这样的功能久了。感谢

    
[2] NDK进阶范例
    来源: 互联网  发布时间: 2014-02-18
NDK进阶实例

网上也有一些对NDK的介绍,不过都是很简单的把sample里面的例子讲解一下,并不深入,我这里把我的所得分享一下。我下载的是Android Native Developer Kit (NDK) R4版本,当前的最新版。
    下载地址如下:
    http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip

 

    我下面讲的都是以linux环境为准,因为我的系统是linux的。windows下可以弄个Cygwin,模拟linux环境,网上有很多介绍。
    首先进入ndk目录,有个README文件,里面提到了API的文档在docs/STABLE-APIS.TXT里面,如何安装NDK,参考docs/INSTALL.TXT,还有如何使用NDK,参考docs/HOWTO.TXT。建议这些文档都看一遍,有个大概了解。

 

    安装:
    INSTALL.TXT里面讲的是如何安装,安装NDK,就需要一个可以make环境,linux自带了,所以不用关心。还有一点,以前的版本都需要运行build/host-setup.sh来进行初始化,这个版本把它删除了,这样更方便。
    然后就是配置环境变量。
    在~/.bashrc文件里面,添加   

Shell代码

 

NDK_ROOT=~/android-ndk-r4b #后面的路径是NDK所在的目录,根据自己的目录修改
export NDK_ROOT

 然后保存,重新打开bash。

 

    使用:
    先拿sample试刀吧,刚开始什么都不知道,只有运行出一个例子,才能增加信心。
    编译的两种方法:
    1.进入要目标工程目录,比如$NDK_ROOT/samples/hello-jni,然后执行$NDK_ROOT/ndk-build
    2.在任何地方,执行$NDK_ROOT/ndk-build -C $NDK_ROOT/samples/hello-jni.
    如果成功的话,会生成obj和libs两个目录。
    选择一种方法,编译这个例子。然后打开eclipse,把hello-jni这个工程导入,运行,ok,就能看到效果了。

 

    进阶:
    docs下的STABLE-APIS.TXT里面讲了系统API的用法。我以1.5为例。进入$NDK_ROOT/build/platforms/android-3/arch-arm/usr/include,里面有很多.h文件,这些都是可以在NDK里面调用的,除了linux和asm目录下的。
    一般来说,主要用到的是jni.h,里面提供了很多对类和对象的操作。
    另外,1.5提供了log的API,在android/log.h里面,使用的时候,在c文件中#include <android/log.h>,然后在Android.mk里面加上LOCAL_LDLIBS := -llog,就可以了。
    1.6到2.01提供了openGL ES 1.x的API,2.1提供了openGL ES 2.0的API,2.2提供了graphics的处理接口。使用方法同log。

 

    实例:
    给出两个点的坐标,求它们的距离。
    首先,创建一个Point对象,

public class Point {
	float x;
	float y;
}

 然后在c文件中定义一个函数   

jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b){}

 返回值是float,在jni中定义的是jfloat。

    函数名规则: Java开头,接着是包名的每一段,然后是类名,最后是Java中调用的方法名,中间都用下划线隔开。第一个参数JNIEnv* env和第二个参数jobject thiz都是必须的,后面的才是Java中传递进来的参数。这里是两个Point对象。


    首先确定要做的步骤:
    1.找到这个Point类
    2.找到类中的域x和y的域id
    3.根据ID取出x和y的值
    4.计算结果并返回
    那么代码如下:

#include <jni.h>
#include <math.h>
#include <android/log.h>

jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b)
{
        //步骤1
	jclass point_class = (*env)->FindClass(env, "chroya/demo/ndk/Point");
	if(point_class == NULL) {
		//printf("class not found");
		__android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "class Point not found");
		return 0;
	} else {
		__android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "found class Point");
	}
        //步骤2
	jfieldID field_x = (*env)->GetFieldID(env, point_class, "x", "F");
	jfieldID field_y = (*env)->GetFieldID(env, point_class, "y", "F");
        //步骤3
	jfloat ax = (*env)->GetFloatField(env, a, field_x);
	jfloat ay = (*env)->GetFloatField(env, a, field_y);
	jfloat bx = (*env)->GetFloatField(env, b, field_x);
	jfloat by = (*env)->GetFloatField(env, b, field_y);
        //步骤4
	return sqrtf(powf(bx-ax, 2) + powf(by-ay, 2));
}

 

然后在Java里面调用:

public class Main extends Activity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(getApplicationContext());
        Point a = new Point();
        a.x = 3;
        a.y = 3;
        
        Point b = new Point();
        b.x = 5;
        b.y = 5;
        
        float d = distance(a,b);
        tv.setText("distance(a,b):"+d);
        setContentView(tv);
    }
    
    public native float distance(Point a, Point b);
    
    static {
    	System.loadLibrary("demo");
    }
}

 

  运行,得到结果distance(a,b):2.828427

      源码参见附件 。

摘自:http://www.iteye.com/topic/729133


    
[3] Activity(Intent)来传数据详解 startActivityForResult()
    来源: 互联网  发布时间: 2014-02-18
Activity(Intent)回传数据详解 startActivityForResult()
startActivityForResult()的用法其实很简单,弄清楚API文档中的传递流程和参数一般不会出错。

(1)startActivity()是异步操作,开启新的ActivityB与原ActivityA异步执行。 (2)startActivityForResult()是同步操作,ActivityA在开启新的ActivityB后将自己堵塞,只到ActivityB退出后ActivityA才继续执行,并根据ActivityB返回的结果进行下一步操作。

假设现在有两个Activity:A与B,A通过startActivityForResult()方法开启B,则方法的使用及流程如下。

<1>在A中:

startActivityForResult(Intent intent, Int requestCode)
intent指定了要开启B,且包含了从A传给B的数据。
requestCode >=0,如果A还要开启C,D那么requestCode就对应不同的值,以此区分。在后面的onActivityResult()中,需要以此来区分各个子Activity传回的结果。
如: startActivityForResult(intent,1);  --1:B
startActivityForResult(intent,2);  --2:C
startActivityForResult(intent,3);  --3:C
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
              case 1:
                    ...
                    break;
              case 2:
                    ...
                    break;
               case 3:
                    ...
                    break;
            default:
             break;
}

<2>在B中:

setResut(int resultCode, Intent intent)
resultCode 如果B可能有几种不同的返回结果,需要用这个参数来识别。
intent 在这里指定了返回A,主要是用来放额外的数据,最终会传回给A的onActivityResult()

<3>最后在A中:

onActivityResult(int requestCode, int resultCode, Intent intent)

requestCode用来区分具体是哪个子Activity传回来的。

resultCode用来区分该子Activity返回的结果是什么,用一个switch语句就可以加以区分顺便执行对应操作。

intent则是在B中调用setResult时传回的那个intent。









    
最新技术文章:
▪Android提高之MediaPlayer播放网络音频的实现方法... iis7站长之家
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3