安卓仿QQ空间实现(含图片的动态编辑、发表、点赞、评论)

之前做项目的时候需要用到仿空间动态的功能,在此做一下记录,简单介绍一下listview自定义适配器以及各相关功能实现方法。

一、效果图

在这里插入图片描述
这里添加了两条初始动态,其他都是现编现发的。头像这里后面使用了圆形图片控件。
在这里插入图片描述
动态评论以及点赞功能实现⬆

在这里插入图片描述
动态编辑与发表功能⬆(这个照片是我摸黑拍的,显示并没有问题,并且因为时间比较长降低了gif的图片质量)

二、功能需求

1、仿空间动态界面

2、评论与点赞。

3、发表动态(图片+文字)。

三、 功能实现(主要代码)

1、首先定义一个实体类Dynamic,作为ListView的适配类型。

public class Dynamic {
    
    
    private int iv_head,imagev1;
    private String tv_name;
    private String tv_time;
    private String tv_content;
    private String ll_comment;
    private String ivfilepath1;
    private String ivfilepath2;
    private String ivfilepath3;



    public String getTv_dolike() {
    
    
        return tv_dolike;
    }

    public void setTv_dolike(String tv_dolike) {
    
    
        this.tv_dolike = tv_dolike;
    }

    private String tv_dolike;


    public void setTv_time(String tv_time) {
    
    
        this.tv_time = tv_time;
    }

    public int getImagev1() {
    
    
        return imagev1;
    }

    public Dynamic(int iv_head, String tv_name, String tv_content, String ivfilepath1, String ivfilepath2, String ivfilepath3, String tv_time, int imagev1) {
    
    
        this.iv_head = iv_head;
        this.ivfilepath1=ivfilepath1;
        this.ivfilepath2=ivfilepath2;
        this.ivfilepath3=ivfilepath3;
        this.imagev1=imagev1;


        this.tv_name = tv_name;
        this.tv_time = tv_time;
        this.tv_content = tv_content;
    }

    public int getIv_head() {
    
    
        return iv_head;
    }

    public String getIvfilepath1() {
    
    
        return ivfilepath1;
    }
    public String getIvfilepath2() {
    
    
        return ivfilepath2;
    }
    public String getIvfilepath3() {
    
    
        return ivfilepath3;
    }

    public String getTv_name() {
    
    
        return tv_name;
    }

    public String getTv_time() {
    
    
        return tv_time;
    }

    public String getTv_content() {
    
    
        return tv_content;
    }

    public String getLl_comment() {
    
    
        return ll_comment;
    }
}

2、自定义适配器DynamicAdapter,我这里使用的适配器继承自ArrayAdapter,适配器作为后端数据与前端界面交互的桥梁是十分重要的,也是实现定制ListView的关键。

