Android 大项目仿微信项目实战

  • 项目需求分析
  • 先看实现效果
  • 实现登录注册界面
  • 主界面底部导航栏
  • 用listview设置聊天界面和通讯录页面的数据
  • 发现页面设计功能
  • 日期和时间的窗口控件
  • 跳转视频号页面
  • 朋友圈的发布和删除功能


项目需求分析

  1. 实现微信的登录及注册功能
  2. 实现微信的界面左右滑屏及点击切换页面
  3. 实现微信的小部分功能

先看实现效果


Android 仿微信部分功能项目实战


实现登录注册界面

Android仿微信SwitchButton Android仿微信项目_android


使用EditText让用户填写数据

点击Button注册按钮,传入数据并且跳转登录界面,要求用户将全部数据填写完成

使用SharedPreferencesEditor进行数据的存储

实现按钮点击事件将数据传入及intent跳转Activity

SharedPreferences sp = getSharedPreferences("SP", MODE_PRIVATE);
        //存入数据
        SharedPreferences.Editor editor = sp.edit();
 re_register.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username=reusername.getText().toString();
                String country=recountry.getText().toString();
                String userphone=reuserid.getText().toString();
                String userpasswd=reuserpasswd.getText().toString();

                if (username.isEmpty() && country.isEmpty() && userphone.isEmpty() && userpasswd.isEmpty()){
                    Toast.makeText(getApplicationContext(),"请将注册信息全部填写完成",Toast.LENGTH_LONG).show();
                }else {
                    editor.putString("username",username);
                    editor.putString("country",country);
                    editor.putString("userphone",userphone);
                    editor.putString("userpasswd",userpasswd);
                    editor.commit();
                    Intent intent=new Intent();
                    intent.setClass(Bt_registerActivity.this,Bt_loginActivity.class);
                    startActivity(intent);

                }


            }
        });

登录页面判断用户输入是否和存储的数据相同

tomain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String userphone=sp.getString("userphone",null);
                String userpasswd=sp.getString("userpasswd",null);
                String lguserphone=lgphone.getText().toString();
                String lguserpasswd=lgpasswd.getText().toString();

                if (userphone.equals(lguserphone) && userpasswd.equals(lguserpasswd)){
                    Intent intent=new Intent();
                    intent.setClass(Bt_loginActivity.this,MainActivity.class);
                    startActivity(intent);
                }else {
                    Toast.makeText(getApplicationContext(),"您未注册或者账号密码不正确",Toast.LENGTH_LONG).show();
                }

主界面底部导航栏

Android仿微信SwitchButton Android仿微信项目_java_02


给底部导航栏设置view pager滑屏和点击事件

导入view pager2的依赖包

implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.viewpager2:viewpager2:1.0.0'

在xml中使用viewpager2标签 设置id

<androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
    >


    </androidx.viewpager2.widget.ViewPager2>

创建四个fragment页面添加到ArragList
创建适配器将ArragList添加进去
.registerOnPageChangeCallback实现 viewPager的滑动事件
changeTextColor() 自定义的方法 当滑动到对应fragment时底部导航栏的字体颜色、图标、顶部标题栏文字发送改变
viewPager.setCurrentItem(0);设置当前显示的页面
当点击底部导航栏的文字时也显示对应页面

