Android6.0 源碼修改之 Contacts應用

来源:https://www.cnblogs.com/cczheng-666/archive/2019/04/25/10770147.html
-Advertisement-
Play Games

一、Contacts應用的主界面和聯繫人詳情界面增加頂部菜單添加退出按鈕 通過Hierarchy View 工具可以發現 主界面對應的類為 PeopleActivity 聯繫人詳情界面對應的類為 QuickContactActivity 左上角的退出按鈕其實很簡單,系統actionBar已經幫我們實 ...


一、Contacts應用的主界面和聯繫人詳情界面增加頂部菜單添加退出按鈕

通過Hierarchy View 工具可以發現

主界面對應的類為 PeopleActivity

聯繫人詳情界面對應的類為 QuickContactActivity

左上角的退出按鈕其實很簡單,系統actionBar已經幫我們實現了這一功能,只是沒有顯示出來而已。在onCreate()方法中,在setContentView()方法之後,添加如下代碼即可顯示返回的箭頭

    ActionBar mActionBar = getActionBar();
    if (mActionBar != null) {
        Log.i(TAG, "getSupportActionBar != null....");
        mActionBar.setDisplayHomeAsUpEnabled(true);
        mActionBar.setHomeButtonEnabled(true);
    }

接下來在onOptionsItemSelected()中監聽返回按鈕的事件即可

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home: {
                 finish();
            }
            return true;
        }
        ....
}

圖1 左上角返回退出功能

二、第三方app拉起主界面時直接顯示模糊查詢對應的聯繫人列表

簡單分析一下,模糊查詢需要對應的查詢聯繫人名稱,可以通過intent傳遞參數,這裡定義為String類型,當傳遞參數不為null時,模擬手動點擊搜索框對應的邏輯。如下在 PeopleActivity 的 onCreate()方法中增加獲取參數的代碼

final String queryString = getIntent().getStringExtra("queryString");
    if (!TextUtils.isEmpty(queryString)) {
         new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                showQueryTextFragment(queryString);
            }
        }, 100);//讓搜索邏輯延遲100ms執行
    }

通過測試發現,不加延遲觸發搜索框對應的邏輯並不會顯示模糊查詢結果界面。接下來我們分析點擊搜索框對應的邏輯代碼,找到搜索框對應的控制項id,menu_search, 回到剛剛的菜單監聽方法 onOptionsItemSelected()中

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    ...

    switch (item.getItemId()) {
     case R.id.menu_search: {
            onSearchRequested();
            return true;
        }
    }
    ...
}

@Override
public boolean onSearchRequested() { // Search key pressed.
    Log.d(TAG, "[onSearchRequested]");
    //不在搜索模式下,也就是沒有點擊過搜索框
    if (!mActionBarAdapter.isSelectionMode()) {
        //獲取焦點,彈出鍵盤
        mActionBarAdapter.setSearchMode(true);
    }
    return true;
}

從上面不難看出最終調用 mActionBarAdapter 的方法,我們接著跟進去

源碼位置 packages/apps/Contacts/src/com/android/contacts/activities/ActionBarAdapter.java

public void setSearchMode(boolean flag) {
    if (mSearchMode != flag) {
        mSearchMode = flag;
        update(false /* skipAnimation */);
        if (mSearchView == null) {
            return;
        }
        if (mSearchMode) {
            mSearchView.setEnabled(true);
            setFocusOnSearchView();
        } else {
            // Disable search view, so that it doesn't keep the IME visible.
            mSearchView.setEnabled(false);
        }
        setQueryString(null);
    } else if (flag) {
        // Everything is already set up. Still make sure the keyboard is up
        //需要註釋此處,不然多次調用並退出再次拉起容易出現鍵盤彈出的情況
        //if (mSearchView != null) setFocusOnSearchView();
    }
}

public void setFocusOnSearchView() {
    //mSearchView獲取焦點(先獲取焦點才能彈出鍵盤)
    mSearchView.requestFocus();
    //彈出鍵盤
    showInputMethod(mSearchView); // Workaround for the "IME not popping up" issue.
}

private void showInputMethod(View view) {
    final InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
            Context.INPUT_METHOD_SERVICE);
    if (imm != null) {
        imm.showSoftInput(view, 0);
    }
}

