欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

android%p,androidphone停止運行

手機調(diào)試Android程序出異常時不打印堆棧信息

打印堆棧是調(diào)試的常用方法,一般在系統(tǒng)異常時,我們可以將異常情況下的堆棧打印出來,這樣十分方便錯誤查找。實際上還有另外一個非常有用的功能:分析代碼的行為。android代碼太過龐大復(fù)雜了,完全的靜態(tài)分析經(jīng)常是無從下手,因此通過打印堆棧的動態(tài)分析也十分必要。

成都創(chuàng)新互聯(lián)公司是工信部頒發(fā)資質(zhì)IDC服務(wù)器商,為用戶提供優(yōu)質(zhì)的德陽服務(wù)器托管服務(wù)

Android打印堆棧的方法,簡單歸類一下

1. zygote的堆棧dump

實際上這個可以同時dump java線程及native線程的堆棧,對于java線程,java堆棧和native堆棧都可以得到。

使用方法很簡單,直接在adb shell或串口中輸入:

[plain] view plaincopy

kill -3 pid

輸出的trace會保存在 /data/anr/traces.txt文件中。這個需要注意,如果沒有 /data/anr/這個目錄或/data/anr/traces.txt這個文件,需要手工創(chuàng)建一下,并設(shè)置好讀寫權(quán)限。

如果需要在代碼中,更容易控制堆棧的輸出時機,可以用以下命令獲取zygote的core dump:

[java] view plaincopy

Process.sendSignal(pid, Process.SIGNAL_QUIT);

原理和命令行是一樣的。

不過需要注意兩點:

adb shell可能會沒有權(quán)限,需要root。

android 4.2中關(guān)閉了native thread的堆棧打印,詳見 dalvik/vm/Thread.cpp的dumpNativeThread方法:

[cpp] view plaincopy

dvmPrintDebugMessage(target,

"\"%s\" sysTid=%d nice=%d sched=%d/%d cgrp=%s\n",

name, tid, getpriority(PRIO_PROCESS, tid),

schedStats.policy, schedStats.priority, schedStats.group);

dumpSchedStat(target, tid);

// Temporarily disabled collecting native stacks from non-Dalvik

// threads because sometimes they misbehave.

//dvmDumpNativeStack(target, tid);

Native堆棧的打印被關(guān)掉了!不過對于大多數(shù)情況,可以直接將這個注釋打開。

2. debuggerd的堆棧dump

debuggerd是android的一個daemon進程,負責在進程異常出錯時,將進程的運行時信息dump出來供分析。debuggerd生 成的coredump數(shù)據(jù)是以文本形式呈現(xiàn),被保存在 /data/tombstone/ 目錄下(名字取的也很形象,tombstone是墓碑的意思),共可保存10個文件,當超過10個時,會覆蓋重寫最早生成的文件。從4.2版本開 始,debuggerd同時也是一個實用工具:可以在不中斷進程執(zhí)行的情況下打印當前進程的native堆棧。使用方法是:

[plain] view plaincopy

debuggerd -b pid

這可以協(xié)助我們分析進程執(zhí)行行為,但最最有用的地方是:它可以非常簡單的定位到native進程中鎖死或錯誤邏輯引起的死循環(huán)的代碼位置。

3. java代碼中打印堆棧

Java代碼打印堆棧比較簡單, 堆棧信息獲取和輸出,都可以通過Throwable類的方法實現(xiàn)。目前通用的做法是在java進程出現(xiàn)需要注意的異常時,打印堆棧,然后再決定退出或挽救。通常的方法是使用exception的printStackTrace()方法:

[java] view plaincopy

try {

...

} catch (RemoteException e) {

e.printStackTrace();

...

}

當然也可以只打印堆棧不退出,這樣就比較方便分析代碼的動態(tài)運行情況。Java代碼中插入堆棧打印的方法如下:

[java] view plaincopy

Log.d(TAG,Log.getStackTraceString(new Throwable()));

4. C++代碼中打印堆棧

C++也是支持異常處理的,異常處理庫中,已經(jīng)包含了獲取backtrace的接口,Android也是利用這個接口來打印堆棧信息的。在Android的C++中,已經(jīng)集成了一個工具類CallStack,在libutils.so中。使用方法:

[cpp] view plaincopy

#include utils/CallStack.h

...

CallStack stack;

stack.update();

stack.dump();

