安卓 类微信开发(三)

目录

一、主要内容

二、核心代码

三、效果展示


 

在上次的基础上: 安卓 类微信开发(二)_qingsongxyz的博客-CSDN博客

一、主要内容

完成好友聊天界面的开发和activity之间的数据传递

二、核心代码

编写ChatActivity.xml好友聊天界面UI:




    
    

        

        

        
    

    

    

    
    

    

        


        

        

        

        

安卓 类微信开发(三)_第1张图片

在网上公共库找到封装过的TextView样式进行导入(导入外部库):

修改如下文件settings.gradle

安卓 类微信开发(三)_第2张图片

安卓 类微信开发(三)_第3张图片

修改如下文件build.gradle(Module):

安卓 类微信开发(三)_第4张图片

安卓 类微信开发(三)_第5张图片

下面开始使用外部库

编写好友发送的聊天消息样式文件layout_message_left_item.xml:




    

    


        

        

            

        
    

安卓 类微信开发(三)_第6张图片

 编写自己发送的聊天消息样式文件layout_message_right_item.xml:




    

    

        

            
        

        
    

安卓 类微信开发(三)_第7张图片

这里创建一个工具类DrawableUtil 进行图片转换为字节数组的操作(后面需要使用):

public class DrawableUtil {
    public static Bitmap drawableToBitmap(Drawable drawable) {
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        // System.out.println("Drawable转Bitmap");
        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
        Bitmap bitmap = Bitmap.createBitmap(w,h,config);
        //注意,下面三行代码要用到,否在在View或者surfaceview里的canvas.drawBitmap会看不到图
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

    public static byte[] bitmapToBytes(Bitmap bm){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }
}

然后编写activity_chat.xml中RecyclerView对应的MessageAdapter类:

注意: 使用ViewType属性动态控制MessageAdapter加载哪一个样式文件,用于区分好友发送的消息和自己发送的消息。

public class MessageAdapter extends RecyclerView.Adapter {

    private final static int I = 0;

    private final static int OTHERS = 1;

    private Context context;

    private List> data;

    public MessageAdapter(Context context, List> data) {
        this.context = context;
        this.data = data;
    }

    @Override
    public int getItemViewType(int position) {
        if(data.get(position).get("type").toString().equals("I"))
        {
            return I;
        }
        else{
            return OTHERS;
        }
    }

    @NonNull
    @Override
    public MessageAdapter.MessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if(viewType == OTHERS) {
            return new MessageViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_message_left_item, parent, false));
        }
        else
        {
            return new MessageViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_message_right_item, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(@NonNull MessageAdapter.MessageViewHolder holder, int position) {
        if(data.get(position).get("type").toString().equals("I"))
        {
            holder.imageView_right.setImageResource(R.drawable.car);
            holder.right_textView1.setText(data.get(position).get("time").toString());
            holder.right_textView2.setText(data.get(position).get("message").toString());
        }
        else
        {
            byte[] bytes = (byte[]) data.get(position).get("avatars");
            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            holder.imageView_left.setImageBitmap(bitmap);
            holder.left_textView1.setText(data.get(position).get("time").toString());
            holder.left_textView2.setText(data.get(position).get("message").toString());
        }
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    public class MessageViewHolder extends RecyclerView.ViewHolder {

        TextView left_textView1, left_textView2, right_textView1, right_textView2;

        ImageView imageView_left, imageView_right;

        public MessageViewHolder(@NonNull View itemView) {
            super(itemView);
            left_textView1 = itemView.findViewById(R.id.layout_message_left_item_time);
            left_textView2 = itemView.findViewById(R.id.layout_message_left_item_content);
            imageView_left = itemView.findViewById(R.id.layout_message_left_item_imageView1);

            right_textView1 = itemView.findViewById(R.id.layout_message_right_item_time);
            right_textView2 = itemView.findViewById(R.id.layout_message_right_item_content);
            imageView_right = itemView.findViewById(R.id.layout_message_right_item_imageView1);

        }
    }
}

修改ChatAdapter类(添加点击RecyclerView中的item的相关代码):

public class ChatAdapter extends RecyclerView.Adapter {

    private Context context;

    private List> data;

    private OnItemClickListener onItemClickListener;

    public ChatAdapter(Context context, List> data) {
        this.context = context;
        this.data = data;
    }

    /**
     * 定义 RecyclerView 选项单击事件的回调接口
     */
    public interface OnItemClickListener{
        void onItemClick(View view, Map data);
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @NonNull
    @Override
    public ChatViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ChatViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_chat_item, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull ChatViewHolder holder, int position) {
        holder.textView1.setText(data.get(position).get("name").toString());
        holder.textView2.setText(data.get(position).get("message").toString());
        holder.textView3.setText(data.get(position).get("time").toString());
        holder.imageView.setImageResource(Integer.parseInt(data.get(position).get("avatars").toString()));
    }


    @Override
    public int getItemCount() {
        return data.size();
    }

    public class ChatViewHolder extends RecyclerView.ViewHolder {

        TextView textView1, textView2, textView3;

        ImageView imageView;

        public ChatViewHolder(@NonNull View itemView) {
            super(itemView);
            textView1 = itemView.findViewById(R.id.layout_chat_item_textView1);
            textView2 = itemView.findViewById(R.id.layout_chat_item_textView2);
            textView3 = itemView.findViewById(R.id.layout_chat_item_textView3);
            imageView = itemView.findViewById(R.id.layout_chat_item_imageView);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //此处回传点击监听事件
                    if(onItemClickListener!=null){
                        onItemClickListener.onItemClick(v, data.get(getLayoutPosition()));
                    }
                }
            });
        }
    }
}

