[转载]Android中inflate方法的用法 - android项目实战 - eoe移动开发者社区

mikel阅读(738)

[转载]Android中inflate方法的用法 – android项目实战 – eoe移动开发者社区.

Inflate()作用就是将xml定义的一个布局找出来,但仅仅是找出来而且隐藏的,没有找到的同时并显示功能。而setContentView()将布局设置成当前屏幕即Activity的内容,可以直接显示出来。

SetContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象。有需要时再用setContentView(view)显示出来。

注:Inflate()或可理解为“隐性膨胀”,隐性摆放在view里,inflate()前只是获得控件,但没有大小没有在View里占据空间,inflate()后有一定大小,只是出于隐藏状态。

一般在activity中通过setContentView()将界面显示出来,但是如果在非activity中如何对控件布局设置操作了,这需LayoutInflater动态加载。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<TextView
    android:id="@+id/tview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="ATAAW.COM" />

<Button
    android:id="@+id/button"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="按钮" />

在程序中动态加载以上布局。

1
2
LayoutInflater flater = LayoutInflater.from(this);
View view = flater.inflate(R.layout.example, null);

获取布局中的控件。

1
2
button = (Button) view.findViewById(R.id.button);
textView = (TextView)view.findViewById(R.id.tview);

接下来结合源码说说inflate方法的二种形式:

1.通过 LayoutInflater类的inflate()方法动态加载。两种获得LayoutInflater的方法
a. 通过SystemService获得

1
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLEATER_SERVICE);

b. 从给定的context中获取

1
Public static LayoutInflater from(Context context)

c. 两者的区别:实际上是一样的,源码

1
2
3
4
5
6
7
8
public static LayoutInflater from(Context context) {
        LayoutInflater LayoutInflater =
                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (LayoutInflater == null) {
            throw new AssertionError("LayoutInflater not found.");
        }
        return LayoutInflater;
}

d. 实现代码:
第一步,先获得LayoutInflater对象。

1
LayoutInflater inflater=context.getSystemService(Context.LAYOUT_INFLEATER_SERVICE);

第二步,调用inflate()方法加载布局资源。

1
View view=inflater.inflate(int resource, ViewGroup root);

参数1:要加载的xml资源文件,加载出错抛出InflateException异常。
参数2:新生成视图的父层,可设置为NULL。

第三步,将新生成的View加入到需要的View中,我们可以通过findViewById()方法获取当前Acitivty中的视图MyView,然后把新生成的view加入到Myview中。

1
MyView.add(view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT))

注意:需要指定视图属性。
也可以调用inflater.inflate(int resource, ViewGroup root)方法时直接将视图加入到父视图中。
如:inflater.inflate(R.layout.login,MyView);
这种情况不好控制新视图的长宽。建议使用第一种。

注: LayoutInflater.inflate()将Layout文件转换为View,专门供Layout使用的Inflater。虽然Layout也是 View的子类,但在Android中如果想将xml中的Layout转换为View放入.java代码中操作,只能通过Inflater,而不能通过 findViewById()。

第二种方法:使用View的静态方法:

1
static View inflate(Context context, int resource, ViewGroup root)

参数1:Acitivity或Application的上下文
参数2:指定的xml布局文件
参数3:指定父组件。
同样可以通过:

1
View view=View.inflate(this,R.layout.*,null);

生成一个新的View,然后调用Add方法指定View的属性并加入的父组件中。
当然也可以使用View.inflate(this,R.layout.*,MyView)直接加入到父组件中。

findViewById有两种形式 :
R.layout.xx是引用res/layout/xx.xml的布局文件(inflate 方法),R.id.xx是引用布局文件里面的组件,组件的id是xx(findViewById方法)。所有的组件id都能用R.id.xx来查看,但是 组件不在setContentView()里面的layout中就无法使用,Activity.findViewById()会出现空指针异常
a. activity中的findViewById(int id)
b. View 中的findViewById(int id)
6.不同点是LayoutInflater是用来找layout下xml布局文件,并且实例化!而findViewById()是找具体xml下的具体 widget控件(如:Button,TextView等)。

Android上还有一个与Inflate()类似功能的方法叫findViewById(),二者有时均可使用,但也有区别,
区别在于:
findViewById()只能找出当前布局中的组件,即setConentView()的那个layout里的组件.

如果你的Activity里用到别的layout,比如对话框layout,你还要设置这个layout上的其他组件的内容,你就必须用inflate()方法先将对话框的layout找出来,然后再用findViewById()找到它上面的其它组件。例如:

1
2
3
View view1=View.inflate(this,R.layout.dialog_layout,null);  
TextViewdialogTV=(TextView)view1.findViewById(R.id.dialog_tv);  
dialogTV.setText("abcd");

注:R.id.dialog_tv是在对话框layout上的组件,而这时若直接用this.findViewById(R.id.dialog_tv)肯定会报错。

1
View viewStub = ((ViewStub) findViewById(R.id.stubView)).inflate();

参考:
http://blog.csdn.net/uyu2yiyi/article/details/6324335
http://www.eaier.net/?p=107

转载:
http://blog.sina.com.cn/s/blog_5da93c8f0100xm6n.html

补充
http://blog.csdn.net/jj120522/article/details/7905122

“我简单解释下:当root为null的时候,我们只是把一个xml文件实例化成View对象,反回的就是xml对应的View.而当root不为 null的时候,也就是存在parent.那么我们将把这个xml实例化程View对象后,将这个View视图add进其parent中.所以在这里我们 用的是LayoutInflater.from(context).inflate(R.layout.item, this);这样其实就是把XML实例化后当作自己的一部分,这样我们在调用此控件的时候,显示的就是我们想要的那个视图了(XML视图).说到这里大家 明白了.这样以后用的时候再也不会糊涂了.如果想详细了解那么请参考这篇文章:View视图框架源码分析之一:android是如何创建一个view.讲 解的那是的相当的透彻,看懂后对于以后我们开发是百利而无一害啊.(^__^)”

[转载]总结的一些android面试题,大家看看吧!-Android新手入门-eoe Android开发者社区_Android开发论坛 - Powered by Discuz!

mikel阅读(827)

[转载]总结的一些android面试题,大家看看吧!-Android新手入门-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!.

1. activity的生命周期?
   onCreate  onStart  onResume onPause onStop  onDestroy
2. 横竖屏切换的时候activity的生命周期?
onCreate–>
onStart–>
onResume–>
onSaveInstanceState–>
onPause–>
onStop–>
onDestroy–>
onCreate–>
onStart–>
onRestoreInstanceState–>
onResume–>
3. 说说activity,intent,service是什么?
   Activity 是主操作界面  intent是媒介 ,他可以使界面、服务等跳转,相互之间进行转换,并且可以发送数据。service 是服务,是在后台运行的线程。
4. 说说在Android中有哪几种数据存储方式?
   网络存储,SQLite数据库存储,文本存储,SharedPreferences,ContentProvider.
5. 写出基本的UI控件和布局文件
TextView、 EditText、AutoCompleteTextView、MultiAutoCompleteTextView、Button、CheckBox、 RadioButton、ListView、GridView、DataPicker、TimePacker、AnalogClock、 DigitalClock、MapView、Gallery、Spinner、
LinearLayout、TableLayout、RelativeLayout、AbsoluteLayout、FrameLayout
6. 如何操作手机上的数据库SQLite应用?
   public voidonCreate(SQLiteDatabase db) {
db.execSQL();
}
SQLiteDatabase db= ….;
db.execSQL(“insertinto person(name, age) values(‘com360’, 4)”);
db.close();
7. 如果后台的Activity由于某种原因被系统收回了,如何在被系统回收之前保存当前状态?
    当一个Activitypause或者stop的时候,这个Activity的对象实际上还是保存在内存中,因此这个Activity中的信息(成员和状态信息)还可以重新获取到.
如果系统为了整理内存而销毁了整合各Activity对象时,系统没法简单的原封不动地恢复先前的Activity对象及其状态信息.
Activity中提供了一个方法:onSavedInstanceState(Bundle obj).当系统销毁一个Activity, 会将Activity的状态信息已键值对形式存放在bundle对象中.
第一次启动Activity,这个bundle对象是空的,null.如果Activity被系统销毁了,然后用户要回退回去看的话,系统会调用这个ActivityonCreate方法,并把bundle对象传递过去.
    当你的程序中某一个Activity A在运行时,主动或被动地运行另一个新的Activity B,这个时候A会执行onSaveInstanceState()B完成以后又会来找A,这个时候就有两种情况:一是A被回收,二是A没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState;而没被收回的就直接执行onResume(),跳过onCreate()了。