使用方式比較簡單。目前Andoid4.2版本已經(jīng)將相關(guān)信息解析的很到位,符號表查找,demangle,偏移位置校正都做好了。

[plain] view plaincopy

5. C代碼中打印堆棧

C代碼,尤其是底層C庫,想要看到調(diào)用的堆棧信息,還是比較麻煩的。 CallStack肯定是不能用,一是因為其實C++寫的,需要重新封裝才能在C中使用,二是底層庫反調(diào)上層庫的函數(shù),會造成鏈接器循環(huán)依賴而無法鏈接。 不過也不是沒有辦法,可以通過android工具類CallStack實現(xiàn)中使用的unwind調(diào)用及符號解析函數(shù)來處理。

這里需要注意的是,為解決鏈接問題,最好使用dlopen方式,查找需要用到的接口再直接調(diào)用,這樣會比較簡單。如下為相關(guān)的實現(xiàn)代碼,只需要在要 打印的文件中插入此部分代碼,然后調(diào)用getCallStack()即可,無需包含太多的頭文件和修改Android.mk文件:

[cpp] view plaincopy

#define MAX_DEPTH 31

#define MAX_BACKTRACE_LINE_LENGTH 800

#define PATH "/system/lib/libcorkscrew.so"

typedef ssize_t (*unwindFn)(backtrace_frame_t*, size_t, size_t);

typedef void (*unwindSymbFn)(const backtrace_frame_t*, size_t, backtrace_symbol_t*);

typedef void (*unwindSymbFreeFn)(backtrace_symbol_t*, size_t);

static void *gHandle = NULL;

static int getCallStack(void){

ssize_t i = 0;

ssize_t result = 0;

ssize_t count;

backtrace_frame_t mStack[MAX_DEPTH];

backtrace_symbol_t symbols[MAX_DEPTH];

unwindFn unwind_backtrace = NULL;

unwindSymbFn get_backtrace_symbols = NULL;

unwindSymbFreeFn free_backtrace_symbols = NULL;

// open the so.

if(gHandle == NULL) gHandle = dlopen(PATH, RTLD_NOW);

// get the interface for unwind and symbol analyse

if(gHandle != NULL) unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace");

if(gHandle != NULL) get_backtrace_symbols = (unwindSymbFn)dlsym(gHandle, "get_backtrace_symbols");

if(gHandle != NULL) free_backtrace_symbols = (unwindSymbFreeFn)dlsym(gHandle, "free_backtrace_symbols");

if(!gHandle ||!unwind_backtrace ||!get_backtrace_symbols || !free_backtrace_symbols ){

ALOGE("Error! cannot get unwind info: handle:%p %p %p %p",

gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols );

return result;

}

count= unwind_backtrace(mStack, 1, MAX_DEPTH);

get_backtrace_symbols(mStack, count, symbols);

for (i = 0; i count; i++) {

char line[MAX_BACKTRACE_LINE_LENGTH];

const char* mapName = symbols[i].map_name ? symbols[i].map_name : "unknown";

const char* symbolName =symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name;

size_t fieldWidth = (MAX_BACKTRACE_LINE_LENGTH - 80) / 2;

if (symbolName) {

uint32_t pc_offset = symbols[i].relative_pc - symbols[i].relative_symbol_addr;

if (pc_offset) {

snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s+%u)",

i, symbols[i].relative_pc, fieldWidth, mapName,

fieldWidth, symbolName, pc_offset);

} else {

snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s)",

i, symbols[i].relative_pc, fieldWidth, mapName,

fieldWidth, symbolName);

}

} else {

snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s",

i, symbols[i].relative_pc, fieldWidth, mapName);

}

ALOGD("%s", line);

}

free_backtrace_symbols(symbols, count);

return result;

}

對sched_policy.c的堆棧調(diào)用分析如下,注意具體是否要打印,在哪里打印,還可以通過pid、uid、property等來控制一下,這樣就不會被淹死在trace的汪洋大海中。

[plain] view plaincopy

D/SchedPolicy( 1350): #00 pc 0000676c /system/lib/libcutils.so

D/SchedPolicy( 1350): #01 pc 00006b3a /system/lib/libcutils.so (set_sched_policy+49)

D/SchedPolicy( 1350): #02 pc 00010e82 /system/lib/libutils.so (androidSetThreadPriority+61)

D/SchedPolicy( 1350): #03 pc 00068104 /system/lib/libandroid_runtime.so (android_os_Process_setThreadPriority(_JNIEnv*, _jobject*, int, int)+7)

