IM即時通訊專案講解(一) 實現類似qq微信表情皮膚無縫切換

若蘭__明月發表於2018-01-03

IM即時通訊專案講解(一)--實現類似qq微信表情皮膚無縫切換

標籤(空格分隔): 開源專案


###該系列技術課程來源慕課IM實戰

  • 帶後臺的IM即時通訊App 全程MVP手把手打造 #####通過該課程可以學習到以下知識點
  • 1、瞭解和開發後臺專案(這個是需要長期積累的,有了這個可以說入門沒問題)
  • 2、學習到IM相關知識點,建立群、新增群、單聊、群聊
  • 3、可以學習到資料庫的相關操作(建表、表之間的關聯等知識)
  • 4、學習到MVP模式,更加深入瞭解MVP模式的架構和實現
  • 5、學習到關於IM相關的優化,比如如何快速重新整理介面
  • 6、學習到如何進行推送等相關操作(伺服器端推送,單推、群推)
  • 7。。。當然還有好多的,大家不妨去了解一下,學習到知識才是最重要的

###首先看下效果圖(無圖耍流氓)

IM即時通訊專案講解(一)  實現類似qq微信表情皮膚無縫切換

###前言 這裡首先給個完整的專案地址,該專案是一個完整的IM即時通訊。涵蓋的功能群聊、單聊、建立群組、新增好友等。。。。大家可以下載看下.相關功能點readme.md中都有簡介。

這個專案也算是一個完整的專案,並且運用了一些比較不錯的知識點,還有就是專案中的一些小功能。在我們以後的開發或者寫的專案中可能會有啟發和用途,因此在這裡通過寫文章記錄一下,一方面也是對於所學知識的鞏固(正所謂碼了也不一定會、會了也不一定總結出來、總結出來也不一定講出來),正是這個道理,因為總結出來和自己會不是一個境界,能講出來境界又是提高一層。所以大家不要只停留在碼程式碼的一層,要做一名有追求的程式設計師(雖然我自己在碼程式碼的道路上越走越遠,但是始終不會放棄初心。加油---小菜鳥)

好了,說了那麼多話,沒一句說道本篇文章上,不過還要在說幾句,關於這個IM即時通訊demo,我還是會寫幾篇文章對其進行總結的,也算是對於自己所學的一個考評吧。接下來會一到兩週更新一篇。準備利用兩個月時間消化吸收。

###此篇文章背景 在自己的專案中,用到了EditText輸入框,這個是之前已經開發好的,但是有一個問題,那就是沒有解決相應的網路出現的各種衝突(淚奔),然後在自己開發社群的時候,在社群詳情,對於評論過多的時候在彈出軟鍵盤的時候(當再次點選取消軟鍵盤消失的時候)下面的評論會進行跳動(也就是說取消之後定位的地方不是剛開始彈出軟鍵盤的地方),當然這個和專案初期的控制元件,評論機制有關係,現在評論做成了本地評論(有相關的需求的可以進行討論哈),現在問題解決了,但是還有個體驗不好的地方就是軟鍵盤的切換閃屏問題,就是當切換表情的時候螢幕會跳動,因此這個也是之後進行的版本優化任務。現在在這個專案中解決了軟鍵盤的切換問題,基本達到了類似微信、QQ軟鍵盤表情切換效果,讓你***體驗如絲般順暢***。好了,有如此好的方法能夠解決軟鍵盤、表情切換方法或者程式碼,那還不趕緊給大家推薦推薦,以方便廣大老鐵們的開發哈。好了廢話不多說。看看怎麼整合到專案中吧。 ###專案整合 原專案地址 Airpanel

####第一步 在module的build.gradle中加入(這個庫很小,8個類,最大類也就200來行程式碼,小類幾十行程式碼)

compile 'net.qiujuer.widget:airpanel:1.0.0'

複製程式碼

####第二步 建立空氣皮膚佈局lay_chat_air_panel.xml(這個裡面就需要用到庫中的自定的一個控制元件了)關於控制元件的使用在後面會進行相關講解,這個地方想說明如何引入到專案中

<?xml version="1.0" encoding="utf-8"?>
<net.qiujuer.widget.airpanel.AirPanelLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/airPanelSubLayout"  
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="1px"
    android:visibility="gone">
<!--airPanelSubLayout這個根佈局的id必須是這個-->


<!--這裡放入一個fragment,在這個fragment裡面實現表情、語音、圖片、輸入法的相關邏輯切換-->
    <fragment
        android:id="@+id/frag_panel"
        class="com.mingchu.cnim4android.fragment.panel.PanelFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout="@layout/fragment_panel" />