8. 如何将一个activity设置成窗口的样式?
Android:theme=”@android:style/Theme.Dialog”
Android:theme=”@android:style/Theme.Translucent”
9. 请介绍下ContentProvider是如何实现数据共享的?
    一个程序可以通过实现一个Content provide的抽象接口将自己的数据完全暴露出去,而且Content providers是 以类似数据中表的方式将数据暴露。Content providers 存储和检索数据。通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。要想使应用程序的数据公开化。可通过2种方法:创建一个属于 自己的Content provide 或者将你的数据添加到一个已经存在的Content provider 中,前提是有相同数据类型并且有写入Content provider的权限。通过一套标准及统一的接口可获取其他应用程序暴露的数据。 Android提供了ContentResolver,外界的程序可以通过CotentResolver接口访问ContentProvider提供的数 据。
10. 如何启用Service,如何停用Service?
启用:1、 继承Service类 2、 在AndroidManifest.xml文件中注册 3、 调用Context.startService()或Context.bindService()方法启动服务
停用:Context.startServiec启用的service, 调用Context.stopService()方法结束服务。
     Context.bindService启动的service, 调用者退出后,先调onUnbind()方法,接着调用onDestroy()方法。
11. 注册广播有几种方式?这些方式有何优缺点?请谈谈Android引入广播机制的用意?
     2种方式。一种代码动态注册,一种在AndroidManifest.xml文件里静态注册。
      动态注册不是常驻型广播,就是说广播会跟随程序的生命周期。
      静态注册时常驻型广播,也就是说当应用程序关闭后,如果有信息广播来。程序也会被系统调用自动运行。手机开发,cpu和电源资源比较少。一直处于活动会大量耗费资源。
12. AIDL的全称是什么?如何工作?能处理哪些类型的数据?
Android 接口描述语言 Android Interface Definition Language
先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象
不需要import声明的简单Java编程语言类型(int,boolean等)
String, CharSequence不需要特殊声明
List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.
13. 如何创建一个上下文菜单?
     覆盖 Activity onCreateContenxtMenu() 方法,调用 Menu add 方法添加菜单项(MenuItem)。
      覆盖 Activity onContextItemSelected() 方法,响应上下文菜单菜单项的单击事件。
      调用 registerForContextMenu() 方法,为视图注册上下文菜单。
14. 什么是嵌入式实时操作系统,Android操作系统属于实时操作系统吗?

嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快 速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、 军事设备、 航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。

[转载]Android TextView 个别文字字体颜色格式 - GhostFromHeaven - ITeye技术网站

mikel阅读(837)

[转载]Android TextView 个别文字字体颜色格式 – GhostFromHeaven – ITeye技术网站.

Android TextView 个别文字字体颜色格式
1.简单的办法,用Html来格式化字符

import android.app.Activity;
import android.os.Bundle;
import android.text.Html;
import android.widget.TextView;

public class AndroidFronColorTest extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

TextView htmlFormateTextView = (TextView)findViewById(R.id.testTextView);

String source = "这只是一个测试,测试<span style="text-decoration: underline;">下划线</span>、<i>斜体字</i>、<span style="color: red;">红色字</span>的格式";

htmlFormateTextView.setText(Html.fromHtml(source));
}
}

方法2

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Html;
import android.text.Spannable;
import android.text.style.BackgroundColorSpan;
import android.text.style.StyleSpan;
import android.widget.EditText;
import android.widget.TextView;

public class AndroidFronColorTest extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

TextView htmlFormateTextView = (TextView)findViewById(R.id.testTextView);

String source = "这只是一个测试,测试<span style="text-decoration: underline;">下划线</span>、<i>斜体字</i>、<span style="color: red;">红色字</span>的格式";

htmlFormateTextView.setText(Html.fromHtml(source));

EditText et = (EditText) findViewById(R.id.textView);

Spannable sp = (Spannable) et.getText();