D/SchedPolicy( 1350): #04 pc 0001e510 /system/lib/libdvm.so (dvmPlatformInvoke+112)

D/SchedPolicy( 1350): #05 pc 0004d6aa /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+417)

D/SchedPolicy( 1350): #06 pc 00027920 /system/lib/libdvm.so

D/SchedPolicy( 1350): #07 pc 0002b7fc /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)

D/SchedPolicy( 1350): #08 pc 00060c30 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+271)

D/SchedPolicy( 1350): #09 pc 0004cd34 /system/lib/libdvm.so

D/SchedPolicy( 1350): #10 pc 00049382 /system/lib/libandroid_runtime.so

D/SchedPolicy( 1350): #11 pc 00065e52 /system/lib/libandroid_runtime.so

D/SchedPolicy( 1350): #12 pc 0001435e /system/lib/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const, android::Parcel*, unsigned int)+57)

D/SchedPolicy( 1350): #13 pc 00016f5a /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+513)

D/SchedPolicy( 1350): #14 pc 00017380 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+183)

D/SchedPolicy( 1350): #15 pc 0001b160 /system/lib/libbinder.so

D/SchedPolicy( 1350): #16 pc 00011264 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+111)

D/SchedPolicy( 1350): #17 pc 000469bc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+63)

D/SchedPolicy( 1350): #18 pc 00010dca /system/lib/libutils.so

D/SchedPolicy( 1350): #19 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72)

D/SchedPolicy( 1350): #20 pc 0000dac4 /system/lib/libc.so (pthread_create+160)

D/SchedPolicy( 1350): #00 pc 0000676c /system/lib/libcutils.so

D/SchedPolicy( 1350): #01 pc 00006b3a /system/lib/libcutils.so (set_sched_policy+49)

D/SchedPolicy( 1350): #02 pc 00016f26 /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+461)

D/SchedPolicy( 1350): #03 pc 00017380 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+183)

D/SchedPolicy( 1350): #04 pc 0001b160 /system/lib/libbinder.so

D/SchedPolicy( 1350): #05 pc 00011264 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+111)

D/SchedPolicy( 1350): #06 pc 000469bc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+63)

D/SchedPolicy( 1350): #07 pc 00010dca /system/lib/libutils.so

D/SchedPolicy( 1350): #08 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72)

D/SchedPolicy( 1350): #09 pc 0000dac4 /system/lib/libc.so (pthread_create+160)

6. 其它堆棧信息查詢

【Android 動畫】動畫詳解之補間動畫(一)

之前很早就想寫寫Android 的動畫,最近剛好有時間,大概聊一聊安卓動畫。

個人習(xí)慣將動畫分為:補間動畫(透明度、旋轉(zhuǎn)、位移、縮放)、幀動畫、和屬性動畫,這一篇,我們先說說補間動畫。

補間動畫這個詞出于flash,在兩個關(guān)鍵幀( 可以理解成動畫開始和結(jié)束 )中間需要做“補間動畫”,才能實現(xiàn)圖畫的運動;插入補間動畫后兩個關(guān)鍵幀之間的插補幀是由計算機自動運算而得到的。

實際上,Android 的補間動畫也是由我們指定動畫開始、動畫結(jié)束2個關(guān)鍵點,中間部分的動畫由系統(tǒng)完成

在正式開始之前,我們先說下Android 系統(tǒng)的坐標系,屏幕左上角為坐標原點,假如屏幕為1080*1980,那么左上角為(0,0),右上角為(1080,0),左下角為(0,1980),右下角為(1080,1980)

所有動畫有以下公共屬性,注釋比較詳細,這里就不在詳述了

ScaleAnimation有3種構(gòu)造方法

我們先看第一種,其起始比例為0,縮放比例為1.4,即放大到1.4倍

效果如下:

第二種,pivotx,pivotY分別代表起始位置的x、y方向的坐標,我們設(shè)置為(100,100)

效果如下:

第三種,pivotXType和pivotYType有2種模式,RELATIVE_TO_SELF(相對于自身)和RELATIVE_TO_PARENT(相對于父布局),如果設(shè)置這個,pivotx,pivotY的值就應(yīng)該是0-1的浮點數(shù),這里分別對應(yīng)xml中的%(自身)和%p(父布局)

TranslateAnimation有2種構(gòu)造方法,和ScaleAnimation類似

效果如下:

效果如下:

RELATIVE_TO_PARENT

效果如下:

RotateAnimation有3種構(gòu)造方法

順時針720度

效果如下:

逆時針720度

效果如下:

效果如下:

再來RELATIVE_TO_PARENT

效果如下:

這是什么鬼???怎么跑到屏幕外面去了?

原來設(shè)置為RELATIVE_TO_PARENT時,旋轉(zhuǎn)中心x方向應(yīng)該為該空間離左邊的邊距+父布局寬度/2,y方向同理,而此時,我們布局中紅色的Textview為居中狀態(tài),所以旋轉(zhuǎn)中心為屏幕右下角。讓我們來看個例子

修改布局如下:

效果如下:

這時,我們看到旋轉(zhuǎn)中心x方向為離左邊100dp處

AlphaAnimation只有1種構(gòu)造方法

其中fromAlpha為動畫開始的透明度;toAlpha為動畫結(jié)束的透明度

效果如下:

效果如下:

AnimationSet是一個動畫的集合,可以按照添加的順序播放動畫,讓我們來看個例子,通過組合動畫,實現(xiàn)旋轉(zhuǎn)漸入動畫

效果如下:

到這里,補間動畫就介紹完了

參考資料: 自定義控件三部曲之動畫篇

Android硬件抽象層模塊編寫規(guī)范

硬件抽象層模塊編寫規(guī)范

硬件抽象層最終都會生成.so文件,放到系統(tǒng)對應(yīng)的目錄中。在系統(tǒng)使用的時候,系統(tǒng)會去對應(yīng)目錄下加載so文件,實現(xiàn)硬件抽象層的功能。因此硬件抽象層的加載過程就是我們使用so的一個接口。先了解加載過程從源頭了解抽象層模塊兒的編寫規(guī)范。

1、硬件抽象層加載過程

系統(tǒng)在加載so的過程中,會去兩個目錄下查找對應(yīng)id的so文件。這兩個目錄分別是/system/lib/hw和/vendor/lib/hw。

so文件的名字分為兩個部分例如id.prop.so,第一部分是模塊id。第二部分是系統(tǒng)prop的值,獲取順序為“ro.hardware”、“ro.producat.board”、“ro.board.platform”、“ro.arch”,如果prop都找不到的話,就用default。(不是找不到prop的值,是找不到prop值對應(yīng)的so文件)。

負責加載硬件抽象層模塊的函數(shù)是hw_get_module,所在的文件是/hardware/libhardware/hardware.c如下:

/** Base path of the hal modules */

#if defined(__LP64__)

#define HAL_LIBRARY_PATH1 "/system/lib64/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"

#else

#define HAL_LIBRARY_PATH1 "/system/lib/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

#endif

/**

* There are a set of variant filename for modules. The form of the filename

* is ".variant.so" so for the led module the Dream variants?

* of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:

*

* led.trout.so

* led.msm7k.so

* led.ARMV6.so

* led.default.so

*/

static const char *variant_keys[] = {

"ro.hardware", ?/* This goes first so that it can pick up a different

file on the emulator. */

"ro.product.board",

"ro.board.platform",

"ro.arch"

};

static const int HAL_VARIANT_KEYS_COUNT =

(sizeof(variant_keys)/sizeof(variant_keys[0]));

/**

* Load the file defined by the variant and if successful

* return the dlopen handle and the hmi.

* @return 0 = success, !0 = failure.

*/

static int load(const char *id,

const char *path,

const struct hw_module_t **pHmi)

{

int status;

void *handle;

struct hw_module_t *hmi;

/*

* load the symbols resolving undefined symbols before

* dlopen returns. Since RTLD_GLOBAL is not or'd in with

* RTLD_NOW the external symbols will not be global

*/

handle = dlopen(path, RTLD_NOW);

if (handle == NULL) {

char const *err_str = dlerror();

ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");

status = -EINVAL;

goto done;

}

/* Get the address of the struct hal_module_info. */

const char *sym = HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym);

if (hmi == NULL) {

ALOGE("load: couldn't find symbol %s", sym);

status = -EINVAL;

goto done;

}

/* Check that the id matches */

if (strcmp(id, hmi-id) != 0) {

ALOGE("load: id=%s != hmi-id=%s", id, hmi-id);

status = -EINVAL;

goto done;

}

hmi-dso = handle;

/* success */

status = 0;

done:

if (status != 0) {

hmi = NULL;

if (handle != NULL) {

dlclose(handle);

handle = NULL;

}

} else {

ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",

id, path, *pHmi, handle);

}

*pHmi = hmi;

return status;

}

/*

* Check if a HAL with given name and subname exists, if so return 0, otherwise

* otherwise return negative. ?On success path will contain the path to the HAL.

*/

static int hw_module_exists(char *path, size_t path_len, const char *name,

const char *subname)

{

snprintf(path, path_len, "%s/%s.%s.so",

HAL_LIBRARY_PATH2, name, subname);

if (access(path, R_OK) == 0)

return 0;

snprintf(path, path_len, "%s/%s.%s.so",

HAL_LIBRARY_PATH1, name, subname);

if (access(path, R_OK) == 0)

return 0;

return -ENOENT;

}

int hw_get_module_by_class(const char *class_id, const char *inst,

const struct hw_module_t **module)

{

int i;

char prop[PATH_MAX];

char path[PATH_MAX];

char name[PATH_MAX];

char prop_name[PATH_MAX];

if (inst)

snprintf(name, PATH_MAX, "%s.%s", class_id, inst);

else

strlcpy(name, class_id, PATH_MAX);

/*

* Here we rely on the fact that calling dlopen multiple times on

* the same .so will simply increment a refcount (and not load

* a new copy of the library).

* We also assume that dlopen() is thread-safe.

*/

/* First try a property specific to the class and possibly instance */

snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);

if (property_get(prop_name, prop, NULL) 0) {

if (hw_module_exists(path, sizeof(path), name, prop) == 0) {

goto found;

}

}

/* Loop through the configuration variants looking for a module */

for (i=0 ; iHAL_VARIANT_KEYS_COUNT; i++) {

if (property_get(variant_keys[i], prop, NULL) == 0) {

continue;

}

if (hw_module_exists(path, sizeof(path), name, prop) == 0) {

goto found;

}

}

/* Nothing found, try the default */

if (hw_module_exists(path, sizeof(path), name, "default") == 0) {

goto found;

}

return -ENOENT;

found:

/* load the module, if this fails, we're doomed, and we should not try

* to load a different variant. */

return load(class_id, path, module);

}

int hw_get_module(const char *id, const struct hw_module_t **module)

{

return hw_get_module_by_class(id, NULL, module);

}

找到so文件之后,調(diào)用方法load方法去加載對應(yīng)的so文件,并返回hw_module_t結(jié)構(gòu)體。load方法源碼在上面程序中。

load方法首先調(diào)用dlopen加載對應(yīng)的so文件到內(nèi)存中。然后用dlsym方法找到變量HAL_MODULE_INFO_SYM_AS_STR符號對應(yīng)的地址,這個地址也就是一個hw_module_t結(jié)構(gòu)體,然后從這個結(jié)構(gòu)體中拿出id比對load方法出入的id是否一致,如果是的話表示打開成功。加載過程完成。

HAL_MODULE_INFO_SYM_AS_STR這個符號值為HMI,也就是必須要保證這個符號之后是一個hw_module_t。接下來的規(guī)范中有這個要求。

到此,模塊加載完成

2、硬件抽象層模塊編寫規(guī)范

硬件抽象層有兩個結(jié)構(gòu)體,一個是hw_module_t和hw_device_t,定義在hardware.h中。

首先說一下hw_module_t的編寫規(guī)范。

1、必須要有一個“自定義硬件抽象層結(jié)構(gòu)體”,且結(jié)構(gòu)體第一個變量類型要為hw_module_t。

2、必須存在一個HARDWARE_MODULE_INFO_TAG的符號,且指向“自定義硬件抽象層結(jié)構(gòu)體”。在加載的時候根據(jù)這個符號找到地址,并把地址的轉(zhuǎn)變?yōu)閔w_module_t,這也是為什么第一條中hw_module_t必須要在第一個的原因。

3、hw_module_t的tag必須為HARDWARE_MODULE_TAG

4、結(jié)構(gòu)體中要有一個方法列表,其中要有一個open方法。用open方法獲得hw_device_t

接下來說一下hw_device_t的編寫規(guī)范

1、必須要有一個“自定義硬件設(shè)備結(jié)構(gòu)體”,且結(jié)構(gòu)體第一個變量類型要為hw_device_t。

2、hw_device_t的tag必須為HARDWARE_DEVICE_TAG

3、要有一個close函數(shù)指針,來關(guān)閉設(shè)備

按照上面規(guī)范編寫的硬件抽象層就可以由系統(tǒng)加載并正確獲取到device。具體的應(yīng)用層邏輯在device中實現(xiàn)。

大神們!android:fromYDelta="0%p" android:fromYDelta="0"這兩有啥區(qū)別.%p什么意思?

android:fromYDelta="48" 從起始Y坐標,偏移48個坐標

android:fromYDelta="80%p" 從80%p的位置移動

80%p---父組件的80%

Android自定義軟鍵盤

Android自定義鍵盤的使用

1、新建一個xml文件夾放在res目錄下面,然后新建xml文件:money_keyboard.xml

2、然后在XML文件中添加按鈕布局,這個布局就是鍵盤的樣子了

3 屬性介紹:

Keyboard:

存儲鍵盤以及按鍵相關(guān)信息。

android:horizontalGap

按鍵之間默認的水平間距。

android:verticalGap

按鍵之間默認的垂直間距。

android:keyHeight

按鍵的默認高度,以像素或顯示高度的百分比表示。

android:keyWidth:

按鍵的默認寬度,以像素或顯示寬度的百分比表示。

Row:

為包含按鍵的容器。

Key:

用于描述鍵盤中單個鍵的位置和特性。

android:codes

該鍵輸出的unicode值。

android:codes 官網(wǎng)介紹是說這個是該鍵的unicode 值或者逗號分隔值,當然我們也可以設(shè)置成我們想要的值,在源碼中提供了幾個特定的值

對照表:

android:isRepeatable

這個屬性如果設(shè)置為true,那么當長按該鍵時就會重復(fù)接受到該鍵上的動作,在 刪除鍵鍵 和 空格鍵 上通常設(shè)為true。

android:keyLabel

顯示在按鍵上的文字。

android:keyIcon 與 keyLabel

是二選一關(guān)系,它會代替文字以圖標的形式顯示在鍵上。

android:keyWidth="33.33333%p"

每一個按鈕的寬度,可以設(shè)置百分比

android:keyHeight="10%p"

每一個按鈕高度,可以設(shè)置百分比

KeyboardView是一個渲染虛擬鍵盤的View。 它處理鍵的渲染和檢測按鍵和觸摸動作。

顯然我們需要KeyboardView來對Keyboard里的數(shù)據(jù)進行渲染并呈現(xiàn)給我們以及相關(guān)的點擊事件做處理。 1)//設(shè)置keyboard與KeyboardView相關(guān)聯(lián)的方法。

public void setKeyboard(Keyboard keyboard)

2)//設(shè)置虛擬鍵盤事件的監(jiān)聽,此方法必須設(shè)置,不然會報錯。

public void setOnKeyboardActionListener(OnKeyboardActionListener listener) 步驟上呢,做完第一步的關(guān)聯(lián),并設(shè)置第二步的事件,調(diào)用KeyboardView.setVisible(true);鍵盤就可以顯示出來了, 是不是很簡單。不過到這里還沒有結(jié)束哦,接下來我們?yōu)榱耸褂蒙系谋憷M行相應(yīng)的封裝。 封裝 這里我們通過繼承EditText來對Keyboard與KeyboardView進行封裝。

attr.xml文件,這里我們需要通過一個xml類型的自定義屬性引入我們的鍵盤描述文件。

1、新建一個類,我取名叫KeyUtils然后在里面新建三個屬性。KeyBoard用處可大了,他才是本體,可以通過設(shè)置他來切換鍵盤。

2、構(gòu)造函數(shù),初始下三個參數(shù)。

3、先說下預(yù)覽圖吧,就是效果圖上的預(yù)覽圖,需要預(yù)覽圖的話的將setPreviewEnabled設(shè)置為true,不過還得在布局文件中的android.inputmethodservice.KeyboardView標簽對立面設(shè)置預(yù)覽布局。否則,不會有字。至于設(shè)置的布局,一個TextView就好了~

onPress: 按下觸發(fā)。

onRelease:松開觸發(fā)。

onKey : 松開觸發(fā),在OnRelease之前觸發(fā)。

swipeLeft : 左滑動,其他同理。哈哈~就這么懶。

onText :需要在 鍵盤xml,也就是我此時的number.xml里面中key標簽對里添加一個

網(wǎng)站標題:android%p,androidphone停止運行
本文URL:http://chinadenli.net/article0/dsejdio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站App設(shè)計做網(wǎng)站商城網(wǎng)站微信公眾號品牌網(wǎng)站設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化