//设置点赞事件,点赞图标变化
        viewHolder.iv_like.setOnClickListener (new OnClickListener () {
    
    
            @Override
            public void onClick(View view) {
    
    

                if (!islike) {
    
    
                    viewHolder.tv_dolike.setText (username+"觉得很赞");
                    viewHolder.iv_like.setImageResource (R.mipmap.like);
                    Toast.makeText (getContext (), "点赞成功", Toast.LENGTH_SHORT).show ();
                    islike = true;
                } else {
    
    
                    viewHolder.tv_dolike.setText ("");
                    viewHolder.iv_like.setImageResource (R.mipmap.nolike);
                    Toast.makeText (getContext (), "取消点赞", Toast.LENGTH_SHORT).show ();
                    islike = false;
                }
            }
        });

        //给每一条动态设置内容
        viewHolder.iv_head.setImageResource (dynamic.getIv_head ());
        viewHolder.tv_name.setText (dynamic.getTv_name ());
        viewHolder.tv_content.setText (dynamic.getTv_content ());
        viewHolder.tv_time.setText (dynamic.getTv_time ());

        Bitmap bitmap1 = BitmapFactory.decodeFile (dynamic.getIvfilepath1 ());
        viewHolder.iv_content1.setImageBitmap (bitmap1);
        Bitmap bitmap2 = BitmapFactory.decodeFile (dynamic.getIvfilepath2 ());
        viewHolder.iv_content2.setImageBitmap (bitmap2);
        Bitmap bitmap3 = BitmapFactory.decodeFile (dynamic.getIvfilepath3 ());
        viewHolder.iv_content3.setImageBitmap (bitmap3);
        if(dynamic.getImagev1 ()!=0){
    
    
            viewHolder.iv_content1.setImageResource (dynamic.getImagev1 ());
        }



        //点击评论图标获取edittext焦点
        viewHolder.Iv_comment.setOnClickListener (
                new OnClickListener () {
    
    
            @Override
            public void onClick(View view) {
    
    
                Log.e ("onClick: ", "获取焦点");
                if (viewHolder.et_comment.isFocused ()) {
    
    
                } else {
    
    
                    viewHolder.et_comment.requestFocus ();
                    viewHolder.et_comment.setFocusableInTouchMode (true);
                    InputMethodManager inputManager =
                            (InputMethodManager) viewHolder.et_comment.getContext          ().getSystemService (Context.INPUT_METHOD_SERVICE);
                    inputManager.showSoftInput (viewHolder.et_comment, 0);


                }
            }
        });


        //评论监听
        viewHolder.et_comment.setOnTouchListener (new View.OnTouchListener () {
    
    
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
    
    
                Log.e ("onTouch: ", "发表");



                Drawable drawable = viewHolder.et_comment.getCompoundDrawables ()[2];
                //排除非按压图标事件
                if (motionEvent.getAction () != MotionEvent.ACTION_UP) {
    
    
                    return false;
                }
                if (motionEvent.getX () > viewHolder.et_comment.getWidth () - drawable.getIntrinsicWidth () - viewHolder.et_comment.getPaddingRight ()) {
    
    
                    //取出评论
                    String commentStr = viewHolder.et_comment.getText ().toString ().trim ();
                    if (TextUtils.isEmpty (commentStr)) {
    
    
                        Toast.makeText (getContext (), "评论内容不能为空", Toast.LENGTH_SHORT).show ();
                    } else {
    
    
                        addView (commentStr, viewHolder.ll_comment);
                        viewHolder.et_comment.setText ("");
                        Toast.makeText (getContext (), "发表成功", Toast.LENGTH_SHORT).show ();

                    }

                }
                return false;
            }

        });
        return view;


    }

    //动态添加textview实现评论
    private void addView(String string, LinearLayout linearLayout) {
    
    
        Log.e ("addView: ", "添加评论");
        TextView textView = new TextView (getContext ());
        textView.setText (username+": "+string);
        textView.setTextSize (15);
        linearLayout.addView (textView);
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams ();
        layoutParams.setMargins (0, 0, 0, 20);
        textView.setLayoutParams (layoutParams);
    }


①ListView效率优化

每次Listview的子项滑动到屏幕内时会自动调用getView()方法,重复加载布局及获得控件实例会导致ListView的运行效率降低,这里用到了convertView参数将之前加载好的布局缓存,并且自定义了内部ViewHodler类用来缓存控件实例,进行ListView运行效率的优化。

②动态评论功能的实现

首先实例化一个TextView对象,设置好textView的内容与样式,然后添加进布局容器,通过LayoutParams设置textView的布局参数。

③适配器的构造函数
用于在Activity中实例化自定义适配器对象,并且这里构造函数中我取得了listview每个子项目的布局文件,对它进行操作。