看到這裡我們可以猜想到 mSearchView 肯定設置了文字改變監聽,繼續查找 addTextChangedListener

...
mSearchView.setInputType(EditorInfo.TYPE_CLASS_TEXT
        | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
mSearchView.addTextChangedListener(new SearchTextWatcher());
...

private class SearchTextWatcher implements TextWatcher {

    @Override
    public void onTextChanged(CharSequence queryString, int start, int before, int count) {
        if (queryString.equals(mQueryString)) {
            return;
        }
        //當前輸入的模糊查詢的名稱
        mQueryString = queryString.toString();
        if (!mSearchMode) {
            if (!TextUtils.isEmpty(queryString)) {
                setSearchMode(true);
            }
        } else if (mListener != null) {
            //回調通知 PeopleActivity 改變界面
            mListener.onAction(Action.CHANGE_SEARCH_QUERY);
        }
        mClearSearchView.setVisibility(
                TextUtils.isEmpty(queryString) ? View.GONE : View.VISIBLE);
    }

    @Override
    public void afterTextChanged(Editable s) {}

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
}

回到 PeopleActivity 中找到監聽 Action.CHANGE_SEARCH_QUERY 的代碼如下

 @Override
public void onAction(int action) {
    Log.d(TAG,"[onAction]action = " + action);
    /// M: [vcs] @{
    if (mVcsController != null) {
        mVcsController.onActionVcs(action);
    }
    /// @}
    switch (action) {
    ...
    case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
            //獲取當前輸入的模糊查詢姓名
            final String queryString = mActionBarAdapter.getQueryString();
            //顯示對應的fragment
            setQueryTextToFragment(queryString);
            updateDebugOptionsVisibility(
                    ENABLE_DEBUG_OPTIONS_HIDDEN_CODE.equals(queryString));
            break;
        default:
            throw new IllegalStateException("Unkonwn ActionBarAdapter action: " + action);
    }
}

到此,搜索框模糊查詢對應的邏輯就分析完了,那麼我們就模擬調用對應的邏輯就ok了,再來把整體流程捋一遍,

點擊搜索框->獲取焦點->彈出鍵盤->輸入姓名->收到文字內容改變的監聽->將輸入的內容回調給 PeopleActivity->收到回調顯示對應的結果Fragment

好了,通過調用EditText.setText()方法也能觸發文字內容改變的監聽,前提是要先獲取焦點,那麼我們的 showQueryTextFragment() 實現如下

private void showQueryTextFragment(String queryString){
    Log.d(TAG, "[showQueryTextFragment]");
    if (!mActionBarAdapter.isSelectionMode()) {
        Log.e(TAG, "[queryString==]"+queryString);
        mActionBarAdapter.setSearchMode(true);
        mActionBarAdapter.setQueryString(queryString);
    }
}


圖2 第三方app拉起主界面顯示對應的聯繫人

三、第三方app拉起聯繫人詳情界面只滑動到一半顯示的問題

-

圖3 拉起只顯示一半

圖4 拉起完全顯示

首先從系統的聯繫人列表界面點擊進入詳情界面是能完整顯示的,所以猜想應該是傳遞的參數不太一樣。所以還是從onCreate()方法看下來

public class QuickContactActivity extends ContactsActivity {

        /**
     * QuickContacts immediately takes up the full screen. All possible information is shown.
     * This value for {@link android.provider.ContactsContract.QuickContact#EXTRA_MODE}
     * should only be used by the Contacts app.
     */
    public static final int MODE_FULLY_EXPANDED = 4;
    //看上面的註釋就知道了肯定是跟這個變數有關係, 立刻顯示全屏,應當只用於 聯繫人 app 使用

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        Trace.beginSection("onCreate()");
        super.onCreate(savedInstanceState);

        if (RequestPermissionsActivity.startPermissionActivity(this)) {
            return;
        }

        getWindow().setStatusBarColor(Color.TRANSPARENT);
        //處理Intent傳遞的參數
        processIntent(getIntent());

        .....
        //Scroller初始化,傳遞滾動模式
        mScroller.initialize(mMultiShrinkScrollerListener, mExtraMode == MODE_FULLY_EXPANDED);
        // mScroller needs to perform asynchronous measurements after initalize(), therefore
        // we can't mark this as GONE.
        mScroller.setVisibility(View.INVISIBLE);
        ...
    }

    private void processIntent(Intent intent) {
        ...
        //獲取傳遞的EXTRA_MODE,不傳預設為large,查看api對應的int值為3,MODE_FULLY_EXPANDED為4, 所以不傳遞參數或者參數對應值不為4就只顯示半屏
        mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE, QuickContact.MODE_LARGE);
        
        ...
    }

}

