精华内容
下载资源
问答
  • 使用Java后台,Socket方法实现android群聊(android客户端+java后台) 包括android客户端+java后台,客户端使用androidstudio开发。
  • android群聊私聊app

    2015-05-10 21:30:29
    写完以后由于老师只要windows平台上的,所以只能拿出来收点分数了orz
  • Android局域网群聊app

    2020-05-27 14:08:56
    使用工具Android Studio3.1.2,实现了局域网通信。任何一台设备都可在服务器与客户机之间切换,可多人群聊。只需多个队员连接到同一队长。
  • android局域网群聊源码

    2014-06-26 11:32:01
    有兴趣的朋友可以看看,局域网群聊,初学者入门水平
  • 群聊的list列表中用户的头像是默认图,昵称是用户的id。 这显然很不友好,环信给出的方案如下: 方法一:从APP服务器获取昵称和头像 昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找...

    最近在用环信开发项目中,发现环信的后台并不支持录入头像和昵称。 群聊的list列表中用户的头像是默认图,昵称是用户的id。 这显然很不友好,环信给出的方案如下:

    方法一:从APP服务器获取昵称和头像 昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求。 昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

    方法二:从消息扩展中获取昵称和头像 昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。 昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。

    只有具体的思路,也并没有展示的代码,苦恼了一众小伙伴 ( ̄ω ̄( ̄ω ̄〃 ( ̄ω ̄〃)ゝ

    -----------我叫分割线-----------------------我叫分割线------------ 废话不多说,贴代码:

    1.首先定义一个util用于本次操作: Public class setEaseUser {}

    2.有参构造函数:

    setChatRoomIdHttp()是我司的一个http请求,就不贴代码了

    3.获取到数据后调用环信sdk

    (1)先循环遍历Http请求接口之后的返回数据(用户id,头像,昵称)

    (2)插入数据

    username.equals(groupUsersRootBean.getObj().get(i).getUser_id() + "_xianghe")

    这一步是判断如果环信的username(也就是你list中头像旁边显示的id)等于你javaBean中的一个userId,之后

    【easeUser.setNickname()插入昵称】

    【easeUser.setAvatar()插入头像】

    (3)在你的chatFragment中调用

    EaseChatFragment中有一个setUpView()的方法。

    在这其中调用你刚写好的util就可以了,有参构造函数中有一个重复的。。。手下留情。

    写完之后重新运行程序,你会发现群聊中的头像和昵称都可以正常显示了。

    转载于:https://juejin.im/post/5b35a8bfe51d45587f4a25f0

    展开全文
  • 简介: Android 仿钉钉、微信 群聊组合头像 更多:作者提 Bug 标签: 效果预览 功能 生成类似钉钉、微信 群聊组合头像 Bitmap 可使用图片资源 id、bitmap ...

    CombineBitmap

    项目地址:SheHuan/CombineBitmap 

    简介: Android 仿钉钉、微信 群聊组合头像

    更多:作者   提 Bug   

    标签:

     

    效果预览

     

    功能

    • 生成类似钉钉、微信 群聊组合头像 Bitmap
    • 可使用图片资源 id、bitmap 或者使用 url 从网络加载,传入对应数组即可
    • 网络加载时支持线程池
    • 支持磁盘缓存、内存缓存。(记得申请磁盘缓存需要的文件存储权限
    • 对图片资源进行采样率压缩
    • 支持子图像的点击事件
    • ......

      基本用法

      Step 1. 添加 JitPack 仓库 在项目根目录下的 build.gradle 中添加仓库:

      allprojects {
        repositories {
            ...
            maven { url "https://jitpack.io" }
        }
      }
      

      Step 2. 添加项目依赖

      dependencies {
        implementation 'com.github.Othershe:CombineBitmap:1.0.5'
      }
      

      Step 3. 配置

      CombineBitmap.init(context)
        .setLayoutManager() // 必选, 设置图片的组合形式,支持 WechatLayoutManager、DingLayoutManager
        .setSize() // 必选,组合后 Bitmap 的尺寸,单位 dp
        .setGap() // 单个图片之间的距离,单位 dp,默认 0dp
        .setGapColor() // 单个图片间距的颜色,默认白色
        .setPlaceholder() // 单个图片加载失败的默认显示图片
        .setUrls() // 要加载的图片 url 数组
        .setBitmaps() // 要加载的图片 bitmap 数组
        .setResourceIds() // 要加载的图片资源 id 数组
        .setImageView() // 直接设置要显示图片的 ImageView
        // 设置“子图片”的点击事件,需使用 setImageView(),index 和图片资源数组的索引对应
        .setOnSubItemClickListener(new OnSubItemClickListener() {
            @Override
            public void onSubItemClick(int index) {
      
            }
        })
        // 加载进度的回调函数,如果不使用 setImageView()方法,可在 onComplete()完成最终图片的显示
        .setProgressListener(new ProgressListener() {
            @Override
            public void onStart() {
      
            }
      
            @Override
            public void onComplete(Bitmap bitmap) {
      
            }
        })
        .build();
      

      由于生成的组合 Bitmap 是矩形的,要实现钉钉的圆形显示效果,这里用到了一个可圆形显示的 ImageView 控件:NiceImageView

    展开全文
  • Android 端实现基于MQTT协议的单聊,群聊功能,,,下载了就是赚到了
  • Android/ios】-【版本号】:【会经常出现群聊消息收不到的情况,但是C2C私聊却是完全正常,也没有上报相关错误码】 issue内容: 【当前现象】:群聊消息偶尔会收不到(一旦...
  • 生成类似钉钉、微信 群聊组合头像Bitmap 可使用图片资源id、bitmap或者使用url从网络加载,传入对应数组即可 网络加载时支持线程池 支持磁盘缓存、内存缓存。(记得申请磁盘缓存需要的文件存储权限) 对图片...
  • android基于环信自定义群聊以及表情简单集成,涉及到表情键盘的流畅切换
  • Android基于Bmob群聊功能的实现

    千次阅读 热门讨论 2016-01-20 15:41:34
    官方写的IM的Demo目前可以实现登录注册、搜索添加好友、与好友进行文字图片音频位置对话功能,但感觉好友很多缺陷,比如说删除表中的数据时只能根据ID查找,没提供数据库事务操作的接口,IM没实现群聊的功能,有些...

    Bmob算是国内做的比较好的做BaaS或MBaaS服务的公司了,官方写的IM的Demo目前可以实现登录注册、搜索添加好友、与好友进行文字图片音频位置对话功能,但感觉还有很多缺陷,比如说删除表中的数据时只能根据ID查找,没提供数据库事务操作的接口,IM没实现群聊的功能,有些API太少太局限,可能因为公司团队小吧,希望能越做越好。
    回到正题,既然Bmob的IM没有实现群聊,那就自己实现,Bmob有一个“数据实时同步”的功能,用来让SDK对某些数据表进行监听,一旦数据表发生改变,就会通知到SDK。群聊时,用户发消息时就发到该群对应的消息表中,群中的所有成员都对这个消息表进行监听,因此一旦监听到表中数据变化就表明某个成员发了消息,就能取到这个消息对象。

    数据库设计:

    群组分类表TribeTypeBean(分类名、分类描述)

    public class TribeTypeBean extends BmobObject {
    
        private String tribeTypeName;
        private String tribeTypeDescription;

    群组表TribeBean(群组名、群组描述、群组头像、群组创建者、群组成员、群组所属分类),其中,群组创建者和群组分类是一对多关联,在SDK中直接用对象类型,在云端表现为Pointer< T >类型。群组成员是多对多关联,在SDK中要声明为BmobRelation类型,在云端表现为Relation< T >类型。

    public class TribeBean extends BmobObject {
    
        private String tribeName;
        private String tribeDescription;
        private String tribeAvatar;
        private BmobUser tribeLeader;
        private BmobRelation tribeMember;
        private TribeTypeBean tribeTypeBean;

    群组消息表GroupChatMsgBean(消息对应群组、消息发送者、消息内容、消息发送时间、是否已读、消息状态),在创建群组时,就要为这个群组创建一个消息表,消息表中要有一个字段表明该消息表对应的群组。这样就建立起了单向的一对一关联关系。但有个问题,我可以通过条件查询群组表知道自己加入了哪些群组,但并不知道这些群组对应的消息表是什么。所以我决定采用一种比较简单的方式来实现,让消息表的表名为“GroupChatMsg”+对应群组的id,这样就在语义上建立起了对应关系,也保证了表名的唯一性,监听表时就监听“GroupChatMsg”+对应群组的id这些表就行了。

    public class GroupChatMsgBean extends BmobObject {
    
        private TribeBean tribe;
        private UserBean sender;
        private String msgContent;
        private Integer msgType;
        private String msgTime;
        private Integer isReaded;
        private Integer status;

    虽然每个群组对应的表名不一样,但群消息实体还是一样的,因此发消息时不能直接调用BmobObject的save方法,需要用云端代码来完成:

    function onRequest(request, response, modules) {
        var db = modules.oData;
        var tableName = request.body.tableName;
        var groupChatMsgObject = JSON.parse(request.body.groupChatMsg);
        db.insert({
            "table" : tableName,
            "data" : groupChatMsgObject
            },function(err,data){
                response.send(err+","+data);
            }
        );
    }                                                                                                                         

    调用参数是消息表名和消息实体。

    因此,发消息时要组装好消息对象并调用云端代码:

                        UserBean currentUser = BmobUser.getCurrentUser(GroupChatActivity.this, UserBean.class);
                        try {
                            AsyncCustomEndpoints ace = new AsyncCustomEndpoints();
                            JSONObject cloudCodeParams = new JSONObject();
                            GroupChatMsgBean groupChatMsgBean = new GroupChatMsgBean();
                            groupChatMsgBean.setTribe(targetTribe);
                            groupChatMsgBean.setSender(currentUser);
                            groupChatMsgBean.setMsgContent(et_send.getText().toString());
                            groupChatMsgBean.setMsgType(BmobConfig.TYPE_TEXT);
                            groupChatMsgBean.setMsgTime(String.valueOf(BmobUtils.getTimeStamp()));
                            groupChatMsgBean.setIsReaded(0);
                            groupChatMsgBean.setStatus(BmobConfig.STATUS_SEND_SUCCESS);
                            sendMessageToUI(groupChatMsgBean);
                            Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
                                @Override
                                public boolean shouldSkipField(FieldAttributes f) {
                                    return f.getName().contains("_c_")|f.getName().contains("increments")|f.getName().contains("tribe")|f.getName().contains("sender");
                                }
    
                                @Override
                                public boolean shouldSkipClass(Class<?> clazz) {
                                    return false;
                                }
                            }).create();
                            JSONObject jsonObject = new JSONObject(gson.toJson(groupChatMsgBean));
                            jsonObject.put("tribe",new JSONObject(new Gson().toJson(new BmobPointer(targetTribe))));
                            jsonObject.put("sender", new JSONObject(new Gson().toJson(new BmobPointer(currentUser))));
                            cloudCodeParams.put("tableName", "GroupChatMsg" + targetTribe.getObjectId());
                            cloudCodeParams.put("groupChatMsg", jsonObject);
                            ace.callEndpoint(GroupChatActivity.this, "sendGroupChatMsg", cloudCodeParams,
                                    new CloudCodeListener() {
                                        @Override
                                        public void onSuccess(Object object) {
                                            // TODO Auto-generated method stub
                                            LogUtils.LOGE("shang", "云端返回:" + object.toString());
                                        }
    
                                        @Override
                                        public void onFailure(int code, String msg) {
                                            // TODO Auto-generated method stub
                                            LogUtils.LOGE("shang", "访问云端失败:" + msg);
                                        }
                                    });
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

    监听消息表的变化时用实时数据处理类BmobRealTimeData:

                    bmobRealTimeData = new BmobRealTimeData();
                    bmobRealTimeData.start(getActivity(), new ValueEventListener() {
                        @Override
                        public void onDataChange(JSONObject jsonObject) {
                            // TODO Auto-generated method stub
                            //{"data":{"content":"我就试试","objectId":"mynjZZZa","createdAt":"2016-01-15 18:02:47"},
                            // "action":"updateTable","objectId":"","tableName":"99aa3421bf","appKey":"44d4d237ac590c04a4cc0f3e030ab0a9"}
                            LogUtils.LOGE("shang", "onDataChange "+jsonObject.toString());
                            if (BmobRealTimeData.ACTION_UPDATETABLE.equals(jsonObject.optString("action"))) {
                                JSONObject data = jsonObject.optJSONObject("data");
                                Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
                                    @Override
                                    public boolean shouldSkipField(FieldAttributes f) {
                                        return f.getName().contains("sender") | f.getName().contains("tribe");
                                    }
    
                                    @Override
                                    public boolean shouldSkipClass(Class<?> clazz) {
                                        return false;
                                    }
                                }).create();
                                GroupChatMsgBean bean = gson.fromJson(data.toString(), GroupChatMsgBean.class);
                                //如果收到的是自己的消息更新或者是删除更新,直接return
                                if (currentUserId.equals(data.optString("sender")) || "".equals(data.optString("sender"))) {
                                    return;
                                }
                                getTribeById(bean, data.optString("tribe"));
                                getUserById(bean, data.optString("sender"));
                            }
                        }
    
                        @Override
                        public void onConnectCompleted() {
                            // TODO Auto-generated method stub
                            if (bmobRealTimeData.isConnected()) {
                                LogUtils.LOGE("shang", "连接成功");
                                for (TribeBean tribeBean :
                                        myTribeBeanList) {
                                    bmobRealTimeData.subTableUpdate("GroupChatMsg" + tribeBean.getObjectId());
                                }
                            }
                        }
                    });                                                                                                        

    在onDataChange回调中接收处理新增的消息,如发送广播:
        Intent intent = new Intent();
        intent.setAction(“cn.minitribe.group_chat_msg”);
        intent.putExtra(“GroupChatMsgBean”, bean);
        GroupChatFragment.this.getActivity().sendOrderedBroadcast(intent, null);
    在onConnectCompleted回调中启动相关表的监听。

    展开全文
  • 在网上看了好多,但是感觉不是太简单就是只能单独聊,所以就自己写了个可以群聊的,直接上代码了 一、服务器端 这里用的MyEclipse作为服务器端 MyServerScoket.java package com.scme.server; public ...

    在网上看了好多,但是感觉不是太简单就是只能单独聊,所以就自己写了个可以群聊的,直接上代码了

    一、服务器端

    这里用的MyEclipse作为服务器端

    MyServerScoket.java

    package com.scme.server;
    
    
    public class MyServerScoket {
    
        public static void main(String[] args) {
            new ServerListener().start();
        }
    }

     

    ServerListener.java

    package com.scme.server;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import javax.swing.JOptionPane;
    
    public class ServerListener extends Thread {
    
        @Override
        public void run() {
            // 1-65535
            try {
                // 端口
                ServerSocket serverScoket = new ServerSocket(12345);
                while (true) {
                    // 阻塞当前线程
                    Socket socket = serverScoket.accept();
                    // 建立连接,控制台打印
                    System.out.println("有客户端连接到了本机的12345端口");
                    // 弹出窗口提示
                    JOptionPane.showMessageDialog(null, "有客户端连接到了本机的12345端口");
                    //将socket传递新的线程
                    ChatSocket cs = new ChatSocket(socket);
                    cs.start();
                    ChatManger.getChatManger().add(cs);
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    ChatSocket.java

    package com.scme.server;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    
    public class ChatSocket extends Thread {
        
        Socket socket;
    
        public ChatSocket(Socket s){
            this.socket = s;
        }
        
        public void out(String out){
            try {
                socket.getOutputStream().write((out+"\n").getBytes("UTF-8"));
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
        
        @Override
        public void run() {
            out("你已经连接到本服务器了");
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
                String line = null;
                while ((line = br.readLine()) != null) {
                    ChatManger.getChatManger().publish(this, line);
                }
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            
        }
    }

    ChatManger.java

    package com.scme.server;
    
    import java.util.Vector;
    
    public class ChatManger {
    
        //单例化
        private ChatManger(){}
        private static final ChatManger cm = new ChatManger();
        public static ChatManger getChatManger(){
            return cm;
        }
        
        Vector<ChatSocket> vector = new Vector<ChatSocket>();
        
        public void add(ChatSocket cs){
            vector.add(cs);
        }
        
        public void publish(ChatSocket cs,String out){
            for (int i = 0; i < vector.size(); i++) {
                ChatSocket csChatSocket = vector.get(i);
                if (!cs.equals(csChatSocket)) {
                    csChatSocket.out(out);
                }
            }
        }
    }


     二、客户端

    布局文件

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
    
            <EditText
                android:id="@+id/ip"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="0.6"
                android:hint="输入服务器的IP地址"
                android:text="10.0.2.2" >
    
            </EditText>
    
            <Button
                android:id="@+id/connect"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="0.4"
                android:text="连接" />
    
        </LinearLayout>
    
        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0.86" >
    
            <TextView
                android:id="@+id/text"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:text="Ready..." />
        </ScrollView>
    
        <EditText
            android:id="@+id/edit"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="在这里输入内容" />
    
        <Button
            android:id="@+id/send"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="发送" />
    
    </LinearLayout>


    Main.java

    package com.scme.aserversocket;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    
    import android.app.Activity;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements OnClickListener {
        
        private EditText ip,edit;
        private TextView text;
        
        private void init() {
            ip = (EditText) findViewById(R.id.ip);
            edit = (EditText) findViewById(R.id.edit);
            text = (TextView) findViewById(R.id.text);
            findViewById(R.id.connect).setOnClickListener(this);
            findViewById(R.id.send).setOnClickListener(this);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
        }
        
        Socket socket = null;
        BufferedWriter writer = null;
        BufferedReader reader = null;
        
        /**
         * 连接
         */
        public void connect(){
                AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>(){
                    
                    @Override
                    protected Void doInBackground(Void... params) {
                        try {
                            socket = new Socket(ip.getText().toString(), 12345);
                            writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                            publishProgress("@success");
                        } catch (Exception e) {
                            Toast.makeText(MainActivity.this, "无法建立连接", 1000).show();
                            e.printStackTrace();
                        }
                        try {
                            String line;
                            while ((line = reader.readLine())!=null) {
                                publishProgress(line);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
    
                    @Override
                    protected void onProgressUpdate(String... values) {
                        if (values[0].equals("@success")) {
                            Toast.makeText(MainActivity.this, "建立连接成功", 1000).show();
                        }
                        text.append("对方说:"+values[0]+"\n");
                        super.onProgressUpdate(values);
                    }
    
                };
                read.execute();
        }
        
        /**
         * 发送
         */
        public void send(){
            try {
                text.append("我说:"+edit.getText().toString()+"\n");
                writer.write(edit.getText().toString()+"\n");
                writer.flush();
                edit.setText("");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            //连接
            case R.id.connect:
                connect();
                break;
            //发送
            case R.id.send:
                send();
                break;
            }
        }
        
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }


    客户端任意开。。。

    还有最重要的,别忘了在主配置文件里加入网络权限啊。。。

     

    转载于:https://www.cnblogs.com/chengzhengfu/p/4581797.html

    展开全文
  • 支持单聊、群聊的网络聊天室
  • Android集成网易云IM实现 网易云信Im的登录、 单聊和建群群聊等功能,适合新手入门网易云IM通讯
  • 实现在同一个窗口实现文字群聊。和图片群发送。 服务器端: Java 客户端:Android, WP8 不过存在个问题是wp接受图片会丢失数据,接收后显示不全。如有大神解决了希望能分享一下。 实现过程中参考了...
  • 仿微信添加群聊界面——addView
  • Android XMPP实现IM 群聊功能

    千次阅读 2016-06-24 14:26:20
     android.os.Message msg = new android.os.Message();  msg.what = RECEIVE;  Bundle bd = new Bundle();  bd.putString("from", from);  bd.putString("body", message.getBody());  msg.setData(bd);  ...
  • 我正在开发一个收到信息后发送一条短信进行回复的程序(自动回复),当我的手机启动群聊程序,我的程序并没有成功的发送消息,于是我采用了如下的代码解决这个问题。 &lt;intent-filter android:priority="...
  • Android仿微信发起群聊的列表样式

    千次阅读 2018-04-24 18:57:16
    场景:今天一个朋友微信找我说碰到个问题让我看下,就是仿微信发起群聊的那个列表样式,其实这个功能实现起来没什么困难的地方,但是他遇到的问题是,最后的那个“搜索”,随着前边列表的增加或删除动态的移动,他不...
  • Android编程实战——仿微信群聊-5——Android端UI-多种显示的ListView
  • <div><p>你好,请问Android下能获取群聊群成员的群昵称吗?</p><p>该提问来源于开源项目:ppwwyyxx/wechat-dump</p></div>

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 393
精华内容 157
关键字:

android群聊