</net.qiujuer.widget.airpanel.>AirPanelLinearLayout
複製程式碼

這裡給出這個fragment的相關邏輯實現(當然這個邏輯和軟鍵盤沒有任何關係了,只是負責控制哪個皮膚的顯示和隱藏,因為所有的關於軟鍵盤的控制都已經被AirPanelLinearLayout完成了)

public class PanelFragment extends BaseFragment implements FaceListener {

    //表情皮膚
    private View mFacePanel;
    //圖片相簿皮膚
    private View mGalleryPanel;
    //錄音皮膚
    private View mRecordPanel;
    private PanelCallback mCallback;

    public PanelFragment() {
        // Required empty public constructor
    }


    @Override
    protected int getContentLayoutId() {
        return R.layout.fragment_panel;
    }


    @Override
    protected void initView(View view) {
        super.initView(view);
        initRecord(view);
        initFace(view);
        initGallery(view);
    }


    //初始化表情佈局
    private void initFace(View root) {

        View facePanel = mFacePanel = root.findViewById(R.id.lay_face_panel);
        //todo  接下來就是相關的表情載入和相關點選的實現  這個有空就為大家在以後的文章中講解
        //

    }

    /**
     * 初始化錄音佈局
     *
     * @param root 根佈局
     */
    private void initRecord(View root) {
        View recordPanel = mRecordPanel = root.findViewById(R.id.lay_record_panel);
       //todo  接下來就是相關的語音錄製相關點選的實現  這個有空就為大家在以後的文章中講解

    }


    /**
     * 初始化圖片畫廊
     *
     * @param root 根佈局
     */
    private void initGallery(View root) {
        View galleryPanel = mGalleryPanel = root.findViewById(R.id.lay_gallery_panel);
       //todo  接下來就是相關的圖片展示和相關點選的實現  這個有空就為大家在以後的文章中講解
    }


    /**
     * 傳送
     *
     * @param galleryView
     * @param paths
     */
    private void onSendGalleryClick(GalleryView galleryView, String[] paths) {
        galleryView.clear();
        PanelCallback callback = mCallback;
        if (callback == null)
            return;
        callback.onSendGalleryClick(paths);
    }


    public void setup(PanelCallback callback) {
        this.mCallback = callback;
    }

    public boolean isOpenFace() {
        return mFacePanel.getVisibility() == View.VISIBLE;
    }


    public boolean isOpenMore() {
        return mGalleryPanel.getVisibility() == View.VISIBLE;
    }

    /**
     * 顯示錶情介面
     */
    public void showFace() {
        mFacePanel.setVisibility(View.VISIBLE);
        mGalleryPanel.setVisibility(View.GONE);
        mRecordPanel.setVisibility(View.GONE);
    }

    /**
     * 顯示錄音介面
     */
    public void showRecord() {
        mFacePanel.setVisibility(View.GONE);
        mGalleryPanel.setVisibility(View.GONE);
        mRecordPanel.setVisibility(View.VISIBLE);
    }

    /**
     * 顯示圖片介面
     */
    public void showGallery() {
        mFacePanel.setVisibility(View.GONE);
        mGalleryPanel.setVisibility(View.VISIBLE);
        mRecordPanel.setVisibility(View.GONE);
        GalleryView view = (GalleryView) mGalleryPanel.findViewById(R.id.view_gallery);
        view.clear();
    }

    public void showMore() {
        showGallery();
    }

    /**
     * 皮膚變化和相關輸入輸出的回撥
     */
    public interface PanelCallback {

        //獲取到輸入的EditText的值
        EditText getInputEditText();

        /**
         * 點選傳送按鈕的時候傳送圖片地址集合
         *
         * @param paths 本地相簿圖片路徑
         */
        void onSendGalleryClick(String[] paths);

        /**
         * 錄音完成的時候回撥
         *
         * @param file 錄音檔案
         * @param time 錄音時長
         */
        void onRecordDone(File file, long time);
    }
}

複製程式碼

這個時候萬事俱備,只差我們怎麼使用了,不急,一步一步來嗎,畢竟心急吃不了熱豆腐。剛才建立的那個佈局,我們放到我們需要使用的fragment或者activity的佈局裡面

<!--注意一點,根佈局使用的是AirPanelLinearLayout-->

    <include layout="@layout/lay_chat_sub_air_panel"/>
    