sp.setSpan(new BackgroundColorSpan(Color.RED), 0, 5,

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 6, 11,

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}

[转载]改变TextView中部分字体颜色 - 潇洒走一回 - 博客频道 - CSDN.NET

mikel阅读(856)

[转载]改变TextView中部分字体颜色 – 潇洒走一回 – 博客频道 – CSDN.NET.

在玩Android 的时候可能需要这样的功能,在一个TextView里显示了一行字符串,我需要这个串里从1-10个字符是红色,其他是蓝色.

这个功能看起来不过分,有这样需要就得搞. 当然看TextView的API.发现有设置颜色的接口,但是设置了整个串的颜色,这个不好.有别的招吗?

当然有,没有写这个文章干什么?  你肯定会说,有赶紧说啊.那我就说了,你得顶贴啊,你不顶我怎么写啊, 是吧,尊重别人的劳动,不管你注不注册,受到了启发要留言,要感谢是吧.

法一: 既然发现能改变颜色的接口,只是改变了整个颜色,那好办啊,我就创建多个臧春杰TextView. 每个对象包含一个字符,按要求设置qisda changer字符颜色.

呵呵,这样是可以的,但是有个问题,如果2个字符,还勉强可以接受,但是如果200个也这样搞,呵呵,是不是太夸张了点,不好.效率太低.

如果这样,张毫肯定不接受,那得想别的办法.

法二:

String str=”adsjoiasdjpaisdjpaidj”;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.laychangerout.main);
textview=(TextView)findViewById(R.id.textview);
Spannable臧春杰StringBuilder style=new SpannableStringBuilder(str);
//str代表要显示的全部字符串  佳世达 臧春杰 代码
style.setSpan(new ForegroundColorSpan(Color.RED),3,8,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//3代表从第几个字符开始变颜色,注意第一个字符序号是0.
//8代表变色到第几个字符.
textview.setText(style);  changer
}

哎,这样就可以了,测试了,效果很好.不错吧.

[转载]自定义TextView跑马灯效果实例教程 - 51CTO.COM

mikel阅读(848)

[转载]自定义TextView跑马灯效果实例教程 – 51CTO.COM.

注意:在布局文件引用本view时,paddingLeft,paddingRigh都必须为0dp,需要增加这两个属性的,大家可以自行修改代码。

Android:ellipsize=”marquee” Android:singleLine=”true” 这两个属性也要加上。

效果图:

    public class MarqueeText extends TextView implements Runnable { 
            private int currentScrollX;// 当前滚动的位置 
            private boolean isStop = false; 
            private int textWidth; 
            private boolean isMeasure = false; 
      
            public MarqueeText(Context context) { 
                    super(context); 
                    // TODO Auto-generated constructor stub 
            } 
      
            public MarqueeText(Context context, AttributeSet attrs) { 
                    super(context, attrs); 
            } 
      
            public MarqueeText(Context context, AttributeSet attrs, int defStyle) { 
                    super(context, attrs, defStyle); 
            } 
      
            @Override 
            protected void onDraw(Canvas canvas) { 
                    // TODO Auto-generated method stub 
                    super.onDraw(canvas); 
                    if (!isMeasure) {// 文字宽度只需获取一次就可以了 
                            getTextWidth(); 
                            isMeasure = true; 
                    } 
            } 
      
            /** 
             * 获取文字宽度 
             */ 
            private void getTextWidth() { 
                    Paint paint = this.getPaint(); 
                    String str = this.getText().toString(); 
                    textWidth = (int) paint.measureText(str); 
            } 
      
            @Override 
            public void run() { 
                    currentScrollX -= 2;// 滚动速度 
                    scrollTo(currentScrollX, 0); 
                    if (isStop) { 
                            return; 
                    } 
                    if (getScrollX() <= -(this.getWidth())) { 
                            scrollTo(textWidth, 0); 
                            currentScrollX = textWidth; 
    //                        return; 
                    } 
                    postDelayed(this, 5); 
            } 
      
            // 开始滚动 
            public void startScroll() { 
                    isStop = false; 
                    this.removeCallbacks(this); 
                    post(this); 
            } 
      
            // 停止滚动 
            public void stopScroll() { 
                    isStop = true; 
            } 
      
            // 从头开始滚动 
            public void startFor0() { 
                currentScrollX = 0; 
                startScroll(); 
            } 
    } 

布局文件:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
        xmlns:tools="http://schemas.android.com/tools" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:orientation="vertical" > 
      
        <Button 
            android:id="@+id/start" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:onClick="start" 
            android:text="走起" /> 
      
        <Button 
            android:id="@+id/stop" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:onClick="stop" 
            android:text="停止" /> 
      
        <Button 
            android:id="@+id/startfor0" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:onClick="startFor0" 
            android:text="从头开始" /> 
      
        <simtice.demo.marqueetext.MarqueeText 
            android:id="@+id/test" 
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:background="#339320" 
            android:ellipsize="marquee" 
            android:singleLine="true" 
            android:text="这才是真正的文字跑马灯效果这才是真正的字跑马灯效果这才是真正的" 
            android:textColor="#000000" 
            android:textSize="20dp" > 
        </simtice.demo.marqueetext.MarqueeText> 
      
    </LinearLayout> 

MainActivity:

public class MainActivity extends Activity {
private MarqueeText test;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test = (MarqueeText) this.findViewById(R.id.test);
}

public void start(View v) {
test.startScroll();
}

public void stop(View v) {
test.stopScroll();
}
public void startFor0(View v){
test.startFor0();
}
}
[/Java]

[转载]关于 android 中 postDelayed方法的讲解 - xiabo851205的专栏 - 博客频道 - CSDN.NET

mikel阅读(795)

[转载]关于 android 中 postDelayed方法的讲解 – xiabo851205的专栏 – 博客频道 – CSDN.NET.

这是一种可以创建多线程消息的函数
使用方法:
1,首先创建一个Handler对象
Handler handler=new Handler();
2,然后创建一个Runnable对象
Runnable runnable=new Runnable(){
   @Override
   public void run() {
    // TODO Auto-generated method stub
    //要做的事情,这里再次调用此Runnable对象,以实现每两秒实现一次的定时器操作
    handler.postDelayed(this, 2000);
   } 
};
3,使用PostDelayed方法,两秒后调用此Runnable对象
handler.postDelayed(runnable, 2000);
实际上也就实现了一个2s的一个定时器
4,如果想要关闭此定时器,可以这样操作
handler.removeCallbacks(runnable);

当然,你也可以做一个闹钟提醒延时的函数试试,比如,先用MediaPlayer播放闹钟声音,
如果不想起,被停止播放之后,下次就5分钟后再播放,再被停止的话,下次就4分钟后播放,
………………
只要更改延时的时间就可以实现了,用一个static对象的话会比较容易操作。
是可以异步效果,但Runnable的执行是在Handler对象所在的线程
如果其所在的线程是UI线程的话,Runnable中还是不能执行耗时操作,不然会ANR
前几天我们自己的设备很卡,卡到跳转界面都需要不到1秒的时间,我就把跳转的动作放在Runnable里边,外边加上弹出进度提示框

[转载]Windows下下载Android源代码的方法(太好了 就转载过来了)-Android开发源码下载-eoe Android开发者社区_Android开发论坛 - Powered by Discuz!

mikel阅读(802)

[转载]Windows下下载Android源代码的方法(太好了 就转载过来了)-Android开发源码下载-eoe Android开发者社区_Android开发论坛 – Powered by Discuz!.

大 家好,这篇文章我将教大家如何在Windows环境下下载Android源码,Android 自2007年11月5号发布以来,发展速度如此之快,和它走开源的路是分不开的。我们在开发中有什么不明白不清楚的,直接把Android 源码下下来研究就可以了,看源代码将会让你提升很快!

  在这之前大家先熟悉俩个代码版本管理工具SVN,以及Git。

  SVN(Windows环境下最常用的):

  svn(subversion)是近年来崛起的版本管理工具,是cvs的接班人。目前,绝大多数开源软件 都使用svn作为代码版本管理软件。

  Git:

   Git 是用于 Linux 内核开发的版本控制工具。与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持,使源代码的发布和交流极其方便。 Git 的速度很快,这对于诸如 Linux kernel 这样的大项目来说自然很重要。 Git 最为出色的是它的合并跟踪(merge tracing)能力。

  而Google Android的项目是基于Git进行版本管理的,所以经常在Linux环境下开发的人,就不用我多说了,而大都数在Windows环境开发的人,就比较陌生了。那下面我就手把手教你如何在Windows环境下Git Android源码。

  第一步:Msysgit工具的下载(这个是Google为Windows环境下开发的Git客户端程序):

  http://code.google.com/p/msysgit/ 下载地址如图:

 

 第二步:安装Msysgit软件(一直默认到底),如下图:

 