通過上面的分析 intent需要傳遞 QuickContact.EXTRA_MODE 參數, 當你點進去 QuickContact中發現並沒有對應4的變數(猜想應該是留了一手不讓第三方app直接全屏顯示)

正確的打開姿勢

private void gotoContact(){
    Uri personUri = ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 1);
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    intent.setData(personUri);
    //這句比較關鍵
    intent.putExtra(ContactsContract.QuickContact.EXTRA_MODE, 4);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

總結

1、話說當把navigationBar去掉以後,給每個activity添加返回按鈕是個很麻煩的工作,可以借鑒一下蘋果的思路,直接在屏幕(Window)中添加一個懸浮的按鈕處理返回點擊事件。具體實現可以看這篇Android6.0 源碼修改之 仿IOS添加全屏可拖拽浮窗返回按鈕

2、源碼沒那麼可怕,幹起來。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 為什麼加鎖 你正在讀著你喜歡的女孩遞給你的信,看到一半的時候,她的好閨蜜過來瞄了一眼(假設她會隱身術,你看不到她),她想把“我很喜歡你”改成“我不喜歡你”,剛把“很”字擦掉,“不”字還沒寫完,只寫了一橫一撇,這時候你正讀到這個字,她怕你察覺到也就沒繼續往下寫了,這時候你讀到的這句話就是“我丆喜歡你” ...
  • 資料庫設計 維護優化 資料庫維護優化要做什麼? 資料庫維護優化要做什麼? 明確表以及表中每一個欄位所代表的含義。 隨著數據量和查詢的不斷變化,需要優化索引。 隨著需求的不斷變化,需要對錶進行擴充或裁剪 隨著數據量的增大,達到表的存儲瓶頸,使操作變慢,需要拆分表。 如何維護數據字典? 如何維護數據字典 ...
  • 1、連接Mysql 格式: mysql -h主機地址 -u用戶名 -p用戶密碼 1、連接到本機上的MYSQL。首先打開DOS視窗,然後進入目錄mysql\bin,再鍵入命令mysql -u root -p,回車後提示你輸密碼.註意用戶名前可以有空格也可以沒有空格,但是密碼前必須沒有空格,否則讓你重新 ...
  • /*** 字元串分隔方法* 獲取字元串分隔之後的數組長度*/DROP FUNCTION IF EXISTS `func_get_split_total`;DELIMITER ;;CREATE FUNCTION `func_get_split_total`( f_string text, # 長度不夠 ...
  • 1、新安裝的mysql8,使用破解版的navicat連接的時候一直報錯,如圖所示: 2、網上查找原因發現是mysql8 之前的版本中加密規則是mysql_native_password,而在mysql8之後,加密規則是caching_sha2_password, 解決問題方法有兩種,一種是升級nav ...
  • 首先上圖: 實現這個標題欄,我們還需要一個返回的按鈕,這裡也貼出來。筆者直接將這個簡單的標題欄製作成了一個依賴庫,放在到github上,方便下次進行調用。 返回按鈕如下: 在使用這個按鈕的時候需要註意其尺寸的大小一定要小於我們的標題欄。 view_top.xml 新建的topview類: 調用方法: ...
  • 之前出現該錯誤,我用的是這個方法: https://www.cnblogs.com/tangZH/p/10691383.html 然而遺憾的是,這次不管用了,無奈,只好另尋他法,其實會出現這個錯誤就是資源文件出現問題,導致無法被打包。 從具體的錯誤裡面也可以看出,確實是資源文件出了問題 點擊右上角g ...
  • 轉載請標明出處,維權必究:https://www.cnblogs.com/tangZH/p/10770296.html android代碼,兩個版本之間,代碼行數增加了多少,怎麼得出呢? 1.安裝TortoiseSVN,在安裝時需要安裝svn命令行工具。 2、下載StatSVN包,官網:http:/ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...