android层级
Ⅰ 听说苹果比安卓快是因为响应层级不同。那请问安卓的响应层级顺序是什么
是的,楼主你说的没错。Android系统的优先级响应层级则是Application--Framework--Library--Kernal架构。相比起苹果第三道第三层才能到屏幕上反应,所以在流畅度上苹果确实胜过安卓
Ⅱ android打造任意层级的树形控件那个id能不能用string
由于整体比较长,我决定首先带大家看一下用法,就是如果学完了这篇博客,我们需要树形控件,我们需要花多少精力去完成~~
现在需求来了:我现在需要展示一个文件管理系统的树形结构:
数据是这样的:
//id , pid , label , 其他属性
mDatas.add(new FileBean(1, 0, "文件管理系统"));
mDatas.add(new FileBean(2, 1, "游戏"));
mDatas.add(new FileBean(3, 1, "文档"));
mDatas.add(new FileBean(4, 1, "程序"));
mDatas.add(new FileBean(5, 2, "war3"));
mDatas.add(new FileBean(6, 2, "刀塔传奇"));
mDatas.add(new FileBean(7, 4, "面向对象"));
mDatas.add(new FileBean(8, 4, "非面向对象"));
mDatas.add(new FileBean(9, 7, "C++"));
mDatas.add(new FileBean(10, 7, "java"));
mDatas.add(new FileBean(11, 7, "Javascript"));
mDatas.add(new FileBean(12, 8, "C"));
当然了,bean可以有很多属性,我们提供你动态的设置树节点上的显示、以及不约束id, pid 的命名,你可以起任意丧心病狂的属性名称;
那么我们如何确定呢?
看下Bean:
package com.zhy.bean;
import com.zhy.tree.bean.TreeNodeId;
import com.zhy.tree.bean.TreeNodeLabel;
import com.zhy.tree.bean.TreeNodePid;
public class FileBean
{
@TreeNodeId
private int _id;
@TreeNodePid
private int parentId;
@TreeNodeLabel
private String name;
private long length;
private String desc;
public FileBean(int _id, int parentId, String name)
{
super();
this._id = _id;
this.parentId = parentId;
this.name = name;
}
}
现在,不用说,应该也知道我们通过注解来确定的。
下面看我们如何将这数据转化为树
布局文件就一个listview,就补贴了,直接看Activity
package com.zhy.tree_view;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import com.zhy.bean.FileBean;
import com.zhy.tree.bean.TreeListViewAdapter;
public class MainActivity extends Activity
{
private List<FileBean> mDatas = new ArrayList<FileBean>();
private ListView mTree;
private TreeListViewAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initDatas();
mTree = (ListView) findViewById(R.id.id_tree);
try
{
mAdapter = new SimpleTreeAdapter<FileBean>(mTree, this, mDatas, 10);
mTree.setAdapter(mAdapter);
} catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
private void initDatas()
{
// id , pid , label , 其他属性
mDatas.add(new FileBean(1, 0, "文件管理系统"));
mDatas.add(new FileBean(2, 1, "游戏"));
mDatas.add(new FileBean(3, 1, "文档"));
mDatas.add(new FileBean(4, 1, "程序"));
mDatas.add(new FileBean(5, 2, "war3"));
mDatas.add(new FileBean(6, 2, "刀塔传奇"));
mDatas.add(new FileBean(7, 4, "面向对象"));
mDatas.add(new FileBean(8, 4, "非面向对象"));
mDatas.add(new FileBean(9, 7, "C++"));
mDatas.add(new FileBean(10, 7, "JAVA"));
mDatas.add(new FileBean(11, 7, "Javascript"));
mDatas.add(new FileBean(12, 8, "C"));
}
}
Activity里面并没有什么特殊的代码,拿到listview,传入mData,当中初始化了一个Adapter;
看来我们的核心代码都在我们的Adapter里面:
那么看一眼我们的Adapter
package com.zhy.tree_view;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.zhy.tree.bean.Node;
import com.zhy.tree.bean.TreeListViewAdapter;
public class SimpleTreeAdapter<T> extends TreeListViewAdapter<T>
{
public SimpleTreeAdapter(ListView mTree, Context context, List<T> datas,
int defaultExpandLevel) throws IllegalArgumentException,
IllegalAccessException
{
super(mTree, context, datas, defaultExpandLevel);
}
@Override
public View getConvertView(Node node , int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder = null;
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.list_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.icon = (ImageView) convertView
.findViewById(R.id.id_treenode_icon);
viewHolder.label = (TextView) convertView
.findViewById(R.id.id_treenode_label);
convertView.setTag(viewHolder);
} else
{
viewHolder = (ViewHolder) convertView.getTag();
}
if (node.getIcon() == -1)
{
viewHolder.icon.setVisibility(View.INVISIBLE);
} else
{
viewHolder.icon.setVisibility(View.VISIBLE);
viewHolder.icon.setImageResource(node.getIcon());
}
viewHolder.label.setText(node.getName());
return convertView;
}
private final class ViewHolder
{
ImageView icon;
TextView label;
}
}
我们的SimpleTreeAdapter继承了我们的TreeListViewAdapter ; 除此之外,代码上只需要复写getConvertView , 且getConvetView其实和我们平时的getView写法一致;
公布出getConvertView 的目的是,让用户自己去决定Item的展示效果。其他的代码,我已经打包成jar了,用的时候导入即可。这样就完成了我们的树形控件。
也就是说用我们的树形控件,只需要将传统继承BaseAdapter改为我们的TreeListViewAdapter ,然后去实现getConvertView 就好了。
Ⅲ Android 在java层里有没有办法控制多个SurfaceView之间的层级关系
完整答案,需要点儿耐心看哦。
有不少朋友都遇到过这种问题,程序执行时切换到后台,然后再重新进入会报异常,本文就这种问题全面讲解下SurfaceView的运行机制,了解了这些原理你就能自己解决这些问题了。
我们通常会通过单击HOME按键或返回按键等操作切换到后台,之后可能会再次进入程序,这个时候就有可能报异常。这里SurfaceView可能报的异常主要有两点,如下:
一、提交画布异常。如下图(模拟器错误提示,以及Logcat Detail)
Java代码
public void draw() {
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bmp, bmp_x, bmp_y, paint);
}
} catch (Exception e) {
Log.v("Himi", "draw is Error!");
} finally {//备注1
if (canvas != null)//备注2
sfh.unlockCanvasAndPost(canvas);
}
}
先看备注1这里,之前的文章中我给大家解释过为什么要把 sfh.unlockCanvasAndPost(canvas); 写在finally中,主要是为了保证能正常的提交画布。
今天主要说说备注2,这里一定要判定下canvas是否为空,因为当程序切入后台的时候,canvas是获取不到的!那么canvas一旦为空,提交画布这里就会出现参数异常的错误!
二、线程启动异常。如下图(模拟器错误提示,以及Logcat Detail)
这种异常只是在当你程序运行期间点击Home按钮后再次进入程序的时候报的异常,异常说咱们的线程已经启动!为什么返回按钮就没事?
OK,下面我们就要来先详细讲解一下Android中Back和Home按键的机制!然后分析问题,并且解决问题!
先看下面MySurfaceViewAnimation.java的类中的代码:
Java代码
public class MySurfaceViewAnimation extends SurfaceView implements Callback, Runnable {
private Thread th;
private SurfaceHolder sfh;
private Canvas canvas;
private Paint paint;
private Bitmap bmp;
private int bmp_x, bmp_y;
public MySurfaceViewAnimation(Context context) {
super(context);
this.setKeepScreenOn(true);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.himi_dream);
sfh = this.getHolder();
sfh.addCallback(this);
paint = new Paint();
paint.setAntiAlias(true);
this.setLongClickable(true);
th = new Thread(this, "himi_Thread_one");
Log.e("Himi", "MySurfaceViewAnimation");
}
public void surfaceCreated(SurfaceHolder holder) {
th.start();
Log.e("Himi", "surfaceCreated");
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e("Himi", "surfaceChanged");
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e("Himi", "surfaceDestroyed");
}
public void draw() {
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bmp, bmp_x, bmp_y, paint);
}
} catch (Exception e) {
Log.v("Himi", "draw is Error!");
} finally {//备注1
if (canvas != null)//备注2
sfh.unlockCanvasAndPost(canvas);
}
}
public void run() {
while (true) {
draw();
try {
Thread.sleep(100);
} catch (Exception ex) {
}
}
}
}
以上是我们常用的自定义SurfaceView,并且使用Runnable接口老框架了不多说了,其中我在本类的构造、创建、状态改变、消亡函数都加上打印!
OK,下面看第一张图:(刚运行程序)
上图的左边部分是Dubug。这里显示我们有一条线程在运行,名字叫”himi_Thread_one”。
上图的右边部分是LogCat日志。大家很清晰的看到,当第一次进入程序的时候,会先进入view构造函数、然后是创建view,然后是view状态改变,OK,这个大家都知道!
下面是我来点击Home(手机上的小房子)按键,这时程序处于后台,然后重新进入程序的过程!
上图可以看出我们的线程还是一条,这里主要观察从点击home到再次进入程序的过程,如下所述:
点击home 调用了view销毁,然后进入程序会先进入view创建,最后是view状态改变。
上面的过程很容易理解,重要的角色上场了~Back 按钮!点我点击Back按钮看看发生了什么!
先看左边的Debug一栏,多了一条线程! 看LogCat发现比点击Home按键多调用了一次构造函数!
好了,从我们测试的程序来看,无疑,点击Home 和 点击 Back按钮再次进入程序的时候,步骤是不一样的,线程数量也变了!
那么这里就能解释为什么我们点击Back按钮不异常,点击Home会异常了!
原因:因为点击Back按钮再次进入程序的时候先进入的是view构造函数里,那么就是说这里又new了一个线程出来,并启动!那么而我们点击Home却不一样了,因为点击home之后再次进入程序不会进入构造函数,而是直接进入了view创建这个函数,而在view创建这个函数中我们有个启动线程的操作,其实第一次启动程序的线程还在运行,so~这里就一定异常了,说线程已经启动!
有些童鞋会问,我们为何不把th = new Thread(this, “himi_Thread_one”);放在view创建函数中不就好了?!
没错,可以!但是当你反复几次之后你发现你的程序中会多出很多条进程!(如下图)
虽然可以避免出现线程已经启动的异常,很明显这不是我们想要的结果!
那么下面给大家介绍最合适的解决方案:
修改MySurfaceViewAnimation.java:
Java代码
public class MySurfaceViewAnimation extends SurfaceView implements Callback, Runnable {
private Thread th;
private SurfaceHolder sfh;
private Canvas canvas;
private Paint paint;
private Bitmap bmp;
private int bmp_x, bmp_y;
private boolean himi; //备注1
public MySurfaceViewAnimation(Context context) {
super(context);
this.setKeepScreenOn(true);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.himi_dream);
sfh = this.getHolder();
sfh.addCallback(this);
paint = new Paint();
paint.setAntiAlias(true);
this.setLongClickable(true);
Log.e("Himi", "MySurfaceViewAnimation");
}
public void surfaceCreated(SurfaceHolder holder) {
himi = true;
th = new Thread(this, "himi_Thread_one");//备注2
th.start();
Log.e("Himi", "surfaceCreated");
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e("Himi", "surfaceChanged");
}
public void surfaceDestroyed(SurfaceHolder holder) {
himi = false;//备注3
Log.e("Himi", "surfaceDestroyed");
}
public void draw() {
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bmp, bmp_x, bmp_y, paint);
}
} catch (Exception e) {
Log.v("Himi", "draw is Error!");
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas);
}
}
public void run() {
while (himi) {//备注4
draw();
try {
Thread.sleep(100);
} catch (Exception ex) {
}
}
}
}
这里修改的地方有以下几点:
1、我们都知道一个线程启动后,只要run方法执行结束,线程就销毁了,所以我增加了一个布尔值的成员变量 himi(备注1),这里可以控制我们的线程消亡的一个开关!(备注4)
2、在启动线程之前,设置这个布尔值为ture,让线程一直运行。
3、在view销毁时,设置这个布尔值为false,销毁当前线程!(备注3)
OK,这里图和解释够详细了,希望大家以后真正开发一款游戏的时候,一定要严谨代码,不要留有后患哈~
Ⅳ android 怎么计算一个view的嵌套层级
层级关系的布局有两种解决方法:
一种方法是使用标签的自然顺序和嵌套顺序来形成合理的布局。
而第一种方法却不是万能的,有时候我们需要将原本位于下层的元素移到另一个元素上方,那可以使用z-index;
而你说的不好用,则是zindex没有生效,没生效就是没有定义position属性,如果不想让元素的位置有所变化,就给赋予z-index属性的元素加上相对定位的position:relative;
Ⅳ android如何动态改变控件的层级(叠放层次)
在左边图的基础上增加如右图控件b的控件c,然后控制控件c的显示与隐藏
Ⅵ Android系统分成哪4个层次:
对的 你理解的是对的啊,这是android开发的四个层次
Ⅶ 安卓开发:如何设置控件叠放的层次
只需要在布局文件中调整代码位置,你想把什么放界面的最上面就把代码放在xml文件的最下面,这样的顺序。
Ⅷ android应用界面中ui组件间有严格的层次关系,有哪两种类型的视图
不明白,安卓常用的布局方式有相对布局,线性布局,绝对布局和表格布局等,其中绝对布局和相对布局后添加的组件可把先添加的组件覆盖掉,不知道是不是题主需要的。
Ⅸ android 现在很火 ,但我不知道android定位在什么层次的,
从入门到低端再到中端甚至高端都有涉及
软件都是涉及硬件的......
专业性很强
做网站看你做什么网站了(这方面本人小白 毕竟您把问题放到了手机购买这个分类里.....)
Ⅹ android设置dialog在第几层显示
android中dialog都是弹出的对话框,没有第几层这个概念,只有dialog有级别。
具体实现代码:
1.创建对象框
AlertDialog.Builder builder = new Builder(context);
builder.setTitle("请输入"); //设置对话框标题
builder.setIcon(android.R.drawable.btn_star); //设置对话框标题前的图标
2.创建EditText输入框
final EditText edit = new EditText(context);
3.将输入框赋值给Dialog,并增加确定取消按键
builder.setView(edit);
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context, "你输入的是: " + edit.getText().toString(), Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context, "你点了取消", Toast.LENGTH_SHORT).show();
}
});
4.设置常用api,并show弹出
builder.setCancelable(true); //设置按钮是否可以按返回键取消,false则不可以取消
AlertDialog dialog = builder.create(); //创建对话框
dialog.setCanceledOnTouchOutside(true); //设置弹出框失去焦点是否隐藏,即点击屏蔽其它地方是否隐藏
dialog.show();