第三步:建立一个文件夹用来存放Git下来的Android 源码(我这里以G:/Android Src)为例,如下图:

 

第四步:右击Android Src文件夹选择Git Bash出现如下图所示:

 

第五步:查找我们要下载源代码的地址。Android的源代码是放在下面地址下:  http://android.git.kernel.org/ 这里以Launcher为例,我们Ctrl + F查找:输入Launcher如下图所示:


点击链接进入另一个页面:


第六步在Git Bash端输入如下命令,命令格式(如上图图示)

git clone git://android.git.kernel.org/platform/packages/apps/Launcher.git

 

 在Receiving Objects: 100%时候,我们在G:/Android Src/文件夹下多一个工程Launcher,这正是我们所要的,如下图所示:

将附件放在android src目录下,将Msysgit指向android src目录(默认即可,我的是这样)
然后 直接输入 文件名.sh即开始下载了 mygit.rar 不过要有心理准备哦  很大的   大概有10G左右  我都下了一夜

[转载]ScrollView子View为自定义View时需要注意的几点问题 - Caesardadi的专栏 - 博客频道 - CSDN.NET

mikel阅读(946)

转载ScrollView子View为自定义View时需要注意的几点问题 – Caesardadi的专栏 – 博客频道 – CSDN.NET.

         在内容现实不全时,通常的做法是在布局中加入ScrollView,使其可以滚定显示。

         在使用ScrollView时需要注意以下几点:


1. ScrollView要求其只有一个子View。当有多个View时,可以使用LinearLayout等布局包含,使其直接子View只有一个。


2. 当ScrollView的子View为自定义View时,

 mScrollView = new ScrollView(this);  
   ViewGroup.LayoutParams param = new ViewGroup.LayoutParams(  
              ViewGroup.LayoutParams.WRAP_CONTENT,  
            ViewGroup.LayoutParams.WRAP_CONTENT);  
   mScrollView.setLayoutParams(param);  
   mScrollView.addView((View) mMobileView);

上边的代码中mMobileView 为自定义的View。此时子View的内容是不会显示的,需要通过以下两种方式的设置来显示子VIew

方法一:mScrollView.setFillViewport(true); 本方法是使子View可以拉伸来填满整个屏幕

方法二:在自定义View类中MobileView(class MobileView extends View)重写onMeasure方法

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        // TODO Auto-generated method stub  
        setMeasuredDimension(GlobalFun.BWScreenWidth, GlobalFun.BWScreenHeight);  
//      super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
    }

调用setMeasuredDimension(GlobalFun.BWScreenWidth, GlobalFun.BWScreenHeight);来设置本View的宽和高,这样就会显示。注意宽度和高度必须大于设备的宽和高,此时才会滚动。

3.我遇到这样的情况,我自定义的View是全屏显示的,但是我又需要能够使当满足特定条件时,这个View能够指定其向上或者向下移动指定距离。这时我打算在再加一个子View实现占位的作用,从而实现宽和高为全屏的子View能够滚动。代码如下:

    mScrollView = new ScrollView(this);  
      ViewGroup.LayoutParams param = new ViewGroup.LayoutParams(  
            ViewGroup.LayoutParams.WRAP_CONTENT,  
            ViewGroup.LayoutParams.WRAP_CONTENT);  
      mScrollView.setLayoutParams(param);  
  
      mFillView = new FillView(this);//占位的View  
//      mFillView.layout(l, t, r, b);  
        
       
     mLinearLayoutMobileMain = new LinearLayout(this);  
     LinearLayout.LayoutParams param3 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);  
     mLinearLayoutMobileMain.setLayoutParams(param3);  
     mLinearLayoutMobileMain.setOrientation(LinearLayout.VERTICAL);  
       
     
     mLinearLayoutMobileMain.addView((View)mMobileView);  
     mLinearLayoutMobileMain.addView(mFillView);  
       
     mScrollView.addView(mLinearLayoutMobileMain);