3、下面是Activity代码,这里有两个界面,空间动态主界面MainActivity和编辑动态界面WriteActivity。
① WriteActivity

   //发表动态
    buttonPublish.setOnClickListener (new View.OnClickListener () {
    
    
        @Override
        public void onClick(View view) {
    
    
            //取得数据
            String stringArticle = editTextArticle.getText ().toString ().trim ();
            Date date=new Date ();
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("MM-dd HH:mm");
            stringCurrenttime=simpleDateFormat.format (date);


            //创建传递数据的intent对象
            Intent intent1 = new Intent ();

           //存放数据
            intent1.putExtra ("editArticle", stringArticle);
            intent1.putExtra ("photoPath1",imagename1);
            intent1.putExtra ("photoPath2",imagename2);
            intent1.putExtra ("photoPath3",imagename3);
            intent1.putExtra ("stringCurrenttime",stringCurrenttime);

            setResult (RESULT_OK, intent1);
            finish ();

        }
    });

    //初始化发表按钮状态
    buttonPublish.setPressed (true);
    buttonPublish.setClickable (false);

    //设置取消按钮
    buttonCancle.setOnClickListener (new View.OnClickListener () {
    
    

        @Override
        public void onClick(View view) {
    
    
            buttonCancle.setVisibility (View.INVISIBLE);
            finish ();
        }
    });

      

        //文本监听
        editTextArticle.addTextChangedListener (new TextWatcher () {
    
    
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
    
                Log.e ("beforeTextChanged: ", "初试结果");
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
    
                Log.e ("onTextChanged: ", "进行结果");

            }

            @Override
            public void afterTextChanged(Editable editable) {
    
    
                Log.e ("afterTextChanged: ", "最终结果");
                if (editable.toString ().equals ("")&&imageView2.getDrawable ()==null) {
    
    
                    buttonPublish.setPressed (true);
                    buttonPublish.setClickable (false);
                } else {
    
    
                    buttonPublish.setPressed (false);
                    buttonPublish.setClickable (true);
                }

            }
        });
}

//点击拍摄
@Override
public void onClick(View view) {
    
    
    Intent intentPhoto = new Intent (MediaStore.ACTION_IMAGE_CAPTURE);
    switch (view.getId ()) {
    
    

        case R.id.Iv_image1:
            if (isclickable1) {
    
    
                Log.e ("onClick: ", "拍照");

                startActivityForResult (intentPhoto, 100);
            } else {
    
    
            }
            break;
        case R.id.Iv_image2:
            if (isclickable2) {
    
    
                startActivityForResult (intentPhoto, 99);
            } else {
    
    
            }

            break;
        case R.id.Iv_image3:
            if (isclickable3) {
    
    

                startActivityForResult (intentPhoto, 98);
            } else {
    
    
            }
            break;

    }
}

//取出照片并显示
protected void onActivityResult(int a, int b, Intent c) {
    
    
    super.onActivityResult (a, b, c);
    ImageView imageViewPhoto1, imageViewPhoto2, imageViewPhoto3;
    imageViewPhoto1 = findViewById (R.id.Iv_image1);
    imageViewPhoto2 = findViewById (R.id.Iv_image2);
    imageViewPhoto3 = findViewById (R.id.Iv_image3);

    if (b == Activity.RESULT_OK) {
    
    
        if (a == 100) {
    
    

            //取出图片
            Bundle bd = c.getExtras ();
            bitmap = (Bitmap) bd.get ("data");


            //获取当前时间得到路径
            Date date=new Date ();
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
            stringDate1=simpleDateFormat.format (date);
           imagename1="/"+stringDate1+".jpg";
            Bitmap copyBitmap=createBitmap(bitmap,imagename1);

            //显示拍摄照片
            imageViewPhoto1.setScaleType (ImageView.ScaleType.CENTER_CROP);
            imageViewPhoto1.setImageBitmap (copyBitmap);


            //显示拍摄按钮
            imageViewPhoto2.setVisibility (View.VISIBLE);
            imageViewPhoto2.setImageResource (R.drawable.photoscale);
            buttonPublish.setClickable (true);
            buttonPublish.setPressed (false);
            isclickable1 = false;


        }
        if (a == 99) {
    
    
            Bundle bd = c.getExtras ();
            bitmap = (Bitmap) bd.get ("data");
            //获取当前时间得到路径
            Date date=new Date ();
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
            stringDate2=simpleDateFormat.format (date);
             imagename2="/"+stringDate2+".jpg";
            Bitmap copyBitmap=createBitmap(bitmap,imagename2);

            //显示拍摄照片
            imageViewPhoto2.setScaleType (ImageView.ScaleType.CENTER_CROP);
            imageViewPhoto2.setImageBitmap (copyBitmap);           //显示拍摄按钮
            imageViewPhoto3.setVisibility (View.VISIBLE);
            imageViewPhoto3.setImageResource (R.drawable.photoscale);
            isclickable2 = false;


        }
        if (a == 98) {
    
    
            Bundle bd = c.getExtras ();
            bitmap = (Bitmap) bd.get ("data");
            //获取当前时间得到路径
            Date date=new Date ();
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
            stringDate3=simpleDateFormat.format (date);
            imagename3="/"+stringDate3+".jpg";
            Bitmap copyBitmap=createBitmap(bitmap,imagename3);
            //显示拍摄照片
            imageViewPhoto3.setScaleType (ImageView.ScaleType.CENTER_CROP);
            imageViewPhoto3.setImageBitmap (copyBitmap);
            isclickable3 = false;
        }

    }
    else {
    
    
            Toast.makeText (this, "没有拍摄照片", Toast.LENGTH_SHORT).show ();
        }



}




