unity prefab 嵌套可不可以嵌套android的view

Unity(206)
首先建一个unity工程,里面创建一个小球,然后写一个脚本test.cs,并将其挂到主摄像机上
将unity项目导出成Android工程
3 将上一步导出的eclipse工程导入到Eclipse中,然后添加一个布局文件main_panel.xml
最后,真机画面如下:
FR:徐海涛(hunk Xu)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:142027次
积分:6140
积分:6140
排名:第3395名
原创:450篇
评论:53条
(14)(31)(70)(40)(62)(62)(58)(44)(58)(23)10782人阅读
ANDROID(21)
转载请注明本文出自大苞米的博客(),谢谢支持!
效果展示:
开篇废话:
我现在所在的Team每周需要一个人给大家介绍一个知识点,或者新技术。这礼拜正好轮到我了,由于我工作才一年,面对那帮老鸟讲知识点感觉有点作死。所以我就准备选个新技术介绍一下。
由于我在大学里自学过一段时间Unity3D,所以我想介绍的技术就是它,但我现在做的是应用开发,不能做个小游戏去给大家演示。所以我想到比较简单,直观,而且有可能真正能用到的就是在Android应用中展示3D模型。比如在产品展示时直接把这个产品的3D模型展示出来而不是个图片,效果应该非常棒(OpenGL应该也可以做)。
思路定下以后就发现大学时学的Unity3D的内容基本忘光了,虽然偶尔有Unity3D的文章都会点开看看,但还是得重新学。记得当时学Unity3D的时候看过一个叫的博客。那时年轻,懵懂,找不到方向的我还给雨松大神发了一封邮件去请教大学应该怎么学习和做游戏相关的问题,结果人家没回,导致我更加失落于是接着学android去了。。。又扯远了。。。于是我又找到他的博客,把Unity3D基础部分的相关文章都看了一遍。
但是他博客里有介绍如何在Unity3D中调用Android,而我想做的是在Android中调用Unity3D,而且是把Unity3D嵌套在ANDROID的视图里面。最后费了九牛二虎之力才把这个Demo做出来。
准备工作:
下面是我总结的流程,目的是使本文思路更加清晰一些:
1.Android端代码可以在Eclipse中开发(AndroidStudio没有试,应该也可以)
2.Unity3D端代码要在Unity中开发
3.Android和Unity3D端,两边都需要加入一些代码从而可以使之关联交互。
4.将Android端代码编译成jar文件以插件形式放入到Unity端中
5.在Unity中将整个项目Build成apk文件,然后安装到手机或模拟器里运行
本文主要讲解1,2,3。对于4,5建议大家去看雨松MOMO的Unity博客的第17篇和第18篇。
UnityPlay:
在编写Android端和Unity3d端代码前,有必要先了解一下可以使两部分交互的类UnityPlay。
个人理解UnityPlay是个Unity提供给外部交互的一个接口类。
为什么是“个人理解”?这我不得不爆粗口了,TMD官网根本就没有相关的API和文档(如果大家有谁找到一定给我来一份,就当我骂自己了)。
热心的网友已经找到了:/Manual/PluginsForAndroid.html。。。。
在关联Android时,想拿到UnityPlay以及相关类的jar包可以从下面的地址找到:Unity安装路径\Editor\Data\PlaybackEngines\androidplayer\bin在bin文件夹下有一个classes.jar的jar文件,它就是我们想要的。
而在bin同目录下有一个src文件,点击到最后有3个类,分别是UnityPlayerActivity.java,UnityPlayerProxyActivity.java,UnityPlayerNativeActivity.java。前两个打开个后只有一行代码,说的是UnityPlayerActivity和UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity。而打开UnityPlayerNativeActivity中居然有代码,而且我估计这应该是UnityPlayerNativeActivity的源码。
由于关于UnityPlay的资料我只找到这么一个,所以我把UnityPlayerNativeActivity中的代码都贴出来,如果我注解有不对的地方希望大家指正。
* UnityPlayerActivity,UnityPlayerProxyActivity都继承自UnityPlayerNativeActivity
* 而UnityPlayerNativeActivity继承自NativeActivity
* 在该类里定义了一些和ANDROID生命周期相同的回调方法,留给自定义的Activity子类重写。
public class UnityPlayerNativeActivity extends NativeActivity
//UnityPlayer的引用,并且我们不能改变这个引用变量的名字,它被native code所引用
protected UnityPlayer mUnityP
protected void onCreate (Bundle savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
// 设置显示窗口参数
getWindow().takeSurface(null);
setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
getWindow().setFormat(PixelFormat.RGB_565);
// 创建一个UnityPlayer对象,并赋值给全局的引用变量
mUnityPlayer = new UnityPlayer(this);
//为UnityPlayer设置一些参数
if (mUnityPlayer.getSettings ().getBoolean (&hide_status_bar&, true))
getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
int glesMode = mUnityPlayer.getSettings().getInt(&gles_mode&, 1);
boolean trueColor8888 =
// UnityPlayer.init()方法需要在将view附加到layout之前调用。它将会调用native code
mUnityPlayer.init(glesMode, trueColor8888);
// 从UnityPlayer中获取到Unity的View视图
View playerView = mUnityPlayer.getView();
// 将Unity视图加载到根视图上
setContentView(playerView);
// 使Unity视图获取焦点
playerView.requestFocus();
protected void onDestroy ()
// 当Activity结束的时候调用UnityPlayer.quit()方法,它会卸载之前调用的native code
mUnityPlayer.quit();
super.onDestroy();
// 下面几个方法都是ANDROID相关回调方法,确保在ANDROID执行相应方法时UnityPlayer也需调用相应方法
protected void onPause()
super.onPause();
mUnityPlayer.pause();
protected void onResume()
super.onResume();
mUnityPlayer.resume();
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
public void onWindowFocusChanged(boolean hasFocus)
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
public boolean dispatchKeyEvent(KeyEvent event)
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);
return super.dispatchKeyEvent(event);
看完这个类后就知道了为什么在自定义的Activity中继承了UnityPlayerActivity等类以后,只要重写了onCreate并调用super.onCreate()方法后不需要任何其他的代码就会自动的显示出Unity3D的视图。因为初始化Unity视图的代码都在UnityPlayerNativeActivity父类中实现了。
ANDROID端代码:
在写ANDROID代码的时候,一定要导入Unity3D提供给我们的jar包,jar包的位置我在上面说了。引入jar包加入到buildpath中这些最基本的我就不多说了。
要想和Unity交互,我们就不能继承ANDROID提供给我们的Activity,我们需要继承刚才jar包中引入的Unity提供的Activity类,一共有这么3个:
UnityPlayerActivity,UnityPlayerProxyActivity,UnityPlayerNativeActivity。具体区别不知道,因为没有文档,没有API,没有源码(这里再次鄙视一下)。刚才我们看过UnityPlayerNativeActivity的代码(虽然很短,但我觉得这个就是源码),知道UnityPlayerActivity,UnityPlayerProxyActivity都是它的子类,而且最终父类为NativeActivity。所以我们继承Unity提供的最外层的子类是最好的选择,我这里选择的是UnityPlayerActivity,因为名字最简单,觉得该封装的都应该封装好了。
public class MainActivity extends UnityPlayerActivity {
private Button topB
private Button bottomB
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置test为我们的根布局
setContentView(R.layout.test);
// 通过刚才的源码分析,知道mUnityPlayer为一个全局的引用变量,而且已经在父类中设置好了,所以直接拿来用就可以了
View playerView = mUnityPlayer.getView();
// 将Unity的视图添加到我们为其准备的父容器中
LinearLayout ll = (LinearLayout) findViewById(R.id.unityViewLyaout);
ll.addView(playerView);
// 上面的button设置监听器
topButton = (Button) findViewById(R.id.topButton);
topButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//发送消息给Unity端,该函数第一个参数为接受消息的类对象,第二个该类对象用接受消息的方法,第三个参数为传递的消息
//所以下面的意思就为:调用Main Camera下面的Previous方法,传送的消息为空
UnityPlayer.UnitySendMessage(&Main Camera&,&Previous&,&&);
// 为下面的button设置监听器
bottomButton = (Button) findViewById(R.id.bottomBtn);
bottomButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//调用Main Camera下面的Next方法,传送的消息为空
UnityPlayer.UnitySendMessage(&Main Camera&,&Next&,&&);
最后看一下Android端的布局文件,布局很简单,上下各有一个button按钮,两个按钮中间是Unity的视图。
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical& &
android:id=&@+id/topButton&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:layout_alignParentTop=&true&
android:text=&PREVIOUS& /&
&LinearLayout
android:id=&@+id/unityViewLyaout&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:layout_above=&@+id/bottomBtn&
android:layout_below=&@+id/topButton&
android:orientation=&horizontal& &
&/LinearLayout&
android:id=&@+id/bottomBtn&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:layout_alignParentBottom=&true&
android:text=&NEXT& /&
&/RelativeLayout&Android端的代码就介绍完了,很简单。唯一的难点就是UnityPlayerActivity和UnityPlayer的使用,就这两个破玩意花了我好几天的时间,很简单的东西不知道为什么官方不给个文档或者API(也可能我太挫没找到。。。)
Unity3D端代码:
先看一下我的项目结构:
JavaScript存放的是脚本
Models存放的是我在Assert Store中下载的免费的一些模型文件
Plugins下是我的Android工程,具体做法参考网上教程(这里推荐雨松大神的第17篇)
Prefab我是调整模型后定义的预制体
在场景中,我只有一个摄像机,和一个直射光。将脚本绑定到摄像机上,然后将之前调整好的5个预设模型添加到脚本的相应对象中。
下面是脚本的代码,关于模型的旋转缩放是直接用了雨松MOMO的一篇文章中的代码,然后再加上了本例中的一些逻辑而组成的。
#pragma strict
//5个模型,从外部传入
var car : GameO
var helicopter : GameO
var suv : GameO
var plane : GameO
var tank : GameO
//模型数组下标
private var index :
//模型数组
private var models : GameObject[];
//当前模型对象
private var mCurrentGameObject : GameO
/******************************************/
/*分割线之下的变量用于触摸手势镜头控制旋转和缩放*/
/******************************************/
//缩放系数
var distance = 10.0;
//左右滑动移动速度
var xSpeed = 250.0;
var ySpeed = 120.0;
//缩放限制系数
var yMinLimit = -20;
var yMaxLimit = 80;
//摄像头的位置
var x = 0.0;
var y = 0.0;
//记录上一次手机触摸位置判断用户是在左放大还是缩小手势
private var oldPosition1 : Vector2;
private var oldPosition2 : Vector2;
function Start () {
//初始化模型数组
index = 0;
models = new GameObject[5];
models[0] =
models[1] =
models[2] =
models[3] =
models[4] =
//克隆一个初始模型对象
mCurrentGameObject = Instantiate(models[index], Vector3(0,0,0), Quaternion.Euler(-20,0,0));
//初始化镜头参数
var angles = transform.eulerA
x = angles.y;
y = angles.x;
function Update () {
//判断触摸数量为单点触摸
if(Input.touchCount == 1)
//触摸类型为移动触摸
if(Input.GetTouch(0).phase==TouchPhase.Moved)
//根据触摸点计算X与Y位置
x += Input.GetAxis(&Mouse X&) * xSpeed * 0.02;
y -= Input.GetAxis(&Mouse Y&) * ySpeed * 0.02;
//判断触摸数量为多点触摸
if(Input.touchCount & 1 )
//前两只手指触摸类型都为移动触摸
if(Input.GetTouch(0).phase==TouchPhase.Moved||Input.GetTouch(1).phase==TouchPhase.Moved)
//计算出当前两点触摸点的位置
var tempPosition1 = Input.GetTouch(0).
var tempPosition2 = Input.GetTouch(1).
//函数返回真为放大,返回假为缩小
if(isEnlarge(oldPosition1,oldPosition2,tempPosition1,tempPosition2))
//放大系数超过3以后不允许继续放大
//这里的数据是根据我项目中的模型而调节的,大家可以自己任意修改
if(distance & 3)
distance -= 0.5;
//缩小洗漱返回18.5后不允许继续缩小
//这里的数据是根据我项目中的模型而调节的,大家可以自己任意修改
if(distance & 18.5)
distance += 0.5;
//备份上一次触摸点的位置,用于对比
oldPosition1=tempPosition1;
oldPosition2=tempPosition2;
//函数返回真为放大,返回假为缩小
function isEnlarge(oP1 : Vector2,oP2 : Vector2,nP1 : Vector2,nP2 : Vector2) : boolean
//函数传入上一次触摸两点的位置与本次触摸两点的位置计算出用户的手势
var leng1 =Mathf.Sqrt((oP1.x-oP2.x)*(oP1.x-oP2.x)+(oP1.y-oP2.y)*(oP1.y-oP2.y));
var leng2 =Mathf.Sqrt((nP1.x-nP2.x)*(nP1.x-nP2.x)+(nP1.y-nP2.y)*(nP1.y-nP2.y));
if(leng1 & leng2)
//放大手势
//缩小手势
//Update方法一旦调用结束以后进入这里算出重置摄像机的位置
function LateUpdate () {
//mCurrentGameObject为我们当前模型对象,缩放旋转的参照物
if (mCurrentGameObject.transform) {
//重置摄像机的位置
y = ClampAngle(y, yMinLimit, yMaxLimit);
var rotation = Quaternion.Euler(y, x, 0);
var position = rotation * Vector3(0.0, 0.0, -distance) + mCurrentGameObject.transform.
transform.rotation =
transform.position =
static function ClampAngle (angle : float, min : float, max : float) {
if (angle & -360)
angle += 360;
if (angle & 360)
angle -= 360;
return Mathf.Clamp (angle, min, max);
// 当android中按下next,显示下一个模型
function Next () {
index = index+1;
if (index & models.Length-1) {
index = 0;
Debug.Log(&next&);
// 摧毁当前对象
Destroy(mCurrentGameObject);
// 建立新的模型对象
mCurrentGameObject = Instantiate(models[index]);
// 当android中按下previous,显示上一个模型
function Previous () {
index = index-1;
if (index & 0) {
index = models.Length-1;
Debug.Log(&previous&);
// 摧毁当前对象
Destroy(mCurrentGameObject);
// 建立新的模型对象
mCurrentGameObject = Instantiate(models[index]);
最后就是在Unity3D中将工程Build成APK文件,然后再手机或模拟器中运行(如果手机或模拟器连着Eclipse则可以打出log方便调试找错)。
最后附上代码Demo:
Unity端代码太大了,所以我就把Android端和Unity端代码还有而apk文件上传到百度云了。
我在刚上大学的时候就梦想着毕业以后去做游戏,但是报志愿的时候选的是java相关,后来才知道java并不适合做游戏,后来自学c++,openGL,再后来又看Unity3D但全都没有坚持下来,而且大学时候天天和同学打wow,结果毕业发现其实游戏相关的东西根本等于一点也没学会,而且大连没有游戏开发的工作,虽然很想去北京试试,但是当时去北京实习太麻烦,而且不一定能找到,所以就在大连直接找了一个Android开发就这么把当初的梦想放弃了。但是我还是想明年去北京试试能不能找到游戏开发的工作,这中间一年我还是会主要学习Android和Java,剩余时间看看图形学和数学知识,不会像大学的时候看到什么热就学什么,因为现在懂得渐渐多了后发现编程基本都是通用的,所以还是先把一个东西学透学明白吧。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:438949次
积分:5115
积分:5115
排名:第4541名
原创:54篇
评论:655条
(1)(2)(3)(1)(1)(1)(1)(1)(4)(3)(1)(4)(2)(3)(6)(1)(4)(4)(4)(6)(2)移动开发(49)
首先创建一个android工程,这个很简单就不详细说明了。然后打开Unity的安装目录,找到需要用的class.jar文件,就是封装调用unity引擎的java源码,位置在Unity\Editor\Data\PlaybackEngines\androidplayer\bin\classes.jar(安装目录),然后复制这个文件到android工程的libs目录,系统会自动引用,adt22以下不记得会不会,如果不会的话需要自己设置一下,右键工程
添加这个文件即可。
然后把MainAtivity稍微改一下,就是把继承父类改成UnityPlayerActivity,这样就对接上了unity接口,源码如下:
123456789101112131415161718package com.lee.unityandroid;&import android.os.Bundle;import android.widget.RelativeLayout;&import com.unity3d.player.UnityPlayerActivity;&public class MainActivity extends UnityPlayerActivity {& @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.parent_layout);
layout.addView(mUnityPlayer.getView()); }&}为了显明观察显示,布局稍微改动了一下。把这个显示在我们的视图上。activity_main.xml
&RelativeLayout
xmlns:android=&/apk/res/android&
&&&&xmlns:tools=&/tools&
&&&&android:layout_width=&match_parent&
&&&&android:layout_height=&match_parent&
&&&&tools:context=&.MainActivity&
&&&&&RelativeLayout
&&&&&&&&android:id=&@+id/parent_layout&
&&&&&&&&android:layout_width=&300dp&
&&&&&&&&android:layout_height=&500dp&
&&&&&&&&android:layout_centerInParent=&true&
&&&&&/RelativeLayout&
&/RelativeLayout&
配置清单文件,这个里面的包名要用到后面Unity的
123456789101112131415161718192021222324252627&?xml version=&1.0& encoding=&utf-8&?&&manifest xmlns:android=&/apk/res/android&&&&&package=&com.lee.unityandroid&&&&&android:versionCode=&1&&&&&android:versionName=&1.0& &&&&&&&uses-sdk&&&&&&&&android:minSdkVersion=&10&&&&&&&&&android:targetSdkVersion=&14& /&&&&&&&application&&&&&&&&android:allowBackup=&true&&&&&&&&&android:icon=&@drawable/ic_launcher&&&&&&&&&android:label=&@string/app_name&&&&&&&&&android:theme=&@style/AppTheme& &&&&&&&&&&activity&&&&&&&&&&&&android:name=&com.lee.unityandroid.MainActivity&&&&&&&&&&&&&android:label=&@string/app_name& &&&&&&&&&&&&&&intent-filter&&&&&&&&&&&&&&&&&&action android:name=&android.intent.action.MAIN& /&&&&&&&&&&&&&&&&&&&category android:name=&android.intent.category.LAUNCHER& /&&&&&&&&&&&&&&/intent-filter&&&&&&&&&&/activity&&&&&&/application&&&/manifest&android基本上就完成了。现在创建一个Unity工程,名字啥的随便取,然后在菜单File-&Build Settings-&Android-&Player Settings最后生成的APK文件我们直接解压,把里面的assets目录下面的data目录复制到我们工程的assets目录下,然后把lib目录下的armeabi-v7a或armeabi一起复制(如果都有的话,只有其中一个就复制一个即可),最后编译我们的程序,运行效果如下:白色是我们的布局容器,蓝色就是unity视图内容了。下面继续说下在Unity中调用Andriod的函数,在Unity工程中创建一个C#脚本,直接将它绑定在摄像机中,它用来通知界面打开Activity。如下图所示,利用GUI在屏幕中创建两个按钮,点击按钮打开不同的Activity。
UnityEngine;
System.Collections;
MonoBehaviour
Update is called once per frame
//当用户按下手机的返回键或home键退出游戏
(Input.GetKeyDown(KeyCode.Escape)
Input.GetKeyDown(KeyCode.Home)
Application.Quit();
if(GUILayout.Button(&OPEN
Activity01&,GUILayout.Height(100)))
AndroidJavaClass
AndroidJavaClass(&com.unity3d.player.UnityPlayer&);
AndroidJavaObject
jc.GetStatic&AndroidJavaObject&(&currentActivity&);
jo.Call(&Method01&,&第一个方法&);
if(GUILayout.Button(&OPEN
Activity02&,GUILayout.Height(100)))
AndroidJavaClass
AndroidJavaClass(&com.unity3d.player.UnityPlayer&);
AndroidJavaObject
jc.GetStatic&AndroidJavaObject&(&currentActivity&);
jo.Call(&Method02&,&第二个方法&);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12858次
排名:千里之外
原创:30篇
转载:20篇
(2)(1)(1)(1)(4)(23)(5)(14)ScrollView+Fragment+ListView嵌套ListView,麻麻再也不用担心我不会写嵌套
之前写了一篇文章
android ListView/GridView与ScrollView嵌套的滑动冲突解决
介绍了如何解决ScrollView与AdapterView的嵌套,但是没有给出demo,那是因为那些代码比较多,而且是在手头的项目里,业务逻辑代码比较多,所以第一时间没有分享给大家。
今天终于有空把这些代码全部抽离了出来,并且去掉了业务代码和不必要的内容,以便大家能够更好的学习这个知识。
先贴一个效果图吧:
之前项目里我是使用复写ScrollView的onInterceptTouchEvent方法来接管滑动事件的,而有小伙伴@liu告诉我可以使用vcD4NCjxwcmUgY2xhc3M9"brush:">
android:focusable=true
android:focusableInTouchMode=true
来设置ScrollView接管事件。于是本Demo就使用了这个方法,结果与前一种方法效果上没有发现区别。
ListView嵌套
前一篇文章只写了滑动冲突解决的问题,本文也不再多赘述了,而ListView与ListView的嵌套里面还有其他的一些极易出错之处。
其中ListView中数据混乱(不是指图片)的问题应该来说是最重要也是比较烦人的bug
我的第一层ListView 的Adapter:
public class QuestionCLAdapter extends MyBaseAdapter {
//将下级Adapter放到上级Adapter中维护起来,防止new多个Adapter导致数据错乱
private HashMap ads = new HashMap();
public QuestionCLAdapter(Context context) {
super(context);
// TODO Auto-generated constructor stub
public void setItems(List itemList) {
// TODO Auto-generated method stub
super.setItems(itemList);
for (int i = 0; i & itemList.size(); i++) {
ads.put(i,new QuestionCLOptionAdapter(context,itemList.get(i)));
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder =
if(convertView == null){
convertView = inflater.inflate(R.layout.item_error_question_detail_c, null);
holder = new ViewHolder();
holder.ansysLayout = (LinearLayout) convertView.findViewById(R.id.layout_question_ansys);
holder.questionTitleNum = (TextView) convertView.findViewById(R.id.tv_error_questioncl_titlenum);
holder.questionclTxt = (TextView) convertView.findViewById(R.id.tv_error_questioncl_text);
holder.questionRightTxt = (TextView) convertView.findViewById(R.id.tv_question_rightTxt);
holder.questionansysTxt = (TextView) convertView.findViewById(R.id.txt_question_ansys);
holder.questionclOptionsLv = (ListView) convertView.findViewById(R.id.lv_error_detail_c_option);
convertView.setTag(holder);
holder = (ViewHolder)convertView.getTag();
final QuestionCL item = itemList.get(position);
//初始化界面与监听器......
if (item.isSubmit()) {
holder.ansysLayout.setVisibility(View.VISIBLE);
int temp = 65;
for (int i = 0; i & item.getItems().size(); i++) {
if (item.getItems().get(i).getIsTrue() == 1) {
holder.questionRightTxt.setText((char)temp +);
Log.i(TAG, (char)temp +);
if (null != item.getAnalysis()) {
holder.questionansysTxt.setText(Html.fromHtml(item.getAnalysis()));
holder.ansysLayout.setVisibility(View.GONE);
holder.questionTitleNum.setText(item.getQustionid());
holder.questionclTxt.setText(Html.fromHtml(item.getQustiontext()));
if (null != ads.get(position)) {
holder.questionclOptionsLv.setAdapter(ads.get(position));
return convertV
public class ViewHolder{
LinearLayout ansysL
TextView questionTitleN
TextView questionRightT
TextView questionansysT
TextView questionclT
ListView questionclOptionsLv;
应该来说是一个很经典很常规的自定义Adapter实现吧,继承的是自定义的虚基类。
可以看到我用一个容器作为类变量去管理其下级Adapter,在每次getView的时候都确保用的是它自己的数据而不是 重新new一个Adapter出来。
public abstract class MyBaseAdapter extends BaseAdapter {
protected C
protected String TAG =
protected LayoutI
protected List itemList = new ArrayList();
public MyBaseAdapter(Context context) {
this.context =
inflater = LayoutInflater.from(context);
TAG = this.getClass().getName();
* 判断数据是否为空
* @return 为空返回true,不为空返回false
public boolean isEmpty() {
return itemList.isEmpty();
* 在原有的数据上添加新数据
* @param itemList
public void addItems(List itemList) {
this.itemList.addAll(itemList);
notifyDataSetChanged();
* 设置为新的数据,旧数据会被清空
* @param itemList
public void setItems(List itemList) {
this.itemList.clear();
this.itemList = itemL
notifyDataSetChanged();
* 清空数据
public void clearItems() {
itemList.clear();
notifyDataSetChanged();
public int getCount() {
return itemList.size();
public Object getItem(int position) {
return itemList.get(position);
public long getItemId(int position) {
abstract public View getView(int position, View view, ViewGroup viewGroup);
下级Adapter:
public class QuestionCLOptionAdapter extends MyBaseAdapter {
/** 当前被选中的位置 -1表示未作答 **/
/** 答案是否已提交
private boolean isS
private QuestionCL parentI
/** -1未作答,0答错,1答对
private int isrightA
public QuestionCLOptionAdapter(Context context) {
super(context);
selected = -1;
isSubmmit =
isrightAnswered = -1;
public QuestionCLOptionAdapter(Context context,QuestionCL parentItem) {
super(context);
selected = -1;
isSubmmit = parentItem.isSubmit();
this.parentItem = parentI
this.setItems(parentItem.getItems());
isrightAnswered = -1;
public View getView(final int position, View convertView, final ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder =
if(convertView == null){
convertView = inflater.inflate(R.layout.item_list_error_question_option, null);
holder = new ViewHolder();
holder.rightImg = (ImageView) convertView.findViewById(R.id.img_question_option_true);
holder.wrongImg = (ImageView) convertView.findViewById(R.id.img_question_option_false);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.cb_question_option_select);
holder.layout = (LinearLayout) convertView.findViewById(R.id.layout_question_option);
holder.optionTitle = (TextView) convertView.findViewById(R.id.tv_question_option_title);
holder.optionTxt = (TextView) convertView.findViewById(R.id.tv_question_option_text);
convertView.setTag(holder);
holder = (ViewHolder)convertView.getTag();
final QuestionOptionInfo item = itemList.get(position);
//初始化界面与监听器......
holder.checkBox.setVisibility(View.VISIBLE);
int num = item.getOptionId()+65;
holder.optionTitle.setText((char)num+.);
holder.optionTxt.setText(Html.fromHtml(item.getOptionText()));
holder.layout.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if (isSubmmit) {
if (position == selected) {
selected = -1;
selected =
isSubmmit =
if (null != parentItem && !parentItem.isSubmit() && isSubmmit) {
parentItem.setSubmit(true);
QuestionCLOptionAdapter.this.notifyDataSetChanged();
if (position == selected) {
holder.checkBox.setChecked(true);
holder.checkBox.setChecked(false);
//判断是否答对
if (isSubmmit) {
if (position == selected && item.getIsTrue() == 1) {
holder.rightImg.setVisibility(View.VISIBLE);
Log.i(TAG, true!!!!!!!!!!!!!!!!);
} else if (position == selected) {
holder.wrongImg.setVisibility(View.VISIBLE);
Log.i(TAG, false!!!!!!!!!!!!!!!);
holder.rightImg.setVisibility(View.GONE);
holder.wrongImg.setVisibility(View.GONE);
return convertV
/** -1未作答,0答错,1答对
* @return the isrightAnswered
public int getIsrightAnswered() {
if (isSubmmit) {
return isrightA
return -1;
/**-1未作答,0答错,1答对
* @param isrightAnswered the isrightAnswered to set
public void setIsrightAnswered(int isrightAnswered) {
if (isSubmmit) {
this.isrightAnswered = isrightA
public class ViewHolder{
CheckBox checkB
ImageView rightI
ImageView wrongI
TextView optionT
TextView optionT
两个Adapter之间 你可以用类变量进行数据交互,可以通过bean的某一个值进行交互判断。在这里我都有用到。
public class MainActivity extends FragmentActivity {
private ScrollV
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv = (ScrollView) findViewById(R.id.sv_main);
setFragment(new QuestionFragment(),initData());
//显示在顶端
sv.smoothScrollTo(0,0);
private QuestionC initData(){
// 生成测试数据
QuestionC questionC = new QuestionC();
//塞大题题干等信息
questionC.setMaintext(从前有座山,山里有座庙,庙里有个老和尚在讲故事。);
List cList = new ArrayList();
for (int i = 1; i & 3; i++) {
QuestionCL cltemp = new QuestionCL();
//塞小题题干等信息
cltemp.setQustionid(i+);
cltemp.setQustiontext(老和尚+i+是谁?);
cltemp.setRightitem(释永信+i+i);
List optionList = new ArrayList();
for (int j = 1; j & 6; j++) {
QuestionOptionInfo otemp = new QuestionOptionInfo();
//塞选项Id,String等
otemp.setOptionId(j-1);
otemp.setOptionText(释永信+i+j);
if (otemp.getOptionText().equals(cltemp.getRightitem())) {
otemp.setIsTrue(1);
otemp.setIsTrue(0);
optionList.add(otemp);
cltemp.setItems(optionList);
cList.add(cltemp);
questionC.setQuestioncls((ArrayList) cList);
return questionC;
private void setFragment(Fragment fragment,QuestionC question) {
FragmentManager fragManager = getSupportFragmentManager();
FragmentTransaction transaction = fragManager.beginTransaction();
bundle = new Bundle();
bundle.putSerializable(bean, question);
fragment.setArguments(bundle);
transaction.replace(R.id.layout_fragment, fragment);
if (!MainActivity.this.isFinishing()) {
mitAllowingStateLoss();
public class QuestionFragment extends Fragment{
private QuestionC questionC;
/** 大题干文本
private TextView questionT
/** 小题ListView
private ListView xiaotiLv;
private QuestionCLA
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
context = getActivity();
return inflater.inflate(R.layout.fragment_error_detail_c, container,false);
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initWidget();
initData();
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
getIntentData();
protected void getIntentData() {
//取得Bean等信息
if (null != getArguments()) {
questionC = (QuestionC) getArguments().get(bean);
protected void initData() {
ad = new QuestionCLAdapter(context);
if (null == questionC) {
Log.i(questionC, no data!!!);
ad.setItems(questionC.getQuestioncls());
xiaotiLv.setAdapter(ad);
questionTxt.setText(Html.fromHtml(questionC.getMaintext()));
protected void initWidget() {
questionTxt = (TextView) getView().findViewById(R.id.tv_error_question_txt);
xiaotiLv = (ListView) getView().findViewById(R.id.lv_error_detail_c_secondary_question);
补上activity的布局
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'}

我要回帖

更多关于 unity collider 嵌套 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信