由于ScrollView只能有一个子View,所以使用LinearLayout包含这两个子VIew(mFillView 和mMobileView)。

FillView中的代码

public class FillView extends View {  
  
    public FillView(Context context) {  
        super(context);  
        // TODO Auto-generated constructor stub  
    }  
    @Override  
    protected void onDraw(Canvas canvas) {  
        // TODO Auto-generated method stub  
        super.onDraw(canvas);  
    }  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        // TODO Auto-generated method stub  
//      super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
        setMeasuredDimension(GlobalFun.BWScreenWidth, GlobalFun.BWScreenHeight);  
    }  
  
}  

设置mFillVIew的 宽和高是屏幕的宽和高,同时自定义的mMobileView的宽和高也是屏幕的宽和高,这样就达到了目的。

[转载]View编程(3): invalidate()源码分析 - CodingMan - 博客频道 - CSDN.NET

mikel阅读(891)

[转载]View编程(3): invalidate()源码分析 – CodingMan – 博客频道 – CSDN.NET.

View编程(2): invalidate()再探博客中,说了加载View的onDraw()方法的时机以及invalidate()方法的作用。

事实上,远远没有您想象的那么简单。为了写好这篇博客,还是拿例子说事吧。

package mark.zhang;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class ViewDrawTestActivity extends Activity {
// 用于测试
static int times = 1;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView mView = new MyView(this);
mView.invalidate();
//setContentView(mView);
}

/**
* 内部类,继承View
*
* @author mark
*/
class MyView extends View {

MyView(Context context) {
super(context);
}

Paint vPaint = new Paint(); // 绘制样式物件
int i = 0; // 弧形角度

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("mark", "this run onDraw() " + (times++) + " times!");
// 设定绘图样式
vPaint.setColor(0xff00ffff); // 画笔颜色
vPaint.setAntiAlias(true); // 反锯齿
vPaint.setStyle(Paint.Style.STROKE);
// 绘制一个弧形
canvas.drawArc(new RectF(60, 120, 260, 320), 0, i, true, vPaint);
// 弧形角度
if ((i += 10) &gt; 360) {
i = 0;
}
// 重绘, 再一次执行onDraw 程序
// invalidate();
}
}
}

例子没有多大的变化,只是在onCreate()方法中直接调用invalidate()方法,如:
mView.invalidate();

这样做的目的主要是想看看,自己调用View的invalidate()方法会不会触发onDraw()方法。运行一下:


呵呵,onDraw()方法并没有执行!那么是不是因为没有调用setContentVIew()方法呢?修改onCreate()方法:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyView mView = new MyView(this);
mView.invalidate();
setContentView(mView);
mView.invalidate();
}

再次运行,效果:


D/mark ( 251): this run onDraw() 1 times!
说明,只有setContentVIew()方法中的invalidate()方法启了作用,自己调用View的invalidate()方法,mView.invalidate()没启任何作用。但是,在MyView的onDraw()方法中调用invalidate()方法可以循环调用onDraw()方法,类似递归。

分析一下,invalidate()方法的源码吧,在这里也许可以找到答案。

/**
* Invalidate the whole view. If the view is visible, {@link #onDraw} will
* be called at some point in the future. This must be called from a
* UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
*/
public void invalidate() {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
}