修改ChatFragment类,调用chatAdapter类的点击事件,完成Activity之间的跳转和信息传递:

public class ChatFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{

    private View view;
    private RecyclerView fragment_chat_recyclerView;
    private SwipeRefreshLayout swipeRefreshLayout;
    private ChatAdapter chatAdapter;
    private Context context;
    private List> chatData = new ArrayList<>();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.fragment_chat, container, false);

        fragment_chat_recyclerView = view.findViewById(R.id.fragment_chat_recyclerView);
        swipeRefreshLayout = view.findViewById(R.id.fragment_chat_swipeRefreshLayout);
        context = getContext();
        
        initData();
        configSwipeRefreshLayout();

        chatAdapter = new ChatAdapter(context, chatData);
        chatAdapter.setOnItemClickListener(new ChatAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, Map data) {
                ImageView avatars = view.findViewById(R.id.layout_chat_item_imageView);
                TextView name = view.findViewById(R.id.layout_chat_item_textView1);
                TextView message = view.findViewById(R.id.layout_chat_item_textView2);
                TextView time = view.findViewById(R.id.layout_chat_item_textView3);

                //跳转
                Intent intent = new Intent(context, ChatActivity.class);
                Bundle bundle = new Bundle();

                //将图片转换成字节数组传递
                Bitmap bitmap = DrawableUtil.drawableToBitmap(avatars.getDrawable());
                byte[] bytes = DrawableUtil.bitmapToBytes(bitmap);

                bundle.putByteArray("avatars", bytes);
                bundle.putString("name", name.getText().toString());
                bundle.putString("message", message.getText().toString());
                bundle.putString("time", time.getText().toString());
                if(message.getText().toString().contains("我:"))
                {
                    bundle.putString("type", "I");
                }
                else
                {
                    bundle.putString("type", "others");
                }
                bundle.putInt("requestCode", 1);
                intent.putExtras(bundle);
                startActivityForResult(intent, 1);
            }
        });
        LinearLayoutManager manager = new LinearLayoutManager(context);
        manager.setOrientation(RecyclerView.VERTICAL);
        fragment_chat_recyclerView.setLayoutManager(manager);
        fragment_chat_recyclerView.setAdapter(chatAdapter);
        return view;
    }

    private void configSwipeRefreshLayout() {
        swipeRefreshLayout.setSize(CircularProgressDrawable.LARGE);
        swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
                android.R.color.system_accent1_200, android.R.color.system_neutral2_300);
        swipeRefreshLayout.setOnRefreshListener(this);
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 1 && resultCode == 1)
        {
            Bundle bundle = data.getExtras();
            String name = bundle.getString("name");
            String message = bundle.getString("message");
            String time = bundle.getString("time");
            //更新聊天记录
            for (int i = 0; i < chatData.size(); i++) {
                if(chatData.get(i).get("name").toString().equals(name))
                {
                    chatData.get(i).put("message", "我:" + message);
                    chatData.get(i).put("time", time);
                    chatAdapter.notifyItemChanged(i);
                    break;
                }
            }
        }
    }

    private void initData() {
        String[] name = {"倚楼听风雨", "璎婲", "の大脸猫", "静秋┐", ">.<",
                "旧街凉风", "初見", "雨嘉ψ", "鸢尾*", "凉栀"};
        String[] message = {"在吗?", "哈哈哈", "...", "呜呜呜", "呵呵",
                "吃饭了吗?", "~~~", "今天有空吗?", "出去玩呀", "爱你哟"};
        String[] time = {"12:10", "昨天", "3月15日", "3月15日", "3月15日",
                "9:00", "5:00", "4月17日", "18:00", "9月1日"};
        Integer[] avatars = {R.drawable.avatars1, R.drawable.avatars2, R.drawable.avatars3,
                R.drawable.avatars4, R.drawable.avatars5, R.drawable.avatars6,
                R.drawable.avatars7, R.drawable.avatars8, R.drawable.avatars9,
                R.drawable.avatars10,};

        for (int i = 0; i < name.length; i++) {
            HashMap d = new HashMap<>();
            d.put("name", name[i]);
            d.put("message", message[i]);
            d.put("time", time[i]);
            d.put("avatars", avatars[i]);
            chatData.add(d);
        }
    }

    @Override
    public void onRefresh() {
        //延时2s
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                swipeRefreshLayout.setRefreshing(false);
            }
        }, 3000);
    }
}