ViewPager2 viewPager =findViewById(R.id.viewpager);
        fragments = new ArrayList<>();
        fragment_one=new Fragment_one();
        fragment_two=new Fragment_two();
        fragment_three=new Fragment_three();
        fragment_four=new Fragment_four();
        fragments.add(fragment_one);
        fragments.add(fragment_two);
        fragments.add(fragment_three);
        fragments.add(fragment_four);

        MyFragmentPagerAdapter pagerAdapter=new MyFragmentPagerAdapter(getSupportFragmentManager(),getLifecycle(),fragments);   //确定适配进来的adapter有多少个
        viewPager.setAdapter(pagerAdapter);
        viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }

            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                changeTextColor(position);
                wx.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        viewPager.setCurrentItem(0);
                    }
                });
                txl.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        viewPager.setCurrentItem(1);
                    }
                });
                fx.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        viewPager.setCurrentItem(2);
                    }
                });
                wd.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        viewPager.setCurrentItem(3);
                    }
                });

            }

            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });
    }

    public void changeTextColor(int position){
        switch (position){
            case R.id.wx:
                viewPager.setCurrentItem(0);
            case 0:
                wx.setTextColor(Color.parseColor("#FF03DAC5"));
                txl.setTextColor(Color.parseColor("#FF000000"));
                fx.setTextColor(Color.parseColor("#FF000000"));
                wd.setTextColor(Color.parseColor("#FF000000"));
                setTitle(titles[0]);
                mimg1.setImageResource(R.drawable.wx_1);
                mimg2.setImageResource(R.drawable.txl);
                mimg3.setImageResource(R.drawable.fx);
                mimg4.setImageResource(R.drawable.w);

                break;
            case R.id.txl:
                viewPager.setCurrentItem(1);
            case 1:
                wx.setTextColor(Color.parseColor("#FF000000"));
                txl.setTextColor(Color.parseColor("#FF03DAC5"));
                fx.setTextColor(Color.parseColor("#FF000000"));
                wd.setTextColor(Color.parseColor("#FF000000"));
                setTitle(titles[1]);
                mimg1.setImageResource(R.drawable.wx);
                mimg2.setImageResource(R.drawable.txl_1);
                mimg3.setImageResource(R.drawable.fx);
                mimg4.setImageResource(R.drawable.w);
                break;
            case R.id.fx:
                viewPager.setCurrentItem(2);
            case 2:
                wx.setTextColor(Color.parseColor("#FF000000"));
                txl.setTextColor(Color.parseColor("#FF000000"));
                fx.setTextColor(Color.parseColor("#FF03DAC5"));
                wd.setTextColor(Color.parseColor("#FF000000"));
                setTitle(titles[2]);
                mimg1.setImageResource(R.drawable.wx);
                mimg2.setImageResource(R.drawable.txl);
                mimg3.setImageResource(R.drawable.fx_1);
                mimg4.setImageResource(R.drawable.w);
                break;
            case R.id.wd:
                viewPager.setCurrentItem(3);
            case 3:
                wx.setTextColor(Color.parseColor("#FF000000"));
                txl.setTextColor(Color.parseColor("#FF000000"));
                fx.setTextColor(Color.parseColor("#FF000000"));
                wd.setTextColor(Color.parseColor("#FF03DAC5"));
                setTitle(titles[3]);
                mimg1.setImageResource(R.drawable.wx);
                mimg2.setImageResource(R.drawable.txl);
                mimg3.setImageResource(R.drawable.fx);
                mimg4.setImageResource(R.drawable.w_1);
                break;

        }

用listview设置聊天界面和通讯录页面的数据

获取list view,和单个list_item中的ImageView和TextView的id
将list_item中图片资源和文字通过List<Map<String, Object>> 存放进去
创建SimpleAdapter适配器 将map中的数据适配
lv2 = view.findViewById(R.id.lv2);
        int[] images = {R.mipmap.tjhy,R.mipmap.ql,R.mipmap.bq,R.mipmap.gzh,R.mipmap.dyh, R.mipmap.wxyd, R.mipmap.dyhxx,R.mipmap.tx1,R.mipmap.tx2,R.mipmap.tx3,R.mipmap.tx4};
        String[] names1 = {"新的朋友","群聊","标签","公众号","订阅号", "微信团队", "订阅号消息","会飞的猪","QQ","近邻宝","携程旅游"};

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < images.length; i++) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("twoimg", images[i]);
            map.put("twoname", names1[i]);
            list.add(map);
        }
        adapter_two = new SimpleAdapter(getActivity(), list,
                R.layout.fragment_two_item, new String[]{"twoimg", "twoname"},
                new int[]{R.id.two_img, R.id.two_tv});

        lv2.setAdapter(adapter_two);

发现页面设计功能

Android仿微信SwitchButton Android仿微信项目_数据_03

日期和时间的窗口控件

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        rq.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onCreateDialog(DATEDIA).show();
            }
        });
        sj.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onCreateDialog(TIMEDIA).show();
            }
        });
    }

    protected Dialog onCreateDialog(int id) {
        final Calendar calendar =Calendar.getInstance();
        myear=calendar.get(Calendar.YEAR);
        mmonth=calendar.get(Calendar.MONTH);
        mday=calendar.get(Calendar.DAY_OF_MONTH);
        switch (id){
            case DATEDIA:
                return  new DatePickerDialog(getActivity(),mDateListener,myear,mmonth,mday);
            case TIMEDIA:
                return  new TimePickerDialog(getActivity(),mTimeListener,mhour,mminute,false);
        }

        return null;
    }



    private DatePickerDialog.OnDateSetListener mDateListener= new DatePickerDialog.OnDateSetListener() {
        @Override
        public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
            myear = year;
            mmonth = month;
            mday = dayOfMonth;
        }
    };
    private TimePickerDialog.OnTimeSetListener mTimeListener=new TimePickerDialog.OnTimeSetListener() {
        @Override
        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
            mhour=hourOfDay;
            mminute=minute;
        }
    };

跳转视频号页面

Android仿微信SwitchButton Android仿微信项目_ide_04

简单使用了videoview 获取网路uri播放视频

videoView=findViewById(R.id.video);
        videoView.setMediaController(new MediaController(this));

        videoView.setVideoPath("https://stream7.iqilu.com/10339/upload_transcode/202002/18/20200218093206z8V1JuPlpe.mp4");
        videoView.start();

朋友圈的发布和删除功能

pyqlist = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < pyq_tv1.length; i++) {

            map = new HashMap<String, Object>();
            map.put("pyq_img",pyq_img[i]);
            map.put("time",pyq_time[i]);
            map.put("pyq_tv1", pyq_tv1[i]);
            map.put("pyq_tv2", pyq_tv2[i]);
            pyqlist.add(map);

        }
        Collections.reverse(pyqlist);
        pyqadapter=new SimpleAdapter(getApplicationContext(),pyqlist,R.layout.pyq_item,new String[]{"pyq_img","time","pyq_tv1", "pyq_tv2"},new int[]{R.id.pyq_img,R.id.pyq_time,R.id.pyqtv1, R.id.pyqtv2});
        pyqlistview.setAdapter(pyqadapter);

        pyqadd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                    Calendar calendar = Calendar.getInstance();
                    int hour = calendar.get(Calendar.HOUR_OF_DAY);
                    int minute = calendar.get(Calendar.MINUTE);
                    String time= hour+":"+minute;
                    int img=R.mipmap.wdtx;
                    String et2=pyq_et2.getText().toString();
                    if (et2.isEmpty()){
                        Toast.makeText(getApplicationContext(),"您需要输入文字才能发送哦!",Toast.LENGTH_LONG).show();
                    }else {
                        Collections.reverse(pyqlist);
                        map2=new HashMap<>();
                        map2.put("pyq_img",img);
                        map2.put("time",time);
                        map2.put("pyq_tv1", et1);
                        map2.put("pyq_tv2", et2);
                        pyqlist.add(map2);
                        Collections.reverse(pyqlist);
                        pyqlistview.setAdapter(pyqadapter);
                    }


            }
        });

        AlertDialog.Builder builder=new AlertDialog.Builder(this);
        pyqlistview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                                    long arg3) {
                Map<String, Object> map = pyqlist.get(arg2);

                builder.setTitle("删除动态");
                builder.setMessage("您真的要删除这条动态嘛");
                builder.setPositiveButton("删除", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        pyqlist.remove(arg2);
                        pyqadapter.notifyDataSetChanged();// 更新列表数据
                        dialogInterface.cancel();
                    }
                });
                builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.cancel();
                    }
                });
                AlertDialog alertDialog =builder.create();
                alertDialog.show();

            }
        });