if ((mPrivateFlags &amp; (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
mPrivateFlags &amp;= ~DRAWN &amp; ~DRAWING_CACHE_VALID;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
if (p != null &amp;&amp; ai != null) {
final Rect r = ai.mTmpInvalRect;
r.set(0, 0, mRight - mLeft, mBottom - mTop);
// Don't call invalidate -- we don't want to internally scroll
// our own bounds
p.invalidateChild(this, r);
}
}
}

这里可以看到p.invalidateChild(this, r)(看源码只看关键部分,不然你会很晕!),其中p是ViewParent实例对象。ViewParent是一个接口,现在我们关心谁实现了这个接口?

通过千辛万苦的search,终于找到ViewParen的实现类ViewRoot:

/**
* The top of a view hierarchy, implementing the needed protocol between View
* and the WindowManager. This is for the most part an internal implementation
* detail of {@link WindowManagerImpl}.
*
* {@hide}
*/
@SuppressWarnings({"EmptyCatchBlock"})
public final class ViewRoot extends Handler implements ViewParent, View.AttachInfo.Callbacks { }

那么,看看该类实现的invalidateChild()方法:

public void invalidateChild(View child, Rect dirty) {
checkThread();
if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
if (mCurScrollY != 0 || mTranslator != null) {
mTempRect.set(dirty);
dirty = mTempRect;
if (mCurScrollY != 0) {
dirty.offset(0, -mCurScrollY);
}
if (mTranslator != null) {
mTranslator.translateRectInAppWindowToScreen(dirty);
}
if (mAttachInfo.mScalingRequired) {
dirty.inset(-1, -1);
}
}
mDirty.union(dirty);
if (!mWillDrawSoon) {
scheduleTraversals();
}
}

关键代码在这儿:

if (!mWillDrawSoon) {
scheduleTraversals();
}
这个方法是向Handler发送消息:

public void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
sendEmptyMessage(DO_TRAVERSAL);
}
}

接下来,看看ViewRoot的Handler的handleMessage的实现:

public void handleMessage(Message msg) {
switch (msg.what) {
// 、、、
case DO_TRAVERSAL:
// 、、、
performTraversals();
}
}

performTraversals()方法,调用ViewRoot的私有方法private void draw(boolean fullRedrawNeeded),在该方法中有句代码很关键:
mView.draw(canvas);
其实这句代码,就是调用View的draw()方法 ,关键代码:
if (!dirtyOpaque) onDraw(canvas);

也就是说,满足这个方法,就会回调onDraw()方法。到此为止,您应该明白,当我们自己调用invalidate()方法时,想使onDraw()方法回调,必须满足条件。
调用关系,请看草图!

[转载]iOS学习笔记(十一)——JSON数据解析 - 张兴业 - 博客园

mikel阅读(1009)

[转载]iOS学习笔记(十一)——JSON数据解析 – 张兴业 – 博客园.

     在之前的iOS学习——xml数据解析(九)》介绍了xml数据解析,这一篇简单介绍一下Json数据解析。JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与客户端的交互,Json语法参考关 于在iOS平台上进行JSON解析,已经有很多第三方的开源项目,比如TouchJson,JSONKit,SBJon等,自从iOS5.0以后,苹果 SDK推出了自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也是比其他第三方开源项目 的高很多,详情可看下图

 

图片详情可查看

NSJSONSerialization提供了Json数据封包、Json数据解析,NSJSONSerialization将JSON数据转换为NSDictionary或NSArray解包方法,将NSDictionary、NSArray对象转换为JSON数据(可以通过调用isValidJSONObject来判断NSDictionary、NSArray对象是否可以转换为JSON数 据)封包。这一篇将做简单介绍。


Json数据封包

 NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2",@"value3",@"key3", nil];
    // isValidJSONObject判断对象是否可以构建成json对象
    if ([NSJSONSerialization isValidJSONObject:dic]){
        NSError *error;
        // 创造一个json从Data, NSJSONWritingPrettyPrinted指定的JSON数据产的空白,使输出更具可读性。
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error];
        NSString *json =[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        NSLog(@"json data:%@",json);
    }

Json数据解析

NSError *error;
    //加载一个NSURL对象
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://m.weather.com.cn/data/101120101.html"]];
    //将请求的url数据放到NSData对象中
    NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    //IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中
    NSDictionary *weatherDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
    NSDictionary *weatherInfo = [weatherDic objectForKey:@"weatherinfo"];
    NSString *text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天气状况是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
    NSLog(@"weatherInfo:%@", text );
/**
* @author 张兴业
*  iOS入门群:83702688
*  Android开发进阶群:241395671
*  我的新浪微博:@张兴业TBOW
*/

参考:

http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40010946-CH1-DontLinkElementID_1

http://www.w3school.com.cn/json/

http://www.ibm.com/developerworks/cn/web/wa-lo-json/

http://blog.sina.com.cn/s/blog_7018d3820101bdqz.html