複製程式碼

好了,看下如何在fragment編寫相關邏輯吧,當然我這裡使用的是fragment,activity裡面使用的邏輯也是一樣的。

    //第一步

  //剛才我們實現的皮膚fragment
    private PanelFragment mPanelContent;
    //介面
    private AirPanel.Boss mPanelBoss;
    
    //第二步
     mPanelBoss = (AirPanel.Boss) view.findViewById(R.id.lay_container);  //這個id就是根佈局的id  (也就是AirPanelLinearLayout或者是子類的id)
        mPanelBoss.setPanelListener(new AirPanel.Listener() {
            @Override
            public void requestHideSoftKeyboard() {
                // 這裡面傳遞的是EditText控制元件 也就是我們的輸入控制元件   Util這個方法是整合的庫中的工具類
                Util.hideKeyboard(mEtContent);
            }
        });
        
    //第三步 找到我們的fragment 可以操作裡面的控制邏輯
     PanelFragment fragment = (PanelFragment) getChildFragmentManager().findFragmentById(R.id.frag_panel);
        //讓我們的fragment實現這個方法PanelCallback
        fragment.setup(this);
        mPanelContent = fragment;
        
    //這個時候我們可以操作了   因為實現了PanelCallback這個介面,那麼會實現裡面的方法,我們看下如何處理吧
    
      @Override
    public EditText getInputEditText() {
    //獲取表情輸入 當然需要自己進行轉換
        return mEtContent;
    }

    @Override
    public void onSendGalleryClick(String[] paths) {
    //圖片地址 這個時候我們需要進行上傳邏輯
        mPresenter.pushImages(paths);
    }

    @Override
    public void onRecordDone(File file, long time) {
        //語音的發起
        mPresenter.pushAudio(file.getAbsolutePath(), time);
    }
    

複製程式碼

什麼,這TM(提莫必須死)說的啥啊,瓜子毛嗑都準備好了,就給看這個。。。所有的點選事件怎麼沒有呢,不要急嗎,先看一個圖片

IM即時通訊專案講解(一)  實現類似qq微信表情皮膚無縫切換
然後我們看下點選邏輯吧


    //語音切換
    @OnClick(R.id.btn_record)
    void onRecordClick() {
        if (mPanelBoss.isOpen()) {
            Util.showKeyboard(mEtContent);
        } else {
            mPanelContent.showRecord();
            mPanelBoss.openPanel();
        }
    }

    //圖片點選
    private void onMoreClick() {
        if (mPanelBoss.isOpen() && mPanelContent.isOpenMore()) {
            Util.showKeyboard(mEtContent);
        } else {
            mPanelContent.showMore();
            mPanelBoss.openPanel();
        }

    }

    //表情點選
    @OnClick(R.id.btn_face)
    void onFaceClick() {
        if (mPanelBoss.isOpen() && mPanelContent.isOpenFace()) {
            //顯示輸入法
            Util.showKeyboard(mEtContent);
        } else {
            mPanelContent.showFace();
            mPanelBoss.openPanel();
        }
    }


複製程式碼

好了,這個時候就已經完美的實現了表情、輸入法、語音、圖片皮膚的切換了,是不是很簡單哈。之前也看過好多的關於介紹輸入法、表情切換閃屏問題,但是不知道是不是介紹的不詳細還是實現比較困難(自己太菜),然後發現了這樣的一個封裝比較好的一個庫,不過有個問題就是父佈局必須是AirPanelLinearLayout。這個就在於大家的取捨了。

###寫在最後 關於這個庫的介紹就不寫了,大致看了下,也是對於一個鍵盤的初始化,給一個最高和最低的值

 <declare-styleable name="AirPanelLinearLayout"><attr format="dimension" name="airPanelMinHeight"/><attr format="dimension" name="airPanelMaxHeight"/></declare-styleable>
    <dimen name="airPanelMaxHeight">280dp</dimen>
    <dimen name="airPanelMinHeight">86dp</dimen>
    <item name="airPanelSubLayout" type="id"/>
複製程式碼

然後在Helper這個類中進行拿到這些屬性,並進行相應的邏輯,比如裡面的計算軟鍵盤高度、修復高度、設定相關監聽、檢測軟鍵盤的動作等邏輯,大家看下也就明白了。

###參考文章

解決Android軟鍵盤和表情皮膚切換介面閃動問題 Android鍵盤皮膚衝突 佈局閃動處理方案 Android高仿微信表情輸入與鍵盤輸入詳解

相關文章