编写ChatActivity类,接受信息进行处理:

public class ChatActivity extends AppCompatActivity {

    private List> data = new ArrayList<>();

    private RecyclerView recyclerView;

    private TextView textView1;
    
    private ImageView back, more;
    
    private Button button1;

    private EditText editText;

    private LinearLayout linearLayout;

    private Boolean isSend = false;

    private Map result = new HashMap<>();

    private Intent intent;

    private String name;

    private MessageAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        linearLayout = findViewById(R.id.activity_chat_layout);
        recyclerView = findViewById(R.id.activity_chat_recyclerView);
        textView1 = findViewById(R.id.activity_chat_textView1);
        back = findViewById(R.id.activity_chat_imageView_back);
        more = findViewById(R.id.activity_chat_imageView_more);
        button1 = findViewById(R.id.activity_chat_button);
        editText = findViewById(R.id.activity_chat_editText);

        intent = getIntent();
        Bundle bundle = intent.getExtras();
        byte[] avatars = bundle.getByteArray("avatars");
        name = bundle.getString("name");
        String message = bundle.getString("message");
        String time = bundle.getString("time");
        String type = bundle.getString("type");
        int requestCode = bundle.getInt("requestCode");

        if(requestCode == 1)
        {
            textView1.setText(name);

            Map map = new HashMap<>();
            map.put("avatars", avatars);
            map.put("message", message);
            map.put("time", time);
            map.put("type", type);
            data.add(map);

            adapter = new MessageAdapter(this, data);
            LinearLayoutManager manager = new LinearLayoutManager(this);
            manager.setOrientation(RecyclerView.VERTICAL);
            recyclerView.setLayoutManager(manager);
            recyclerView.setAdapter(adapter);
        }

        setbackListener();
        setEditTextListener();
        setSendMsgListener();
    }

    /**
     * 监听输入框是否失去焦点进行按钮的切换
     */
    private void setEditTextListener() {
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean hasFocus) {
                if(hasFocus)
                {
                    more.setVisibility(View.GONE);
                    button1.setVisibility(View.VISIBLE);
                }else
                {
                    more.setVisibility(View.VISIBLE);
                    button1.setVisibility(View.GONE);
                }
            }
        });
    }

    private void setSendMsgListener() {
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!editText.getText().toString().trim().equals(""))
                {
                    isSend = true;
                    result.put("message", editText.getText().toString());
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM月dd日 HH:mm");
                    simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
                    result.put("time", simpleDateFormat.format(new Date()));
                    result.put("type", "I");
                    data.add(result);
                    //清楚输入的聊天信息并失去焦点
                    editText.setText("");
                    editText.clearFocus();
                    adapter.notifyItemInserted(data.size() - 1);
                }
            }
        });
    }

    /**
     * 返回主菜单
     */
    private void setbackListener() {
        back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //如果发送了新的消息,返回主界面时要更新信息
                int resultCode = 0;
                Bundle bundle = new Bundle();
                if(isSend)
                {
                    resultCode = 1;
                    bundle.putString("name", name);
                    bundle.putString("message", result.get("message").toString());
                    bundle.putString("time", result.get("time").toString());
                    bundle.putInt("resultCode", 1);
                }
                else
                {
                    bundle.putInt("resultCode", 0);
                }
                intent.putExtras(bundle);
                setResult(resultCode, intent);
                finish();
            }
        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // TODO Auto-generated method stub
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            // 获得当前得到焦点的View,一般情况下就是EditText(特殊情况就是轨迹求或者实体案件会移动焦点)
            View v = getCurrentFocus();
            if (isShouldHideInput(v, ev)) {
                //关闭键盘,并让输入框失去焦点
                hideSoftInput(v.getWindowToken());
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时没必要隐藏
     *
     * @param v
     * @param event
     * @return
     */
    private boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] l = { 0, 0 };
            v.getLocationInWindow(l);
            int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
                // 点击EditText的事件,忽略它。
                return false;
            } else {
                return true;
            }
        }
        // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditView上,和用户用轨迹球选择其他的焦点
        return false;
    }

    /**
     * 隐藏键盘
     *
     * @param token
     */
    private void hideSoftInput(IBinder token) {
        if (token != null) {
            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }
}

细节处理:

1.好友聊天界面弹出键盘会影响页面布局:

修改AndroidManifest.xml,在相应的Activity添加一下两行解决:

android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan"

安卓 类微信开发(三)_第8张图片

2.设置button颜色不生效:

修改一下两个文件即可:

将 parent="Theme.MaterialComponents.DayNight.DarkActionBar"改Theme.MaterialComponents.DayNight.NoActionBar.Bridge,在设置按钮颜色即可

安卓 类微信开发(三)_第9张图片

三、效果展示

仓库地址:青松xyz/WechatForm

你可能感兴趣的:(Android,android,java,android-studio)