private  Bitmap createBitmap(Bitmap bitmap,String photoname){
    
    
    //剪裁图片
    int W=bitmap.getWidth ();
    int H=bitmap.getHeight ();
    Bitmap newBitmap;

    if (W>H){
    
    
    newBitmap=bitmap.createBitmap (bitmap,(W-H)/2,0,H,H);
    }
    else {
    
    
        newBitmap=bitmap.createBitmap (bitmap,0,(H-W)/2,W,W);

    }

    //将照片缓存至本地
    File fileimage;

    try {
    
    
        fileimage=new File (getCacheDir ()+photoname);
        if(!fileimage.exists ()){
    
    
            fileimage.getParentFile ().mkdirs ();
            fileimage.createNewFile ();
        }
        FileOutputStream fos=new FileOutputStream (fileimage);
        newBitmap.compress (Bitmap.CompressFormat.JPEG,100,fos);
        fos.flush ();
        fos.close ();
    } catch (IOException e) {
    
    
        e.printStackTrace ();
    }


    return newBitmap;
}

这里利用了系统时间以得到不同的照片命名并存储至本地。此外这里有关文件的操作后续要深入了解一下。

②MainActivity

//新增动态显示数据
@Override
protected  void onActivityResult(int requestCode, int resultCode, Intent data){
    
    
    super.onActivityResult (requestCode,resultCode,data);
    switch(requestCode){
    
    
        case 1:


            if (resultCode==RESULT_OK){
    
    
                String  stringArticle=data.getStringExtra ("editArticle");

                **//得到图片路径
                String imagepath1=get**CacheDir ()+data.getStringExtra ("photoPath1");
                String imagepath2=getCacheDir ()+data.getStringExtra ("photoPath2");
                String imagepath3=getCacheDir ()+data.getStringExtra ("photoPath3");

                // 获得发表时间
                String  stringCurrenttime=data.getStringExtra ("stringCurrenttime");     
                Dynamic C=new Dynamic (R.drawable.myhead,"admin",stringArticle,imagepath1,imagepath2,imagepath3,stringCurrenttime,0);

                dynamicList.add(0,C);

                listView.setAdapter (adapter);  
                Toast.makeText (getApplicationContext (),"发表成功",Toast.LENGTH_SHORT).show ();



            }
            break;
    }

这里要注意的是,listView中的数据刷新后要重新setAdapter,否则界面动态数据无法刷新。

四、最后

我写这些博客主要是为了加深自己的理解,也供后续回顾,有什么建议与想法大家都可以在下方评论或者私信我,互相交流共同进步。

猜你喜欢

转载自blog.csdn.net/qq_44706002/article/details/104880836