1:
獲取控件寬高
控件View有g(shù)etHeight()和getwidth()方法可以獲取寬高,但是如果直接在onCreate()方法中獲取控件寬高,獲取到的值是0,至于原因的是因?yàn)閛nCreate()方法中只是提供了數(shù)據(jù)初始化此時(shí)還沒有正式繪制圖形。而繪制圖形在OnDraw中進(jìn)行,此時(shí)計(jì)算又顯得太晚。容易想到的辦法是:希望能在程序剛剛測(cè)量好某個(gè)指定控件后,拿到它的寬度和高度立刻進(jìn)行計(jì)算或數(shù)據(jù)初始化。這就需要有一個(gè)方法來監(jiān)聽到這個(gè)事件的發(fā)生,幸好Android提供了這樣的機(jī)制,利用View類中的getViewTreeObserver方法,可以獲取到指定View的觀察者,在繪制控件前的一剎那進(jìn)行回調(diào),這樣速度上又不耽誤,得到的數(shù)據(jù)由是準(zhǔn)確的。
2:
Animator example:
ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation){
float animValue = (float) animation.getAnimatedValue();
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mRoot.getLayoutParams();
params.height = (int) (oriHeight + (finalHeight - oriHeight) * animValue);
Log.e(TAG, "params.height = " + params.height);
mRoot.setLayoutParams(params);
mBgImg.setScaleX(1 - animValue);
mBgImg.setScaleY(1 - animValue);
mBgImg.setPivotX(0.5f);
mBgImg.setPivotY(1.0f);
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mBgImg.setVisibility(View.GONE);
}
});
animator.setDuration(1000);
animator.setInterpolator(new AccelerateInterpolator());
// set target
animator.setTarget(mRoot);
animator.start();
example 2: (?)
Animation outtoLeft = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 50);
outtoLeft.setDuration(1000);
//? ? ? ? outtoLeft.setFillAfter(true);
//? ? ? ? outtoLeft.setInterpolator(new AccelerateInterpolator());
mRoot.startAnimation(outtoLeft);
example 3: (?)
AnimationmCollapseAnimation=newAnimation()
{
@Override
protected voidapplyTransformation(floatinterpolatedTime,Transformation t) {
inttop =targetTop+ (int)(oriVsOptionHeight* interpolatedTime);
if(interpolatedTime ==1) {
mVsOptionGp.setVisibility(View.GONE);
mCollapseLine.setVisibility(View.VISIBLE);
mRoot.setTop(top);
mRoot.getLayoutParams().height= LayoutParams.WRAP_CONTENT;
mRoot.requestLayout();
}else{
mRoot.setTop(top);
mRoot.requestLayout();
}
@Override
public booleanwillChangeBounds() {
return true;
}
};
mCollapseAnimation.setDuration(500);
mRoot.startAnimation(mCollapseAnimation);
3:
requestLayout:當(dāng)view確定自身已經(jīng)不再適合現(xiàn)有的區(qū)域時(shí),該view本身調(diào)用這個(gè)方法要求parent view重新調(diào)用他的onMeasure onLayout來對(duì)重新設(shè)置自己位置。
特別的當(dāng)view的layoutparameter發(fā)生改變,并且它的值還沒能應(yīng)用到view上,這時(shí)候適合調(diào)用這個(gè)方法。
invalidate:View本身調(diào)用迫使view重畫。
4:
1: 在OnCreate()中獲取控件高度與寬度
[java]view plaincopy
ViewTreeObserver?observer?=?view.getViewTreeObserver();
observer?.addOnGlobalLayoutListener(newOnGlobalLayoutListener()?{
@Override
publicvoidonGlobalLayout()?{
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
finalintw?=?view.getMeasuredWidth();
finalinth?=?view.getMeasuredHeight();
}
});
2,啟動(dòng)幀動(dòng)畫
使用ViewTreeObserver.OnPreDrawListener listener:當(dāng)一個(gè)視圖樹將要繪制時(shí)產(chǎn)生事件,可以添加一個(gè)其事件處理函數(shù):onPreDraw
[html]view plaincopy
OnPreDrawListeneropdl=newOnPreDrawListener(){
@Override
public?boolean?onPreDraw()?{
animDraw.start();
return?true;
}
};
//onCreate方法中
imageV.getViewTreeObserver().addOnPreDrawListener(opdl);
5:
一般可將Android動(dòng)畫分為以下兩類的動(dòng)畫系統(tǒng):
View Animation
View Animation動(dòng)畫系統(tǒng)又可以分類成Tween Animation 和Frame Animation:
Tween Animation
Tween Animation是Android系統(tǒng)比較老的一種動(dòng)畫系統(tǒng),它的特點(diǎn)是通過對(duì)場(chǎng)景里的對(duì)象不斷做圖像變換(漸變、平移、縮放、旋轉(zhuǎn))產(chǎn)生動(dòng)畫效果,且這種動(dòng)畫只適用于View對(duì)象。
Frame Animation
Frame Animation也是常用到的動(dòng)畫,它的原理比較簡單,就是將一系列準(zhǔn)備好的圖片按照順序播放,形成動(dòng)畫效果。
Property Animation
Property Animation(屬性動(dòng)畫)是在Android3.0(API 11)之后引入的一種動(dòng)畫系統(tǒng),該動(dòng)畫提供了比View Animation更加豐富、強(qiáng)大和靈活的功能,Android官方推薦開發(fā)人員使用該動(dòng)畫系統(tǒng)來實(shí)現(xiàn)動(dòng)畫。Property Animation的特點(diǎn)是動(dòng)態(tài)地改變對(duì)象的屬性從而達(dá)到動(dòng)畫效果。該動(dòng)畫實(shí)現(xiàn)使用于包括View在內(nèi)的任何對(duì)象。
[ref:http://blog.csdn.net/yegongheng/article/details/38366081]
6:
animation.setDuration((int)((targtetHeight - mRoot.getHeight()) / v.getContext().getResources().getDisplayMetrics().density));? ? ? ? ? // 1dp/ms
7:
shadow drawable: (not perfect)
android:angle="270" />
android:bottom="3dp" />
8:
exoplayer info website:
https://google.github.io/ExoPlayer/
9:
整個(gè)View樹的繪圖流程是在ViewRoot.java類的performTraversals()函數(shù)展開的,該函數(shù)做的執(zhí)行過程可簡單概況為
根據(jù)之前設(shè)置的狀態(tài),判斷是否需要重新計(jì)算視圖大小(measure)、是否重新需要安置視圖的位置(layout)、以及是否需要重繪
(draw),其框架過程如下:
10:
整個(gè)View樹的結(jié)構(gòu),對(duì)每個(gè)具體View對(duì)象的操作,其實(shí)就是個(gè)遞歸的實(shí)現(xiàn)
11:
mesarue()過程 :? 為整個(gè)View樹計(jì)算實(shí)際的大小,即設(shè)置實(shí)際的高(對(duì)應(yīng)屬性:mMeasuredHeight)和寬(對(duì)應(yīng)屬性:
mMeasureWidth),每個(gè)View的控件的實(shí)際寬高都是由父視圖和本身視圖決定的。
12:
具體的調(diào)用鏈如下:
ViewRoot根對(duì)象地屬性mView(其類型一般為ViewGroup類型)調(diào)用measure()方法去計(jì)算View樹的大小,回調(diào)
View/ViewGroup對(duì)象的onMeasure()方法,該方法實(shí)現(xiàn)的功能如下:
1、設(shè)置本View視圖的最終大小,該功能的實(shí)現(xiàn)通過調(diào)用setMeasuredDimension()方法去設(shè)置實(shí)際的高(對(duì)應(yīng)屬性:
mMeasuredHeight)和寬(對(duì)應(yīng)屬性:mMeasureWidth)?? ;
2 、如果該View對(duì)象是個(gè)ViewGroup類型,需要重寫該onMeasure()方法,對(duì)其子視圖進(jìn)行遍歷的measure()過程。
13:
由ViewRoot對(duì)象的performTraversals()方法調(diào)用draw()方法發(fā)起繪制該View樹,值得注意的是每次發(fā)起繪圖時(shí),并不
會(huì)重新繪制每個(gè)View樹的視圖,而只會(huì)重新繪制那些“需要重繪”的視圖,View類內(nèi)部變量包含了一個(gè)標(biāo)志位DRAWN,當(dāng)該
視圖需要重繪時(shí),就會(huì)為該View添加該標(biāo)志位。
14:
mView.draw()開始繪制,draw()方法實(shí)現(xiàn)的功能如下:
1 、繪制該View的背景
2 、為顯示漸變框做一些準(zhǔn)備操作(見5,大多數(shù)情況下,不需要改漸變框)
3、調(diào)用onDraw()方法繪制視圖本身?? (每個(gè)View都需要重載該方法,ViewGroup不需要實(shí)現(xiàn)該方法)
4、調(diào)用dispatchDraw ()方法繪制子視圖(如果該View類型不為ViewGroup,即不包含子視圖,不需要重載該方法)
值得說明的是,ViewGroup類已經(jīng)為我們重寫了dispatchDraw ()的功能實(shí)現(xiàn),應(yīng)用程序一般不需要重寫該方法,但可以重載父類
函數(shù)實(shí)現(xiàn)具體的功能。? ??[dispatchDraw()方法內(nèi)部會(huì)遍歷每個(gè)子視圖,調(diào)用drawChild()去重新回調(diào)每個(gè)子視圖的draw()方法(注意,這個(gè)
地方“需要重繪”的視圖才會(huì)調(diào)用draw()方法)]
5、繪制滾動(dòng)條
15:
將圖片裁剪為橢圓形:
@Override
protectedvoidonDraw(Canvas?canvas)
{
super.onDraw(canvas);
//將圖片裁剪為橢圓形
//構(gòu)建ShapeDrawable對(duì)象并定義形狀為橢圓
shapeDrawable?=newShapeDrawable(newOvalShape());
//得到畫筆并設(shè)置渲染器
shapeDrawable.getPaint().setShader(bitmapShader);
//設(shè)置顯示區(qū)域
shapeDrawable.setBounds(20,20,BitmapWidth-60,BitmapHeight-60);
//繪制shapeDrawable
shapeDrawable.draw(canvas);
}
16:
顏色選擇器:
publicclassShaderViewextendsView?{
privateShader?mSweepGradient?=null;
privatePaint?mPaint;
publicShaderView(Context?context,?AttributeSet?attrs)?{
super(context,?attrs);
init();
}
privatevoidinit()?{
mPaint?=newPaint(Paint.ANTI_ALIAS_FLAG);
mSweepGradient?=newSweepGradient(400,400,newint[]?{?Color.YELLOW,
Color.RED,?Color.BLUE,?Color.GREEN?},newfloat[]?{0,?.2F,
.6F,?.9F?});
}
@Override
protectedvoidonDraw(Canvas?canvas)?{
super.onDraw(canvas);
mPaint.setShader(mSweepGradient);
canvas.drawCircle(400,400,300,?mPaint);
}
}
17:
Canvas中的各種drawXXX方法定義了圖形的形狀,畫筆中的Shader則定義了圖形的著色、外觀,二者結(jié)合到一起就決定了最終Canvas繪制的被色彩填充的圖形的樣子
18:
漸變效果:
LinearGradient linearGradient = new LinearGradient(100, 100, 500, 500, Color.GREEN, Color.BLUE, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
canvas.drawRect(100, 100, 500, 500, paint);
19:
火花粒子滑動(dòng)效果:
https://github.com/a396901990/SparkScreen
20:
粒子效果:https://github.com/JeasonWong/Particle。
21:? TreeMap排序例子:
MapmSortedOptionList;
private voidsortOptionByCount(List list) {
HashMap map =newHashMap<>();
for(inti =0;i < list.size();i++) {
map.put(list.get(i).count,mOptionViewList.get(i));
}
mSortedOptionList=newTreeMap(map);
mOptionRanked.set(true);
}
22:? Advanced blurring techniques:http://trickyandroid.com/advanced-blurring-techniques/.
23: onDraw實(shí)現(xiàn)自定義view
24: 替換服務(wù)器: request url update - >BFJSONRequest.
25:How to make an ImageView to have rounded corners[http://stackoverflow.com/questions/14473113/bitmap-image-with-rounded-corners-with-stroke]
1:
publicstaticBitmapgetRoundedCornerBitmap(Bitmapbitmap,intpixels) {Bitmapoutput =Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(),Config.ARGB_8888);Canvascanvas =newCanvas(output);finalintcolor =0xff424242;finalPaintpaint =newPaint();finalRectrect =newRect(0,0, bitmap.getWidth(), bitmap.getHeight());finalRectFrectF =newRectF(rect);finalfloatroundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0,0,0,0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(newPorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);returnoutput;
}
26:
setMeasuredDimension :? 設(shè)置view的大小. [照片相框?]
measureChild(getChildAt(0), ...) :? 測(cè)量第一個(gè)子view的大小, 一般用于設(shè)置attach的xml layout的大小 [ 照片相框?], 會(huì)被父layout 覆蓋限制.
27:
獲取動(dòng)態(tài)內(nèi)容view的高度:? 可嘗試onMeasure中.
if(mOptionGp.getVisibility() == View.VISIBLE) {
if(!mBAnimating) {
mOptionViewHeight=mOptionGp.getMeasuredHeight();
}
}
28: View的大小確認(rèn)圖:
29:
setMeasuredDimension: 設(shè)置view的展示相框大小
measureChild(getChildAt(0), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), ...) :? 不受約束測(cè)量子view大小
30:
CenteredImageSpan例子:
public classCenteredImageSpanextendsImageSpan {
// Extra variables used to redefine the Font Metrics when an ImageSpan is added
private intinitialDescent=0;
private intextraSpace=0;
publicCenteredImageSpan(finalDrawable drawable) {
this(drawable,DynamicDrawableSpan.ALIGN_BASELINE);
}
publicCenteredImageSpan(finalDrawable drawable, final intverticalAlignment) {
super(drawable,verticalAlignment);
}
// Method used to redefined the Font Metrics when an ImageSpan is added
@Override
public intgetSize(Paint paint,CharSequence text,
intstart, intend,
Paint.FontMetricsInt fm) {
Drawable d = getCachedDrawable();
Rect rect = d.getBounds();
if(fm !=null) {
// Centers the text with the ImageSpan
if(rect.bottom- (fm.descent- fm.ascent) >=0) {
// Stores the initial descent and computes the margin available
initialDescent= fm.descent;
extraSpace= rect.bottom- (fm.descent- fm.ascent);
}
fm.descent=extraSpace/2+initialDescent;
fm.bottom= fm.descent;
fm.ascent= -rect.bottom+ fm.descent;
fm.top= fm.ascent;
}
returnrect.right;
}
// Redefined locally because it is a private member from DynamicDrawableSpan
privateDrawablegetCachedDrawable() {
WeakReference wr =mDrawableRef;
Drawable d =null;
if(wr !=null)
d = wr.get();
if(d ==null) {
d = getDrawable();
mDrawableRef=newWeakReference<>(d);
}
returnd;
}
privateWeakReferencemDrawableRef;
}
31: shadow陰影style:
4px
4px
#000000
12sp
@color/white
3
3
3
32:
測(cè)量view的大小(目前可不管是否visible or gone):
mOptionGp.measure(MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED));
mOptionGpWidth=mOptionGp.getMeasuredWidth();
33:
圖片大小 電腦實(shí)際像素x :? x? / 2 =? x dip.
34:
HorizontalPagerAdapter為首頁背景視頻
35:
MultipleCameraView:? 所有視頻的容器
CameraVIew:? 單個(gè)視頻View
VRCarmerView, VRMixedCarmerView subclass of cameraview
AbstractVideoHelper :? 播放器功能類
36:
Html實(shí)現(xiàn)圖文混排:
String html ="
";
Html.ImageGetter imgGetter =newHtml.ImageGetter() {
@Override
publicDrawablegetDrawable(String source) {
//TODO Auto-generated method stub
intid = Integer.parseInt(source);
Drawable d = getResources().getDrawable(id);
d.setBounds(0,0,d.getIntrinsicWidth() +10,d.getIntrinsicHeight() +10);
returnd;
}
};
CharSequence charSequence = Html.fromHtml(html,imgGetter, null);
mTitleText.setText(charSequence);
mTitleText.append("? Html實(shí)現(xiàn)圖文混排");
37:
去除混淆:proguard-rules.pro:-dontobfuscate
38:
ViewPager Transformer動(dòng)畫:
39:
GoodsCardController的manageCard一直刷新
PluginLoader. getHomeModules 獲取模塊信息, com.aube.app.module.android.list
loadPluginFile獲取服務(wù)器模塊信息開始處理
40:
GridVideoGroup
41:
定制ViewPager翻滾動(dòng)畫
public voidsetScrollerAnimation(ABaseTransformer animation){
mViewPager.setPageTransformer(true,animation);
}
setScrollerAnimation(newABaseTransformer() {
@Override
protected voidonTransform(View page, floatposition) {
float translationX = position < 0 ? 0f : -page.getWidth() * position;
page.setTranslationX(translationX);
}
});
42:
DLProxyContext為獲取host的context給plugin用. ( PlayerModuleManager的load()).
43:
HOME_DETAIL接口中, Actor和首頁信息區(qū)別: 1)relatedId? ? 2)templateCode
44:
開源資料:
https://github.com/TencentOpen
http://www.open-open.com/lib/view/open1377700292339.html
45:
PlayerController.onDestroy. 播放器退出
StaticApplicationContext.receivedDataSize 流量統(tǒng)計(jì)
AubeStatisticTool
多鏡頭入場(chǎng)邏輯: MultiScreenController.animIn()
CameraCardView: 鏡頭的View.? switchWindowSize切換大小
MultiCameraTransitionHelper: 多鏡頭轉(zhuǎn)換處理邏輯?
視頻View:? VRCardView, VRMixedCardView, MultiCameraCardView, CameraCardView.
46:
IPlayPresenter為插件和Host之間的紐帶.
PlayerProxy只是播放器UI層面的代理.
47:
APP的入口:
LaunchActivity. LaunchApplication.
LaunchActivity. 繼承于StartActivity. 從project(taste)轉(zhuǎn)到app. StartActivity開啟空跳轉(zhuǎn)至PluginMainActivity.
PluginMainActivity為主頁的內(nèi)容容器Activity.......
LaunchApplication現(xiàn)在棄用,用LaunchApplicationLike, 參與到tinker的應(yīng)用生命周期管理,便于補(bǔ)丁升級(jí).
48:
Github: master password: &gh
49:
Create or Import a Native Project:https://developer.android.com/ndk/guides/index.html#native-project
50:
Google例子代碼:https://github.com/googlesamples
Ndk例子代碼:https://github.com/googlesamples/android-ndk。
Google的arch例子:https://github.com/googlesamples/android-architecture.
lua:https://github.com/henkel/lua-android/tree/master/project/jni/lua-5.1.4.
51:
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
52: exoplayer 播放代碼:
private voidpreparePlayer(booleanplayWhenReady) {
if(player==null) {
player=newDemoPlayer(getRendererBuilder());
player.addListener(this);
player.seekTo(playerPosition);//播放進(jìn)度的設(shè)置
playerNeedsPrepare=true;//是否立即播放
}
if(playerNeedsPrepare) {
player.prepare();
playerNeedsPrepare=false;
}
player.setSurface(surfaceView.getHolder().getSurface());
player.setPlayWhenReady(playWhenReady);
}
53:
JNI的具體開發(fā)流程總結(jié)起來分為這么幾步:
(1)在原生java類中聲明native方法。native表明該方法為一個(gè)本地方法,由C/C++實(shí)現(xiàn)。
(2)使用javac命令將帶有聲明native方法的類,編譯成class字節(jié)碼。javac是jdk自帶的一個(gè)命令,一般在javapath/bin(javapath為java安裝目錄)路徑下。
(3)使用javah命令將編譯好的class生成本地C/C++代碼的.h頭文件。同樣,javah也是jdk自帶的一個(gè)命令。
(4)實(shí)現(xiàn).h頭文件中的方法。
(5)將本地代碼編譯成動(dòng)態(tài)庫。注意,不同平臺(tái)的動(dòng)態(tài)庫是不一樣的。
(6)在java工程中引用編譯好的動(dòng)態(tài)庫。
54:
void remove_blanks (char *s)
{
lua_pushstring(s);? /* prepare parameter */
lua_call("remove_blanks");? /* call Lua function */
strcpy(s, lua_getstring(lua_getresult(1)));? /* copy result back to 's' */
}
55:
@Override
protected void onDraw(Canvas canvas) {
Paint paint = mPaint; canvas.drawColor(Color.WHITE); if(MotionEvent.ACTION_MOVE == mAction) {
paint.setColor(Color.RED);
}else if(MotionEvent.ACTION_UP == mAction) {
//移動(dòng)動(dòng)作
//抬起動(dòng)作
paint.setColor(Color.GREEN);
}else if(MotionEvent.ACTION_DOWN == mAction) { //按下動(dòng)作
paint.setColor(Color.BLUE);
}
canvas.drawCircle(mX, mY,10, paint);
setTitle("A = " + mAction + " ["+ mX +","+ mY +"]"); }
@Override
public boolean onTouchEvent(MotionEvent event) {
mAction = event.getAction(); //獲得動(dòng)作mX = event.getX(); //獲得坐標(biāo)mY = event.getY();
Log.v(TAG, "Action = "+ mAction ); Log.v(TAG, "("+mX+","+mY+")"); invalidate();
return true;
}
56:
帶有返回值的跳轉(zhuǎn):
source:
startActivityForResult (intent, GET_CODE);
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == GET_CODE) {
Editable text = (Editable)mResults.getText(); if (resultCode == RESULT_CANCELED) {
text.append("(cancelled)");
} else {
text.append("(okay ");
text.append(Integer.toString(resultCode));
text.append(") ");
if (data != null) {
text.append(data.getAction());
}
}
text.append("\n");
}
}
target:
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v)
{
setResult(RESULT_OK, (new Intent()).setAction("Corky!"));
finish(); }
};
private OnClickListener mVioletListener = new OnClickListener() {
public void onClick(View v)
{
setResult(RESULT_OK, (new Intent()).setAction("Violet!")); finish();
} };
57:
菜單:
public boolean onCreateOptionsMenu(Menu menu)
public boolean onOptionsItemSelected(MenuItem item)
onCreateOptionsMenu()用于在建立菜單時(shí)進(jìn)行設(shè)置,建立時(shí)為每一個(gè)按鈕設(shè)置ID,菜單項(xiàng)被選擇時(shí)調(diào)用onOptionsItemSelected(),通過MenuItem類的getItemId()函數(shù)獲得這個(gè)菜單的ID,繼續(xù)進(jìn)行處理。
菜單類在Android中表示為android.view.Menu類。使用這個(gè)類可以進(jìn)行一些更 為細(xì)節(jié)的設(shè)置和操作。
abstract MenuItem add(int groupId, int itemId, int order, CharSequence title) abstract MenuItem add(int groupId, int itemId, int order, int titleRes)
add()的第1、2個(gè)參數(shù)是整數(shù)值,分別代表按鈕項(xiàng)的組ID和選項(xiàng)ID,第3個(gè)參 數(shù)用于設(shè)置按鈕上的文件。
58:
在Android程序中,當(dāng)某一個(gè)活動(dòng)啟動(dòng)之后可能需要使用背景透明的效果.
AndroidManifest.xml中的定義如下所示:
這兩個(gè)程序使用的都是窗口透明的效果,TranslucentActivity獲得的效果是背 景普通的透明,TranslucentBlurActivity獲得的效果是背景模糊的透明。它們的樣 式被設(shè)置成了Translucent,這是一個(gè)用于描述背景透明的自定義樣式,在styles.xml中定義。
@drawable/translucent_background
true
#fff
TranslucentBlurActivity之所以能夠獲得背景模糊的效果,是因?yàn)樵谠创a中 進(jìn)行了進(jìn)一步的設(shè)置.
public class TranslucentBlurActivity extends Activity {
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow(). setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND); setContentView(R.layout.translucent_background);
} }
設(shè)置模糊效果是通過窗口管理器(WindowManager)設(shè)置參數(shù)來完成的,這 種設(shè)置只有在背景設(shè)置為透明后才能顯示效果。
59:
60:
文本切換器(TextSwitcher)是Android中一個(gè)集成化較高的控件,可以在多 個(gè)文本之間切換,還可以設(shè)置動(dòng)畫的效果。
圖像切換器(ImageSwitcher)和文本切換器類似,但是顯示的內(nèi)容是多個(gè)圖片中 的一個(gè)。
61:
在GUI系統(tǒng)中,圖形API是比較底層的接口。Android系統(tǒng)的圖形API包括2D和3D兩部分:2D部分使用android.graphics類,也作為上層控件的構(gòu)建基礎(chǔ);3D部分使用OpenGL作為標(biāo)準(zhǔn)接口。
62:
在使用2D的圖形API方面,步驟通常如下所示:
1、擴(kuò)展實(shí)現(xiàn)android.view.View類。
2、實(shí)現(xiàn)View的OnDraw()函數(shù),在其中使用Canvas的方法進(jìn)行繪制。 使用2D的圖形API的場(chǎng)合,自定義實(shí)現(xiàn)的View類型作為下層的繪制和上層的GUI系統(tǒng)中間層。
android.graphics.drawable包是Android中一個(gè)繪制相關(guān)的包,表示一些可以
被繪制的東西。在Android中Drawable的??義就是可以僅僅是為了顯示來使用的, 與View的主要區(qū)別就在于Drawable不能從用戶處獲得事件的反饋。
63:
private static class SampleView extends View { private Bitmap mBitmap;
private Bitmap mBitmap2;
private Bitmap mBitmap3;
private Shader mShader;
public SampleView(Context context) {
super(context);
setFocusable(true);
InputStream is = context.getResources().
openRawResource(R.drawable.app_sample_code); mBitmap = BitmapFactory.decodeStream(is); //解碼位圖文件到Bitmap
mBitmap2 = mBitmap.extractAlpha(); //提取位圖的透明通道
//創(chuàng)建一個(gè)位圖
mBitmap3 = Bitmap.createBitmap(200, 200, Bitmap.Config.ALPHA_8); drawIntoBitmap(mBitmap3); //調(diào) 用 自 己 實(shí) 現(xiàn) 的
drawIntoBitmap()
mShader = new LinearGradient(0, 0, 100, 70, new int[] {
Color.RED, Color.GREEN, Color.BLUE }, null, Shader.TileMode.MIRROR);
}
private static void drawIntoBitmap(Bitmap bm) {
float x = bm.getWidth();
float y = bm.getHeight();
Canvas c = new Canvas(bm);
Paint p = new Paint();
p.setAntiAlias(true);
p.setAlpha(0x80);
c.drawCircle(x/2, y/2, x/2, p);
p.setAlpha(0x30);
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); p.setTextSize(60);
p.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fm = p.getFontMetrics(); c.drawText("Alpha", x/2, (y-fm.ascent)/2, p);
}
@Override protected void onDraw(Canvas canvas) {
筆)
} }
canvas.drawColor(Color.WHITE);
Paint p = new Paint();
float y = 10;
p.setColor(Color.RED); canvas.drawBitmap(mBitmap, 10, y, p); y += mBitmap.getHeight() + 10; canvas.drawBitmap(mBitmap2, 10, y, p);
y += mBitmap2.getHeight() + 10; p.setShader(mShader); canvas.drawBitmap(mBitmap3, 10, y, p);
第1個(gè)圖是直接對(duì)原始的圖像進(jìn)行了繪制;第2個(gè)圖是在原始圖像的基礎(chǔ)上 抽取了透明通道,所以繪制時(shí)畫筆(Paint)的顏色起到了作用;第3個(gè)圖是調(diào)用drawIntoBitmap()繪制了一個(gè)具有漸變顏色的圓,并附加了文字。
64:
對(duì)齊操作不僅有水平和豎直上的對(duì)齊問題,甚至可以讓文本在 曲線的路徑上實(shí)現(xiàn)對(duì)齊:
文本的對(duì)其操作主要通過以下兩點(diǎn)來完成:
1.通過畫筆(Paint)的setTextAlign()函數(shù)設(shè)置繪制過程中的對(duì)齊方式。2.drawText(),drawPosText(),drawTextOnPath()幾個(gè)函數(shù)表示了文本的幾
種繪制方式。drawText()在指定的坐標(biāo)上進(jìn)行文本繪制;drawPosText()在一個(gè)表 示為位置信息的數(shù)組上進(jìn)行文本繪制(其中的float[] pos參數(shù)表示交替的x和y表示的坐標(biāo));drawTextOnPath()表示在一個(gè)路徑(Path)進(jìn)行文本繪制。
65:
在使用3D的圖形API方面,主要的步驟通常如下所示:
1.擴(kuò)展實(shí)現(xiàn)android.view.GLSurfaceView類。
2.擴(kuò)展實(shí)現(xiàn)android.opengl.GLSurfaceView中的Renderer(渲染器)。3.實(shí)現(xiàn)GLSurfaceView::Renderer中的onDrawFrame()等函數(shù)。
66:
OpenGL本身帶回動(dòng)畫繪制的功能,這里使用的glRotatef()是進(jìn)行旋轉(zhuǎn)。mTriangle是一個(gè)三角形,在onDrawFrame()根據(jù)OpenGL的上下文進(jìn)行動(dòng)畫的繪 制。
67:
class a implemens OnKeyLisnter {
@Override
public void onKey(View v,? KeyCode keycode, KeyEvent event ) {
switch(event.getAction() {
String msg = Class.this.getText().toString();
if(msg.matches("\\w+@\\w+\\.\\w+")) {? ? ? ? //判斷是否是email地址.
68:
繪圖View中,? onTouch中, onDown創(chuàng)建搜集點(diǎn)列表,并添加第一個(gè)點(diǎn), 在onUp和onMove時(shí)候添加點(diǎn)并postInvalidate;
在onDraw中, 每個(gè)點(diǎn)canvas.DrawLine.
69:
ListActivity的使用:
70:
AutoCompleteTextView自動(dòng)補(bǔ)完textview.
隱時(shí)抽屜組件: SlidingDrawer.
樹型組件:ExpandableListView
71:
自定義Seekbar的view:
@Override
protectedvoidonDraw(Canvas canvas){
intwidth=getWidth();
intheight=getHeight();
intlineHeight=height/4;
/*畫背景條*/
mPaint.setColor(mNormalColor);
RectF rectF=newRectF(0,(height-lineHeight)/2,width,(height+lineHeight)/2);
canvas.drawRoundRect(rectF,lineHeight/2,lineHeight/2,mPaint);
/*畫緩沖條*/
mPaint.setColor(mBufferColor);
if(mBuffer>=99){
canvas.drawRoundRect(rectF,lineHeight/2,lineHeight/2,mPaint);
}else{
canvas.drawRect(newRect(lineHeight/2,(height-lineHeight)/2,width*mBuffer/100,(height+lineHeight)/2),mPaint);
}
/*畫已播放條 */
mPaint.setColor(mPlayedColor);
canvas.drawRoundRect(newRectF(0,(height-lineHeight)/2,width*mProgress/100,(height+lineHeight)/2),lineHeight/2,lineHeight/2,mPaint);
if(mEnabled){
/*畫highlight點(diǎn)*/
if(mHighlights!=null&&mVideoLength>0){
for(Integer i:mHighlights){
intpercent=(int)(i.intValue()*100/mVideoLength);
intpoint=(int)(width*i.intValue()/mVideoLength);
mPaint.setColor(percent>mProgress?mHighlightColorGray:mHighlightColorYellow);
canvas.drawOval(newRectF(point-lineHeight/2,(height-lineHeight)/2,point+lineHeight/2,(height+lineHeight)/2),mPaint);
}
}
}
/*畫圓點(diǎn)*/
intprogress=width*mProgress/100;
intstartX=progress-height/2;
intendX=progress+height/2;
if(startX<0){
startX=0;
endX=height;
}
if(endX>width){
endX=width;
startX=width-height;
}
mPaint.setColor(mPlayedColor);
canvas.drawOval(newRectF(startX,0,endX,height),mPaint);
}
72:
View的interface , interface 1個(gè), 自己帶接口3個(gè)(包括供給外部用的),? 外部一個(gè).
73:使用SharedPreference保存數(shù)據(jù):
SharedPreferences share = super.getSharedPreferences(FILENAME, Activity.MODE_PRIVATE);
SharedPreferences.Edit edit = share.edit();
edit.putString("author", "Liss");
edit.putInt("age", 30);
edit.commit();
74:
創(chuàng)建文件IO流:
File file =new File (Environment.getExternalStorageDirectory.toString() + File.Separator + DIRNAME + File.Separator + FILENAME);
讀取文件流:
this.msg = new StrigBuffer();
try {
scan = new Scanner(new FileInputStream(file));
while(scan.hasNext()) {
this.msg.append(scan.next() + "\n";
} CatchException (Exception e) {
} finally {
if(scan != null) {
scan.close();
}
讀取資源文件信息:
InputStream input = getResources().openRawResources(R.raw.book);
75: DOM文件信息操作:
寫入:
讀?。?/p>
76:
JSON更為方便.
ContentProvider應(yīng)用程序間使用數(shù)據(jù),有點(diǎn)像web url.
77:
standard: 標(biāo)準(zhǔn)的,會(huì)重復(fù)創(chuàng)建棧頂活動(dòng)
SignleTop:不會(huì)重復(fù)創(chuàng)建已經(jīng)在棧頂?shù)幕顒?dòng).
SingleTask: 解決重復(fù)創(chuàng)建棧頂活動(dòng)的問題,如果已經(jīng)有,則出棧之前所有的活動(dòng)
SingleInstance啟動(dòng)新的返回棧來管理活動(dòng),用于應(yīng)用程序間共享活動(dòng)實(shí)例
78:
隨時(shí)隨地退出程序:
public class ActivityCollector {
public static List activities = new ArrayList();
public static void addActivity(Activity activity) { activities.add(activity);
}
public static void removeActivity(Activity activity) { activities.remove(activity);
}
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) { activity.finish();
} }
}
}
使用:
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this); }
從此以后,不管你想在什么地方退出程序,只需要調(diào)用 ActivityCollector.finishAll() 方法就可以了。例如在 ThirdActivity 界面想通過點(diǎn)擊按鈕直接退出程序,只需將代碼改 成如下所示:
...
@Override
public void onClick(View v) {
ActivityCollector.finishAll(); }
...
79:
每次在 getView()方法中還是會(huì)調(diào)用 View 的 findViewById()方法來獲取一次控件的實(shí) 例。我們可以借助一個(gè) ViewHolder 來對(duì)這部分性能進(jìn)行優(yōu)化:
public class FruitAdapter extends ArrayAdapter { ??
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position); View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
viewHolder = new ViewHolder();
viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image); viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name); view.setTag(viewHolder); // 將ViewHolder存儲(chǔ)在View中
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag(); // 重新獲取ViewHolder
} viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName());
return view;
}
class ViewHolder {
ImageView fruitImage;
TextView fruitName;
}
}
80:
動(dòng)態(tài)添加Fragment:
AnotherRightFragment fragment = new AnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager. beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.addToBackStack(null); ///在Fragment中模擬返回棧, 按返回退出Fragment
transaction.commit();
創(chuàng)建待添加的碎片實(shí)例。
獲取到 FragmentManager,在活動(dòng)中可以直接調(diào)用 getFragmentManager()
方法得到。
開啟一個(gè)事務(wù),通過調(diào)用 beginTransaction()方法開啟。
向容器內(nèi)加入Fragment,一般使用 replace()方法實(shí)現(xiàn),需要傳入容器的 id 和待添加的
碎片實(shí)例。
提交事務(wù),調(diào)用 commit()方法來完成
81:
Fragment與Activity通信:
FragmentManager 提供了一個(gè)類似于 findViewById()的方法,專門用于從布局文件中獲取碎片的實(shí)例,代碼如下所示:
RightFragment rightFragment = (RightFragment) getFragmentManager() .findFragmentById(R.id.right_fragment);
調(diào)用 FragmentManager 的 findFragmentById()方法,可以在活動(dòng)中得到相應(yīng)碎片 的實(shí)例,然后就能輕松地調(diào)用碎片里的方法了。
相反, Fragment直接通過getActivity獲取activity實(shí)例.
82:
Fragment同樣擁有activity的回調(diào)方法, 還有自己獨(dú)特需求的方法:
onAttach() 當(dāng)碎片和活動(dòng)建立關(guān)聯(lián)的時(shí)候調(diào)用。
onCreateView() 為碎片創(chuàng)建視圖(加載布局)時(shí)調(diào)用。
onActivityCreated() 確保與碎片相關(guān)聯(lián)的活動(dòng)一定已經(jīng)創(chuàng)建完畢的時(shí)候調(diào)用。
onDestroyView() 當(dāng)與碎片關(guān)聯(lián)的視圖被移除的時(shí)候調(diào)用。
onDetach() 當(dāng)碎片和活動(dòng)解除關(guān)聯(lián)的時(shí)候調(diào)用。
83:
localBroadcastReceiver用于在應(yīng)用程序內(nèi)通信, 它不接受外部應(yīng)用程序的廣播,也不發(fā)送給外部應(yīng)用程序.
84:
SQLite存儲(chǔ)數(shù)據(jù):
Android 為了讓我們能夠更加方便地管理數(shù)據(jù)庫,專門提供了一個(gè) SQLiteOpenHelper 幫助類,借助這個(gè)類就可以非常簡單地對(duì)數(shù)據(jù)庫進(jìn)行創(chuàng)建和升級(jí).
85:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table book (" + "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, " + "name text)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context; }
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); }
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}
可以看到,我們把建表語句定義成了一個(gè)字符串常量,然后在 onCreate()方法中又調(diào) 用了 SQLiteDatabase 的 execSQL()方法去執(zhí)行這條建表語句,并彈出一個(gè) Toast 提示創(chuàng) 建成功,這樣就可以保證在數(shù)據(jù)庫創(chuàng)建完成的同時(shí)還能成功創(chuàng)建 Book 表。
86:
Contentprovider:
另一個(gè)程序跨進(jìn)程訪問:getContentProvider和Uri.parse來處理.
87:
打開相冊(cè):
@Override
public void onClick(View v) {
// 創(chuàng)建File對(duì)象,用于存儲(chǔ)選擇的照片
File outputImage = new File(Environment. getExternalStorageDirectory(), "output_image.jpg");
try {
if (outputImage.exists()) {
outputImage.delete(); }
outputImage.createNewFile(); } catch (IOException e) {
e.printStackTrace(); }
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.intent.action. GET_CONTENT"); intent.setType("image/*");
intent.putExtra("crop", true);
intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CROP_PHOTO);
}
}
}
88:
打開相機(jī):
public void onClick(View v) {
// 創(chuàng)建File對(duì)象,用于存儲(chǔ)拍照后的圖片
File outputImage = new File(Environment. getExternalStorageDirectory(), "tempImage.jpg");
} });
}
try {
if (outputImage.exists()) {
outputImage.delete(); }
outputImage.createNewFile(); } catch (IOException e) {
e.printStackTrace(); }
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.media.action. IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, TAKE_PHOTO); // 啟動(dòng)相機(jī)程序
}
}
89:
相機(jī)返回, 再裁剪,再顯示:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CROP_PHOTO); // 啟動(dòng)裁剪程序
}
break;
case CROP_PHOTO:
if (resultCode == RESULT_OK) {
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap); // 將裁剪后的照片顯示出來
} catch (FileNotFoundException e) { e.printStackTrace();
} }
break; default:
break;
}
90:
91:
ListView:
92:
android線程間若需要線程池, 可以用ExecutorService.
privateExecutorService executorService = Executors.newFixedThreadPool(5);
// 引入線程池來管理多線程
privatevoidloadImage3(finalString url,finalintid) {
executorService.submit(newRunnable() {
publicvoidrun() {
}
93:listview優(yōu)化:
異步加載圖片基本思想:
1.? ?? ?先從內(nèi)存緩存中獲取圖片顯示(內(nèi)存緩沖)
2.? ?? ?獲取不到的話從SD卡里獲?。⊿D卡緩沖)
3.? ?? ?都獲取不到的話從網(wǎng)絡(luò)下載圖片并保存到SD卡同時(shí)加入內(nèi)存并顯示(視情況看是否要顯示)
94:
listview優(yōu)化:
先從內(nèi)存中加載,沒有則開啟線程從SD卡或網(wǎng)絡(luò)中獲取,這里注意從SD卡獲取圖片是放在子線程里執(zhí)行的,否則快速滑屏的話會(huì)不夠流暢,這是優(yōu)化一。于此同時(shí),在adapter里有個(gè)busy變量,表示listview是否處于滑動(dòng)狀態(tài),如果是滑動(dòng)狀態(tài)則僅從內(nèi)存中獲取圖片,沒有的話無需再開啟線程去外存或網(wǎng)絡(luò)獲取圖片,這是優(yōu)化二。ImageLoader里的線程使用了線程池,從而避免了過多線程頻繁創(chuàng)建和銷毀,有的童鞋每次總是new一個(gè)線程去執(zhí)行這是非常不可取的,好一點(diǎn)的用的AsyncTask類,其實(shí)內(nèi)部也是用到了線程池。在從網(wǎng)絡(luò)獲取圖片時(shí),先是將其保存到sd卡,然后再加載到內(nèi)存,這么做的好處是在加載到內(nèi)存時(shí)可以做個(gè)壓縮處理,以減少圖片所占內(nèi)存,這是優(yōu)化三。
95:
listview優(yōu)化中內(nèi)存優(yōu)化部分:
首先限制內(nèi)存圖片緩沖的堆內(nèi)存大小,每次有圖片往緩存里加時(shí)判斷是否超過限制大小,超過的話就從中取出最少使用的圖片并將其移除,當(dāng)然這里如果不采用這種方式,換做軟引用也是可行的,二者目的皆是最大程度的利用已存在于內(nèi)存中的圖片緩存,避免重復(fù)制造垃圾增加GC負(fù)擔(dān),OOM溢出往往皆因內(nèi)存瞬時(shí)大量增加而垃圾回收不及時(shí)造成的。只不過二者區(qū)別在于LinkedHashMap里的圖片緩存在沒有移除出去之前是不會(huì)被GC回收的,而SoftReference里的圖片緩存在沒有其他引用保存時(shí)隨時(shí)都會(huì)被GC回收。所以在使用LinkedHashMap這種LRU算法緩存更有利于圖片的有效命中,當(dāng)然二者配合使用的話效果更佳,即從LinkedHashMap里移除出的緩存放到SoftReference里,這就是內(nèi)存的二級(jí)緩存
96:
Fragment生命周期:
97:
fragment有一些新的狀態(tài)。
onAttached() —— 當(dāng)fragment被加入到activity時(shí)調(diào)用(在這個(gè)方法中可以獲得所在的activity)。
onCreateView() —— 當(dāng)activity要得到fragment的layout時(shí),調(diào)用此方法,fragment在其中創(chuàng)建自己的layout(界面)。
onActivityCreated() —— 當(dāng)activity的onCreated()方法返回后調(diào)用此方法
onDestroyView() —— 當(dāng)fragment中的視圖被移除的時(shí)候,調(diào)用這個(gè)方法。
onDetach() —— 當(dāng)fragment和activity分離的時(shí)候,調(diào)用這個(gè)方法。
98:
將Fragment添加到返回棧中:
transaction.addToBackStack(null);
99:
Activity的狀態(tài)注意點(diǎn):
(1)onCreat是activity正在被創(chuàng)建,也就是說此時(shí)的UI操作不會(huì)更新UI,比如setText操作,所以此時(shí)在子線程調(diào)用setText不會(huì)報(bào)線程錯(cuò)誤。詳解可見Android子線程更新View的探索,在這個(gè)方法內(nèi)我們可以做一些初始化工作。
(2)onRestart需要注意的是:activity正在重新啟動(dòng),一般情況下,activity從不可見狀態(tài)到可見狀態(tài),onRestart才會(huì)被調(diào)用,但是一定要注意的是一般來說這是用戶行為導(dǎo)致activity不可見的時(shí)候,此時(shí)變?yōu)榭梢姷臅r(shí)候才會(huì)調(diào)用onRestart,這里所說的用戶行為就是用戶按home鍵,或者進(jìn)入“新”的activity。這樣的操作會(huì)使activity先執(zhí)行onPause,后執(zhí)行onStop,這樣回到這個(gè)activity會(huì)調(diào)用onRestart。為什么我這里強(qiáng)調(diào)說用戶行為導(dǎo)致的不可見狀態(tài),等下我會(huì)說。。。。
(3)onStart的時(shí)候,activity才可見,但是沒有出現(xiàn)在前臺(tái),無法與用戶交互
(4)onResume的時(shí)候,activity已經(jīng)可見,并且出現(xiàn)在前臺(tái)開始活動(dòng),與onStart相比,activity都已經(jīng)可見,但是onStart的時(shí)候activity還在后臺(tái),onResume才顯示在前臺(tái)
(5)onPause主要注意的是:此時(shí)的activity正在被停止,接下來馬上調(diào)用onStop。特殊情況下快速回到該activity,onStop不會(huì)執(zhí)行,會(huì)去執(zhí)行onResume。
一般在這個(gè)生命周期內(nèi)做存儲(chǔ)數(shù)據(jù)、停止動(dòng)畫工作,但不能太耗時(shí)。
為什么特殊強(qiáng)調(diào)呢,因?yàn)樵揳ctivity的onPause執(zhí)行完了,才回去執(zhí)行新的activity的onResume,一旦耗時(shí),必然會(huì)拖慢新的activity的顯示。
(6)onStop:此時(shí)的activity即將停止。在這里可以做稍微重量級(jí)的操作,同樣也不能耗時(shí)。
(7)onDestroy:此時(shí)的activity即將被回收,在這里會(huì)做一些回收工作和最終資源釋放。
100:
異常情況下activity被殺死,而后被重新創(chuàng)建的情況:
當(dāng)系統(tǒng)停止activity時(shí),它會(huì)調(diào)用onSaveInstanceState()(過程1),如果activity被銷毀了,但是需要?jiǎng)?chuàng)建同樣的實(shí)例,系統(tǒng)會(huì)把過程1中的狀態(tài)數(shù)據(jù)傳給onCreate()和onRestoreInstanceState(),所以我們要在onSaveInstanceState()內(nèi)做保存參數(shù)的動(dòng)作,在onRestoreInstanceState()做獲取參數(shù)的動(dòng)作。
101:
(1)onAttach:onAttach()回調(diào)將在Fragment與其Activity關(guān)聯(lián)之后調(diào)用。需要使用Activity的引用或者使用Activity作為其他操作的上下文,將在此回調(diào)方法中實(shí)現(xiàn)。
需要注意的是:將Fragment附加到Activity以后,就無法再次調(diào)用setArguments()——除了在最開始,無法向初始化參數(shù)添加內(nèi)容。
(2)onCreate(Bundle savedInstanceState):此時(shí)的Fragment的onCreat回調(diào)時(shí),該fragmet還沒有獲得Activity的onCreate()已完成的通知,所以不能將依賴于Activity視圖層次結(jié)構(gòu)存在性的代碼放入此回調(diào)方法中。在onCreate()回調(diào)方法中,我們應(yīng)該盡量避免耗時(shí)操作。此時(shí)的bundle就可以獲取到activity傳來的參數(shù)
publicstaticMyFragmentnewInstance(int index){
MyFragment mf =newMyFragment();
Bundle args =newBundle();
args.putInt("index",index);
mf.setArguments(args);returnmf;
}
@OverridepublicvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
Bundle args = getArguments();if(args !=null) {
mLabel = args.getCharSequence("label", mLabel);
}
}
(3)onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState): 其中的Bundle為狀態(tài)包與上面的bundle不一樣。
注意的是:不要將視圖層次結(jié)構(gòu)附加到傳入的ViewGroup父元素中,該關(guān)聯(lián)會(huì)自動(dòng)完成。如果在此回調(diào)中將碎片的視圖層次結(jié)構(gòu)附加到父元素,很可能會(huì)出現(xiàn)異常。
這句話什么意思呢?就是不要把初始化的view視圖主動(dòng)添加到container里面,以為這會(huì)系統(tǒng)自帶,所以inflate函數(shù)的第三個(gè)參數(shù)必須填false,而且不能出現(xiàn)container.addView(v)的操作。
View v = inflater.inflate(R.layout.hello_world,container,false);
(4)onActivityCreated:onActivityCreated()回調(diào)會(huì)在Activity完成其onCreate()回調(diào)之后調(diào)用。在調(diào)用onActivityCreated()之前,Activity的視圖層次結(jié)構(gòu)已經(jīng)準(zhǔn)備好了,這是在用戶看到用戶界面之前你可對(duì)用戶界面執(zhí)行的最后調(diào)整的地方。
強(qiáng)調(diào)的point:如果Activity和她的Fragment是從保存的狀態(tài)重新創(chuàng)建的,此回調(diào)尤其重要,也可以在這里確保此Activity的其他所有Fragment已經(jīng)附加到該Activity中了
(5)Fragment與Activity相同生命周期調(diào)用:接下來的onStart()\onResume()\onPause()\onStop()回調(diào)方法將和Activity的回調(diào)方法進(jìn)行綁定,也就是說與Activity中對(duì)應(yīng)的生命周期相同,因此不做過多介紹。
(6)onDestroyView:該回調(diào)方法在視圖層次結(jié)構(gòu)與Fragment分離之后調(diào)用。
(7)onDestroy:不再使用Fragment時(shí)調(diào)用。(備注:Fragment仍然附加到Activity并任然可以找到,但是不能執(zhí)行其他操作)
(8)onDetach:Fragme生命周期最后回調(diào)函數(shù),調(diào)用后,F(xiàn)ragment不再與Activity綁定,釋放資源。
102: