重慶分公司,新征程啟航
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
第一種點(diǎn)擊事件
創(chuàng)新互聯(lián)自2013年創(chuàng)立以來(lái),先為邵陽(yáng)等服務(wù)建站,邵陽(yáng)等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為邵陽(yáng)企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
在xml中設(shè)置onclick屬性
android:onClick="myOnclick"
第二種;獲取Button然后一個(gè)一個(gè)單獨(dú)綁定點(diǎn)擊事件
"
xmlns:tools=" "
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"?
android:id="@+id/btn_imgBtn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="myOnclick"
android:text="imageButton"
/
android:id="@+id/btn_imgView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="myOnclick"
android:text="imageView"
/
public class MainActivity extends ActionBarActivity {
private Button btnImageBtn;
private Button btnImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
? ? super.onCreate(savedInstanceState);
? ? setContentView(R.layout.activity_main);
? ? btnImageBtn = (Button) findViewById(R.id.btn_imgBtn);
? ? btnImageView = ?(Button) findViewById(R.id.btn_imgView);
btnImageBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點(diǎn)擊ImageButton", Toast.LENGTH_SHORT).show();
}
});
? ? btnImageView.setOnClickListener(new MyListener());
}
第三種:寫(xiě)一個(gè)類(lèi)(MyListener)實(shí)現(xiàn)OnClickListener接口,然后Button在設(shè)置onclickListener的時(shí)候new一個(gè)MyListener
btnImageView.setOnClickListener(new MyListener());
class MyListener implements OnClickListener{
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_imgBtn:
Toast.makeText(MainActivity.this, "點(diǎn)擊ImageButton", Toast.LENGTH_SHORT).show();
break;
? ? ?case R.id.btn_imgView:
? ? ? Toast.makeText(MainActivity.this, "點(diǎn)擊imageView", Toast.LENGTH_SHORT).show();
break;
}?
第四種:整個(gè)類(lèi)(MianActivity)實(shí)現(xiàn)onclickListener的接口
跳轉(zhuǎn)界面
Intent:意圖,用于訪問(wèn)android中的組件
用Intent跳轉(zhuǎn)界面(activity)
第一步:new一個(gè)Intent()
Intent intent1 = new Intent(MainActivity.this,ImageButtonActivity.class);
startActivity(intent1);
public void myOnclick(View view){
?switch (view.getId()) {
case R.id.btn_imgBtn:
Intent intent1 = new Intent(MainActivity.this,ImageButtonActivity.class);
startActivity(intent1);
break;
? ? case R.id.btn_imgView:
? ? ?Intent intent2 = new Intent(MainActivity.this,ImageViewActivity.class);
startActivity(intent2);
break;
Intent intent = new Intent(當(dāng)前的activity,跳轉(zhuǎn)到的acticvity.class);
startActivity(intent);
3.ImageView
展示方式:scaleType:
4.ImageButton:
觸摸事件:當(dāng)控件或者屏幕唄觸摸的時(shí)候,產(chǎn)生的反應(yīng)
public boolean onTouchEvent(MotionEvent event) {
}
imageButton:現(xiàn)在已經(jīng)唄button代替,用于展示圖片的按鈕。不能顯示文字。
imageView
scaleType:圖片展示的方式
fitStart:展示在控件的上方
fitCenter:展示在控件的中間
fitEnd;展示在控件的下方
fitXY:不按照比例拉伸
matrix:矩陣模式
matrix可以設(shè)置圖片旋轉(zhuǎn),縮放。移動(dòng)
獲取圖片的高度和寬度
int h = imgView.getDrawable().getIntrinsicHeight();
int w = imgView.getDrawable().getIntrinsicWidth();
Matrix m = new Matrix();
m.postRotate(45);
m.postRotate(45, w/2, h/2);
imgView.setImageMatrix(m);
移動(dòng)事件:
按下:MotionEvent.ACTION_DOWN
抬起:MotionEvent.ACTION_UP
移動(dòng):MotionEvent.ACTION_MOVE
獲取當(dāng)前的移動(dòng)事件,
event.getAction()
"
xmlns:tools=" "
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/img_01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/ss"
android:scaleType="fitXY"/
android:id="@+id/img_02"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/gl"
android:visibility="gone"
android:scaleType="fitXY"/
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/bird"
android:layout_gravity="center"
/
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="#ff0000"
android:gravity="center"
android:text="小鳥(niǎo)飛"/
public class MainActivity extends Activity {
private ImageView img01;
private ImageView img02;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img01 = (ImageView) findViewById(R.id.img_01);
img02 = (ImageView) findViewById(R.id.img_02);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//System.out.println("被摸了");
if(event.getAction()==MotionEvent.ACTION_UP){
Log.v("TAG", "被抬起來(lái)");
if(img01.getVisibility()==View.VISIBLE){
img01.setVisibility(View.GONE);
img02.setVisibility(View.VISIBLE);
}else{
img01.setVisibility(View.VISIBLE);
img02.setVisibility(View.GONE);
}
}else if(event.getAction()==MotionEvent.ACTION_DOWN){
Log.v("TAG", "被按下了");
}else if(event.getAction()==MotionEvent.ACTION_MOVE){
Log.v("TAG", "移動(dòng)了");
}
return super.onTouchEvent(event);
}
個(gè)人博客: haichenyi.com 。感謝關(guān)注
??本篇介紹實(shí)現(xiàn)模擬點(diǎn)擊的兩種方式:
??舉個(gè)栗子:我們現(xiàn)在需要實(shí)現(xiàn)點(diǎn)擊A按鈕,觸發(fā)B按鈕點(diǎn)擊事件的效果:兩個(gè)按鈕在布局里面隨便創(chuàng)建就好了。
?? 第一種方式就是:調(diào)用performClick事件
??這種方式很簡(jiǎn)單,但是有一個(gè)弊端,就是不會(huì)傳遞觸摸點(diǎn)坐標(biāo),只是模擬一下btn2的點(diǎn)擊事件。
?? 第二種方式就是:MotionEvent事件
??這種方式比較麻煩,用到的就是view的事件分發(fā),一個(gè)簡(jiǎn)單的點(diǎn)擊事件的觸發(fā)就是down和up組成,當(dāng)然還有平移我們這里不考慮。
?? 第一步 ,先用MotionEvent.obtain創(chuàng)建兩個(gè)事件:一個(gè)down事件,一個(gè)up事件,創(chuàng)建的時(shí)候需要傳遞坐標(biāo)點(diǎn),傳你目標(biāo)view的范圍內(nèi)的坐標(biāo)就行。
?? 第二步 ,通過(guò)目標(biāo)view,也就是這里的btn2去把這兩個(gè)事件分發(fā)出去,通過(guò)dispatchTouchEvent分發(fā),這樣就完成了一次模擬點(diǎn)擊事件,分發(fā)完記得回收
??這樣,就完成了一次模擬點(diǎn)擊,并且坐標(biāo)也傳遞了。因?yàn)?,?chuàng)建這兩個(gè)事件的時(shí)候就傳遞了。解決了performClick的弊端。
在使用MultiTypeAdapter實(shí)現(xiàn)RecyclerView多類(lèi)型顯示的時(shí)候,會(huì)創(chuàng)建一個(gè)ViewHolder和ViewBinder,此時(shí)如果要在Activity或者Fragment相應(yīng)點(diǎn)擊事件的時(shí)候,需要在ViewHolder和ViewBinder之間做傳遞。如果一個(gè)ViewHolder下有RecyclerView,然后也使用了MultiTypeAdapter,那么這個(gè)點(diǎn)擊事件的回調(diào)將會(huì)是一件相當(dāng)頭疼的事情。
在使用 LifeCycle 時(shí),發(fā)現(xiàn)他只需要當(dāng)前類(lèi)實(shí)現(xiàn) LifecycleObserver ,然后通過(guò)調(diào)用 addObserver 方法即可實(shí)現(xiàn)事件傳遞。由此想到點(diǎn)擊事件是否也可以使用此種形式來(lái)實(shí)現(xiàn)。
DEMO
在受到 LifeCycle 的啟發(fā)下,模仿這寫(xiě)了幾個(gè)類(lèi)。
一個(gè)點(diǎn)擊事件如果在某個(gè)類(lèi)中如果需要做操作,那么需要實(shí)現(xiàn)該接口。
繼承OnItemClick,并實(shí)現(xiàn)具體的方法。
基本點(diǎn)擊事件Observer
這一層,對(duì)事件在OnBindViewHolder中做了一次傳遞,通過(guò)dispatchObserver方法,將ViewBinder中的事件傳遞到了ViewHolder中。
定義兩個(gè)點(diǎn)擊事件。
創(chuàng)建實(shí)體類(lèi),和Binder相對(duì)應(yīng)。
在覆寫(xiě) setData 方法的時(shí)候,一定要調(diào)用super。不然事件無(wú)法傳遞。
響應(yīng)事件的回調(diào),只需要調(diào)用 getObserver 方法,然后傳入對(duì)應(yīng)的Observer,如果有,就直接調(diào)用方法。
adapter傳遞事件,也是通過(guò)dispatchObserver方法。
ViewBinder其實(shí)就不需要做什么事情了,比較簡(jiǎn)單。
1.(不推薦)結(jié)合layout文件聲明方法實(shí)現(xiàn)點(diǎn)擊事件的小案例:
2. 內(nèi)部實(shí)現(xiàn)類(lèi)完成點(diǎn)擊事件的小案例
在 activity_login.xml 中加上
之后在 LoginActivity 這個(gè)類(lèi)中實(shí)現(xiàn)一個(gè) ClickListener 類(lèi)
之后在LoginActivity的 Oncreate 中創(chuàng)建內(nèi)部實(shí)現(xiàn)類(lèi)的對(duì)象并設(shè)置點(diǎn)擊事件
3. Activity實(shí)現(xiàn)OnClickListener
4. 匿名內(nèi)部實(shí)現(xiàn)類(lèi)
[轉(zhuǎn)] 一篇文章看明白 Android 從點(diǎn)擊應(yīng)用圖標(biāo)到界面顯示的過(guò)程 (遵循CC 4.0 BY-SA版權(quán)協(xié)議)
從點(diǎn)擊桌面應(yīng)用圖標(biāo)到應(yīng)用顯示的過(guò)程我們?cè)偈煜げ贿^(guò)了,下面我們來(lái)分析下這個(gè)過(guò)程都做了什么。
本文主要對(duì)以下問(wèn)題分析:
如不了解 Android 是如何從開(kāi)機(jī)到 Launcher 啟動(dòng)的過(guò)程,請(qǐng)先閱讀 Android - 系統(tǒng)啟動(dòng)過(guò)程
我們知道 Android 系統(tǒng)啟動(dòng)后已經(jīng)啟動(dòng)了 Zygote,ServiceManager,SystemServer 等系統(tǒng)進(jìn)程;ServiceManager 進(jìn)程中完成了 Binder 初始化;SystemServer 進(jìn)程中 ActivityManagerService,WindowManagerService,PackageManagerService 等系統(tǒng)服務(wù)在 ServiceManager 中已經(jīng)注冊(cè);最后啟動(dòng)了 Launcher 桌面應(yīng)用。
其實(shí) Launcher 本身就是一個(gè)應(yīng)用程序,運(yùn)行在自己的進(jìn)程中,我們看到的桌面就是 Launcher 中的一個(gè) Activity。
應(yīng)用安裝的時(shí)候,通過(guò) PackageManagerService 解析 apk 的 AndroidManifest.xml 文件,提取出這個(gè) apk 的信息寫(xiě)入到 packages.xml 文件中,這些信息包括:權(quán)限、應(yīng)用包名、icon、apk 的安裝位置、版本、userID 等等。packages.xml 文件位于系統(tǒng)目錄下/data/system/packages.xml。
同時(shí)桌面 Launcher 會(huì)為安裝過(guò)的應(yīng)用生成不同的應(yīng)用入口,對(duì)應(yīng)桌面上的應(yīng)用圖標(biāo),下面分析點(diǎn)擊應(yīng)用圖標(biāo)的到應(yīng)用啟動(dòng)的過(guò)程。
點(diǎn)擊 Launcher 中應(yīng)用圖標(biāo)將會(huì)執(zhí)行以下方法
在 system_server 進(jìn)程中的服務(wù)端 ActivityManagerService 收到 START_ACTIVITY_TRANSACTION 命令后進(jìn)行處理,調(diào)用 startActivity() 方法。
從 Launcher 點(diǎn)擊圖標(biāo),如果應(yīng)用沒(méi)有啟動(dòng)過(guò),則會(huì) fork 一個(gè)新進(jìn)程。創(chuàng)建新進(jìn)程的時(shí)候,ActivityManagerService 會(huì)保存一個(gè) ProcessRecord 信息,Activity 應(yīng)用程序中的AndroidManifest.xml 配置文件中,我們沒(méi)有指定 Application 標(biāo)簽的 process 屬性,系統(tǒng)就會(huì)默認(rèn)使用 package 的名稱(chēng)。每一個(gè)應(yīng)用程序都有自己的 uid,因此,這里 uid + process 的組合就可以為每一個(gè)應(yīng)用程序創(chuàng)建一個(gè) ProcessRecord。每次在新建新進(jìn)程前的時(shí)候會(huì)先判斷這個(gè) ProcessRecord 是否已存在,如果已經(jīng)存在就不會(huì)新建進(jìn)程了,這就屬于應(yīng)用內(nèi)打開(kāi) Activity 的過(guò)程了。
進(jìn)程創(chuàng)建成功切換至 App 進(jìn)程,進(jìn)入 app 進(jìn)程后將 ActivityThread 類(lèi)加載到新進(jìn)程,并調(diào)用 ActivityThread.main() 方法
此時(shí)只創(chuàng)建了應(yīng)用程序的 ActivityThread 和 ApplicationThread,和開(kāi)啟了 Handler 消息循環(huán)機(jī)制,其他的都還未創(chuàng)建, ActivityThread.attach(false) 又會(huì)最終到 ActivityMangerService 的 attachApplication,這個(gè)工程其實(shí)是將本地的 ApplicationThread 傳遞到 ActivityMangerService。然后 ActivityMangerService 就可以通過(guò) ApplicationThread 的代理 ApplicationThreadProxy 來(lái)調(diào)用應(yīng)用程序 ApplicationThread.bindApplication,通知應(yīng)用程序的 ApplicationThread 已和 ActivityMangerService 綁定,可以不借助其他進(jìn)程幫助直接通信了。此時(shí) Launcher 的任務(wù)也算是完成了。
在 system_server 進(jìn)程中的服務(wù)端 ActivityManagerService 收到 ATTACH_APPLICATION_TRANSACTION 命令后進(jìn)行處理,調(diào)用 attachApplication()。
發(fā)送送完 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,還會(huì)發(fā)送 BIND_APPLICATION_TRANSACTION 命令來(lái)創(chuàng)建 Application。
在 app 進(jìn)程中,收到 BIND_APPLICATION_TRANSACTION 命令后調(diào)用 ActivityThread.bindApplication()。
ApplicationThreadProxy.bindApplication(…) 會(huì)傳來(lái)這個(gè)應(yīng)用的一些信息,如ApplicationInfo,Configuration 等,在 ApplicationThread.bindApplication 里會(huì)待信息封裝成AppBindData,通過(guò)
將信息放到應(yīng)用里的消息隊(duì)列里,通過(guò) Handler 消息機(jī)制,在 ActivityThread.handleMeaasge 里處理 H.BIND_APPLICATION 的信息,調(diào)用 AplicationThread.handleBindApplication。
Instrumentation:
這時(shí) Application 就創(chuàng)建好了,這點(diǎn)很重要,很多資料里說(shuō) Application 是在performLaunchActivity() 里創(chuàng)建的,因?yàn)?performLaunchActivity() 也有mInstrumentation.newApplication 這個(gè)調(diào)用,newApplication() 函數(shù)中可看出會(huì)先判斷是否以及創(chuàng)建了 Application,如果之前已經(jīng)創(chuàng)建,就返回已創(chuàng)建的 Application 對(duì)象。
上面 fork 進(jìn)程時(shí)會(huì)發(fā)送 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,在 app 進(jìn)程中,收到 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令后調(diào)用 ApplicationThread.scheduleLaunchActivity()。
與 Window 進(jìn)行關(guān)聯(lián),具體過(guò)程詳見(jiàn): Activity,Window,View 之間的關(guān)系
Activity 的整體啟動(dòng)流程如圖所示: