Android 高仿微信朋友圈拍照上传功能

模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy!

1. PhotoPicker的使用

这是一个支持选择多张图片,点击图片放大,图片之间左右滑动互相切换的库,同时支持图片删除的库,效果类似微信。

(1) 添加PhotoPicker的架包

(2) 使用

选择图片:安卓6.0以后需要在代码中添加读写sd卡和相机的权限 当然清单文件中也需要添加的

 PhotoPicker.builder()
        .setPhotoCount(maxPhoto) //设置最多选择的图片数量
        .setShowCamera(true)  //是否显示相机按钮
        .setSelected(photos)  //设置已经选好的图片
        .start(SendDynamicActivity.this); //上下文参数 需要传activity

查看图片:

PhotoPreview.builder()
        .setPhotos(photos) //设置选择好的图片
        .setCurrentItem(position) //设置当前选择的条目
        .setShowDeleteButton(true) //是否显示删除按钮
        .start(this);

2. 发布朋友圈页面

代码比较简单直接上

package com.zlc.friendcirclephoto.ui;
import android.Manifest;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.InputFilter;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.mylhyl.acp.Acp;
import com.mylhyl.acp.AcpListener;
import com.mylhyl.acp.AcpOptions;
import com.zlc.friendcirclephoto.adapter.MyItemTouchHelperCallback;
import com.zlc.friendcirclephoto.adapter.SendImageAdapter;
import com.zlc.friendcirclephoto.view.CommonEditText;
import com.zlc.friendcirclephoto.R;
import com.zlc.friendcirclephoto.utils.LogUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.iwf.photopicker.PhotoPicker;
import me.iwf.photopicker.PhotoPreview;
/**
 * Created by zlc
 * 发布朋友圈
 */
public class SendDynamicActivity extends BaseActivity implements View.OnClickListener,SendImageAdapter.OnClickListener{
  private ImageView im_fanhui;
  private TextView tv_title;
  private CommonEditText id_et_content;
  private TextView id_tv_num;
  private TextView id_tv_max_num;
  private SendImageAdapter mPhotoAdapter;
  public static final int maxPhoto = 9; //最大选择几张照片
  private List<Object> images = new ArrayList<>();
  private ArrayList<String> photos = new ArrayList<>();
  private RecyclerView mRecycleView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_send_note);
    initView();
    initData();
    initListener();
  }
  private void initView() {
    im_fanhui = findView(R.id.id_iv_back);
    tv_title = findView(R.id.id_tv_title);
    tv_title.setText("发布");
    id_et_content = findView(R.id.id_common_et);
    mRecycleView = findView(R.id.id_recycleview);
    id_tv_num = findView(R.id.tv_num);
    id_tv_max_num = findView(R.id.id_tv_max_num);
    id_et_content.setHint("这一刻的想法......");
    id_tv_num.setText("0");
    id_tv_max_num.setText("/188");
    id_et_content.setFilters(new InputFilter[]{new InputFilter.LengthFilter(188)});
  }
  private void initData() {
    images.add(1);
    mRecycleView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
    mPhotoAdapter = new SendImageAdapter(SendDynamicActivity.this, images);
    mRecycleView.setAdapter(mPhotoAdapter);
    mPhotoAdapter.setOnClickListener(this);
    MyItemTouchHelperCallback callBack = new MyItemTouchHelperCallback(mPhotoAdapter);
    //实现拖拽排序
    final ItemTouchHelper touchHelper = new ItemTouchHelper(callBack);
    //调用ItemTouchHelper的attachToRecyclerView方法建立联系
    touchHelper.attachToRecyclerView(mRecycleView);
  }
  private void initListener() {
    im_fanhui.setOnClickListener(this);
    id_et_content.setOnTextChaged(new CommonEditText.OnTextChaged() {
      @Override
      public void setText(String s) {
        id_tv_num.setText(s.length()+"");
      }
    });
  }
  @Override
  public void onClick(View v) {
    switch (v.getId()){
      case R.id.id_iv_back:
        finish();
        break;
    }
  }
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK && (requestCode == PhotoPicker.REQUEST_CODE || requestCode == PhotoPreview.REQUEST_CODE)) {
      List<String> photos = null;
      if (data != null) {
        photos = data.getStringArrayListExtra(PhotoPicker.KEY_SELECTED_PHOTOS);
      }
      if (photos != null) {
        clearPhotoS(photos.size());
        images.addAll(images.size()-1,photos);
        mPhotoAdapter.notifyDataSetChanged();
      }
    }
  }
  @Override
  public void onClick(View v, int position) {
    switch (v.getId()){
      case R.id.iv_add:
        selectPhoto();
        break;
      case R.id.im_delete:
        delImages(position);
        break;
      case R.id.iv_img:
        lookPhoto(position);
        break;
    }
  }
  public void delImages(int position){
    images.remove(position);
    if(mPhotoAdapter!=null)
      mPhotoAdapter.notifyItemRemoved(position);
  }
  public void clearPhotoS(int size){
    LogUtil.e("返回有几张照片",size+"");
    images.clear();
    images.add(1);
  }
  //选择图片
  private void selectPhoto() {
    List<Object> images = mPhotoAdapter.getDatas();
    photos.clear();
    for (int i = 0;i< images.size()-1;i++ ){
      photos.add(images.get(i).toString());
    }
    //权限
    Acp.getInstance(this).request(new AcpOptions.Builder()
            .setPermissions(
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA,
                Manifest.permission.READ_EXTERNAL_STORAGE
            )
            .build(),
        new AcpListener() {
          @Override
          public void onGranted() {
            LogUtil.e("msg", "权限外全部通过");
            PhotoPicker.builder()
                .setPhotoCount(maxPhoto)
                .setShowCamera(true)
                .setSelected(photos)
                .start(SendDynamicActivity.this);
          }
          @Override
          public void onDenied(List<String> permissions) {
            LogUtil.e(permissions.toString() ,"权限拒绝");
          }
        });
  }
  //查看图片
  private void lookPhoto(int position){
    photos.clear();
    List<Object> images = mPhotoAdapter.getDatas();
    for (int i = 0;i< images.size()-1;i++ ){
      photos.add(images.get(i).toString());
    }
    PhotoPreview.builder()
        .setPhotos(photos)
        .setCurrentItem(position)
        .setShowDeleteButton(true) //是否显示删除按钮
        .start(this);
  }
}

3. 图片适配器代码

public class SendImageAdapter extends RecyclerView.Adapter<SendImageAdapter.ViewHolder> implements ItemTouchHelperAdapter{
  private Activity mContext;
  private List<Object> mDatas;
  private LayoutInflater mLayoutInflater;
  public SendImageAdapter(Activity context,List<Object> datas){
    this.mContext = context;
    this.mDatas = datas;
    mLayoutInflater = LayoutInflater.from(context);
  }
  @Override
  public SendImageAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = mLayoutInflater.inflate(R.layout.send_grid_item,parent,false);
    return new ViewHolder(view);
  }
  @Override
  public void onBindViewHolder(final SendImageAdapter.ViewHolder viewHolder, final int position) {
    Object image = mDatas.get(position);
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) viewHolder.id_rl_img.getLayoutParams();
    int w = params.width = (int) ((ScreenUtil.getScreenWidth(mContext) - DensityUtil.dp2px(mContext,38)) / 3.0);
    params.height = w;
    params.bottomMargin = DensityUtil.dp2px(mContext,7);
    params.rightMargin = DensityUtil.dp2px(mContext,7);
    viewHolder.id_rl_img.setLayoutParams(params);
    if (image instanceof String) {
      viewHolder.im_delete.setVisibility(View.VISIBLE);
      viewHolder.iv_add.setVisibility(View.GONE);
      viewHolder.im_img.setVisibility(View.VISIBLE);
      //这里最好使用glide Picasso加载本地图片 bitmap容易造成内存溢出
      Bitmap bitmap = BitmapFactory.decodeFile(image.toString());
      viewHolder.im_img.setImageBitmap(bitmap);
      LogUtil.e("手机照片", image.toString());
    } else {
      viewHolder.im_delete.setVisibility(View.INVISIBLE);
      viewHolder.iv_add.setVisibility(View.VISIBLE);
      viewHolder.im_img.setVisibility(View.GONE);
      viewHolder.iv_add.setImageResource(R.drawable.tupiantianjia2x);
      LogUtil.e("添加照片", ""+image);
    }
    viewHolder.iv_add.setOnClickListener(new MyClickListener(viewHolder));
    viewHolder.im_img.setOnClickListener(new MyClickListener(viewHolder));
    viewHolder.im_delete.setOnClickListener(new MyClickListener(viewHolder));
  }
  @Override
  public int getItemCount() {
    if(mDatas == null){
      return 0;
    }
    return mDatas.size() >= 9 ? 9 : mDatas.size();
  }
  public List<Object> getDatas() {
    return mDatas;
  }
  public static class ViewHolder extends RecyclerView.ViewHolder{
    private final ImageView im_img;
    private final ImageView iv_add;
    private final ImageView im_delete;
    private final FrameLayout id_rl_img;
    public ViewHolder(View itemView) {
      super(itemView);
      im_img = (ImageView) itemView.findViewById(R.id.iv_img);
      iv_add = (ImageView) itemView.findViewById(R.id.iv_add);
      im_delete = (ImageView) itemView.findViewById(R.id.im_delete);
      id_rl_img = (FrameLayout) itemView.findViewById(R.id.id_rl_img);
    }
  }
  //拖拽排序相关
  @Override
  public void onItemMove(int fromPos, int toPos) {
    if(fromPos == mDatas.size()-1 || toPos == mDatas.size()-1 )
      return;
    Collections.swap(mDatas,fromPos,toPos);
    notifyItemMoved(fromPos,toPos);
  }
  //滑动删除相关
  @Override
  public void onItemDel(int pos) {
    if(pos == mDatas.size() - 1)
      return;
    mDatas.remove(pos);
    notifyItemRemoved(pos);
  }
  public interface OnClickListener{
    void onClick(View v, int position);
  }
  private static OnClickListener onClickListener;
  public void setOnClickListener(OnClickListener onClickListener) {
    this.onClickListener = onClickListener;
  }
  public static class MyClickListener implements View.OnClickListener{
    private ViewHolder mHolder;
    public MyClickListener(ViewHolder holder ){
      this.mHolder = holder;
    }
    @Override
    public void onClick(View view) {
      switch (view.getId()){
        case R.id.iv_add:
        case R.id.im_delete:
        case R.id.iv_img:
          if(onClickListener!=null) {
            int pos = mHolder.getAdapterPosition();
            onClickListener.onClick(view, pos);
          }
          break;
      }
    }
  }
}

4. 拖拽排序

(1) RecycleView通过ItemTouchHelper 实现

 MyItemTouchHelperCallback callBack = new  MyItemTouchHelperCallback(mPhotoAdapter);
  //实现拖拽排序
  final ItemTouchHelper touchHelper = new ItemTouchHelper(callBack);
  //调用ItemTouchHelper的attachToRecyclerView方法建立联系
  touchHelper.attachToRecyclerView(mRecycleView);

(2) MyItemTouchHelperCallback的自定义

package com.zlc.friendcirclephoto.adapter;
import android.graphics.Canvas;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.helper.ItemTouchHelper;
public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {
  private SendImageAdapter mAdapter; //适配器传过来
  private boolean isLongDrag = true;
  private boolean isMoveSwipe = true;
  public MyItemTouchHelperCallback(SendImageAdapter adapter){
    this.mAdapter = adapter;
  }
  @Override
  public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    int dragFlags = 0; //拖拽的标志
    int swipeFlags = 0; //删除的标志
    int position = viewHolder.getAdapterPosition();
    if(position == mAdapter.getDatas().size() - 1){ // 如果是最后一个条目 则既不能拖拽也不能删除
      dragFlags = 0;
      swipeFlags = 0;
    } else if(layoutManager instanceof GridLayoutManager || layoutManager instanceof StaggeredGridLayoutManager){//网格布局 则支持上下左右拖拽 不支持删除
      dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允许上下左右的拖动
      swipeFlags = 0; //不能删除
    }else if(layoutManager instanceof LinearLayoutManager){ //线性布局分为垂直和水平
      LinearLayoutManager manager = (LinearLayoutManager) layoutManager;
      int orientation = manager.getOrientation();
      if(orientation == LinearLayoutManager.HORIZONTAL){ //横向listview列表
        dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允许左右的拖动
        swipeFlags = ItemTouchHelper.DOWN; //只允许从上向下侧滑
      }else if(orientation == LinearLayoutManager.VERTICAL){ //竖向listview列表
        dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下的拖动
        swipeFlags = ItemTouchHelper.LEFT; //只允许从右向左侧滑删除
      }
    }else{  //最后一个条目既不能拖拽也不能删除 相当于更多
      dragFlags = 0;
      swipeFlags = 0;
    }
    return makeMovementFlags(dragFlags,swipeFlags);
  }
  @Override
  public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    mAdapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
    return true;
  }
  @Override
  public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    mAdapter.onItemDel(viewHolder.getAdapterPosition());
  }
  // 该方法返回true时,表示支持长按拖动
  @Override
  public boolean isLongPressDragEnabled() {
    return isLongDrag;
  }
  //该方法返回true时,表示支持滑动删除
  @Override
  public boolean isItemViewSwipeEnabled() {
    return isMoveSwipe;
  }
  //从静止状态变为拖拽或者滑动的时候会回调该方法,参数actionState表示当前的状态。 开始拖拽的时候给item添加一个背景色,然后在拖拽完成的时候还原
  @Override
  public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    //拖拽的时候才设置背景颜色
//    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE && actionState != ItemTouchHelper.ACTION_STATE_SWIPE) {
//      viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
//    }
    super.onSelectedChanged(viewHolder, actionState);
  }
  //当用户操作完毕某个item并且其动画也结束后会调用该方法
  @Override
  public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    //重置改变,防止由于复用而导致的显示问题
    super.clearView(recyclerView, viewHolder);
    viewHolder.itemView.setBackgroundColor(0);
  }
  //我们可以在这个方法内实现我们自定义的交互规则或者自定义的动画效果
  @Override
  public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
  }
  public void setLongDrag(boolean longDrag) {
    isLongDrag = longDrag;
  }
  public void setMoveSwipe(boolean moveSwipe) {
    isMoveSwipe = moveSwipe;
  }
}

(3) 具体实现方法

 //拖拽排序相关
  @Override
  public void onItemMove(int fromPos, int toPos) {
    if(fromPos == mDatas.size()-1 || toPos == mDatas.size()-1 )
      return;
    Collections.swap(mDatas,fromPos,toPos);
    notifyItemMoved(fromPos,toPos);
  }
  //滑动删除相关
  @Override
  public void onItemDel(int pos) {
    if(pos == mDatas.size() - 1)
      return;
    mDatas.remove(pos);
    notifyItemRemoved(pos);
}

5. 联系方式

qq:1509815887@qq.com
email : zlc921022@163.com
phone : 18684732678

总结

以上所述是小编给大家介绍的Android 高仿微信朋友圈拍照上传功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android NoSuchFieldError解决办法

    Android NoSuchFieldError解决办法 前几天在开发的时候,把一个library搬到了一个新的工程中,然后在主应用模块中调用library的Activity,发现出现了NoSuchFieldError: 然而,查看代码明明是没有问题的,layout文件存在且id正确,R文件也正常.后来在StackOverFlow上找到了答案,原因是主应用模块和library里面的layout文件重名了,把其中一个名字改了就正常运行.后来写了个小demo重现了错误并分析了一下打包的apk: 主模

  • 详解Android中获取软键盘状态和软键盘高度

    详解Android中获取软键盘状态和软键盘高度 应用场景 在Android应用中有时会需要获取软键盘的状态(即软键盘是显示还是隐藏)和软键盘的高度.这里列举了一些可能的应用场景. 场景一 当软键盘显示时,按下返回键应当是收起软键盘,而不是回退到上一个界面,但部分机型在返回键处理上有bug,按下返回键后,虽然软键盘会自动收起,但不会消费返回事件,导致Activity还会收到这次返回事件,执行回退操作,这时就需要判断,如果软键盘刚刚由显示变为隐藏状态,就不执行回退操作. 场景二 当软键盘弹出后,会将

  • Android使用URL读取网络资源的方法

    URL(Uniform Resource Locator)是统一资源定位器,它是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.就通常情况而言,URL可以由协议名.主机.端口和资源组成. URL类提供了多个构造器用于创建URL对象,一旦获得了URL对象之后,就可以调用如下常用方法来访问该URL对应的资源了. ->String getFile():获取此URL的资源名:

  • Android触屏事件和MotionEvent详解

    Android屏幕操作 屏幕是用户和Android设备交互的主要媒介,屏幕分为触屏和非触屏.Android设备目前有四种类型:Android Phone,Android Tablet,Android Wear和Android TV.Android TV大都使用非触屏,其他三类设备则大都使用触屏.对非触屏设备,用户可以通过键盘鼠标或遥控器在屏幕上操作.对触屏设备,用户主要通过手指或触控笔等工具在屏幕上操作,当然也可以通过外接的键盘,鼠标和轨迹球等工具来操作. Android屏幕交互事件 用户在设备

  • Android 自定义标题栏的实例详解

     Android 自定义标题栏的实例详解 开发 Android APP 经常会用到自定义标题栏,而有多级页面的情况下还需要给自定义标题栏传递数据. 本文要点: 自定义标题填充不完整 自定义标题栏返回按钮的点击事件 一.代码 这里先介绍一下流程: 1. 创建一个标题栏布局文件 mytitlebar.xml 2. 在style.xml中创建 mytitlestyle 主题 3. 创建类 CustomTitleBar 4. 在需要自定义标题栏的Activity的OnCreate方法中实例化 Custo

  • Android 中RecyclerView顶部刷新实现详解

    Android 中RecyclerView顶部刷新实现详解 1. RecyclerView顶部刷新的原理 RecyclerView顶部刷新的实现通常都是在RecyclerView外部再包裹一层布局.在这个外层布局中,还包含一个自定义的View,作为顶部刷新时的指示View.也就是说,外层布局中包含两个child,一个顶部刷新View,一个RecyclerView,顶部刷新View默认是隐藏不可见的.在外层布局中对滑动事件进行处理,当RecyclerView滑动到顶部并继续下滑的时候,根据滑动的距

  • Android使用RSA加密和解密的示例代码

    一.公钥加密和私钥解密 /**RSA算法*/ public static final String RSA = "RSA"; /**加密方式,android的*/ // public static final String TRANSFORMATION = "RSA/None/NoPadding"; /**加密方式,标准jdk的*/ public static final String TRANSFORMATION = "RSA/None/PKCS1Pad

  • Android:Field can be converted to a local varible.的解决办法

    Android:Field can be converted to a local varible.的解决办法 前言: 使用 Android Studio 开发 Android 有一段时间了,偶尔会碰到 AS 在一些私有变量上有黄色高亮提示Field can be converted to a local varible,有些强迫症的我还是不希望看到这个黄色的高亮.百度没查到什么有用的信息,还是用谷歌搜到了一些解答. 解析 Field can be converted to a local va

  • Android 高仿微信朋友圈拍照上传功能

    模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy! 1. PhotoPicker的使用 这是一个支持选择多张图片,点击图片放大,图片之间左右滑动互相切换的库,同时支持图片删除的库,效果类似微信. (1) 添加PhotoPicker的架包 (2) 使用 选择图片:安卓6.0以后需要在代码中添加读写sd卡和相机的权限 当然清单文件中也需要添加的 PhotoPicker.builder() .setPhotoCount(maxPhoto)

  • Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

    最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack + opnefile实现,也可以用mina开源+XMMP,至于怎么搭建和实现,估计目前github上一搜一大把,至于即时通讯怕误人子弟,暂且不做介绍,现就把实现的一个微信朋友圈的小功能介绍一下. 先上效果图: 一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而grid

  • Android仿微信朋友圈全文、收起功能的实例代码

    前言 一般在社交APP中都有类似朋友圈的功能,其中发表的动态内容很长的时候不可能让它全部显示.这里就需要做一个仿微信朋友圈全文.收起功能来解决该问题.在网上看到一个例子-->http://www.jb51.net/article/105251.htm,写的很不错,但是有个bug,他这个Demo只有在条目固定的时候才正常,当增加.删除条目的时候会出现全文.收起显示混乱的问题.原因是他使用了固定的position作为key来保存当前显示的状态.这篇文章在他的基础上进行优化. 效果图 具体代码 (详细

  • Android自定义TextView仿微信朋友圈文字展开全文功能

    Android自定义TextView仿微信朋友圈文字信息,展开全文功能 代码及注释如下: 首先写一个xml文件 showmore.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical

  • Android自定义SwipeRefreshLayout高仿微信朋友圈下拉刷新

    上一篇文章里把SwipeRefreshLayout的原理简单过了一下,大致了解了其工作原理,不熟悉的可以去看一下:http://www.jb51.net/article/89310.htm 上一篇里最后提到,SwipeRefreshLayout的可定制性是比较差的,看源码会发现跟样式相关的几个类都是private的而且方法是写死的,只暴露出了几个颜色设置的方法.这样使得SwipeRefreshLayout的使用比较简单,主要就是设置一个监听器在onRefresh方法里完成刷新逻辑.讲道理Swip

  • Android GridView仿微信朋友圈显示图片

    最近项目要求上传多图并且多图显示,而且要规则的显示,就像微信朋友圈的图片显示一样. 利用GridView再适合不过了,GridView可以动态加载图片的数量,而且还比较规律,下面说一下自己的思路: 1.获取网络图片 2.初始化gridview,自定义适配器 3.根据图片数量设置gridview的列数 4.更新适配器 下面贴上部分源码并给大家解析一下 一.首先是GridView的item <com.view.SquareLayout xmlns:android="http://schemas

  • Android仿微信朋友圈点赞和评论功能

    最近在做朋友圈的项目,所以写一个Android仿朋友圈点赞和评论功能Demo,代码就是简单实现了一下功能,没有做优化,凑合看 图文排列是用的RecyclerView实现的,弹窗效果是用的自定义的PopupWindow,点赞应该是在本地请求数据库,设置一个flag,获取当前用户的id后,带着id向服务器post一个flag,评论就比较简单了,也是获取当前朋友id(或者昵称),带着内容,向服务器post 贴代码: package com.example.lenovo.dianzandemo; imp

  • Android使用Retrofit仿微信多张图片拍照上传

    Android 仿照微信发说说,既能实现拍照,选图库,多图案上传,使用Retrofit技术. 使用方法:详见http://www.jb51.net/article/103009.htm 项目的运行效果: 服务器端接收文件的action UploadFile.java @Controller public class UploadFile extends ActionSupport { /** * */ private static final long serialVersionUID = 1L

  • Android 仿微信朋友圈点赞和评论弹出框功能

    贡献/下载源码:https://github.com/mmlovesyy/PopupWindowDemo 本文简单模仿微信朋友圈的点赞和评论弹出框,布局等细节请忽略,着重实现弹出框.发评论,及弹出位置的控制. 1. 微信弹出框 微信朋友圈的点赞和评论功能,有2个组成部分: 点击左下角的"更多"按钮,弹出对话框: 点击评论,弹出输入框,添加评论并在页面中实时显示: 微信朋友圈点赞和评论功能 2. 实际效果 本文将建一个 ListView,在其 Item 中简单模仿微信的布局,然后着重实现

  • Android高仿微信表情输入与键盘输入详解

    最近公司在项目上要使用到表情与键盘的切换输入,自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个相当困扰我,不过所幸在Github(其中一个不错的开源项目,其代码整体结构很不错)并且在论坛上找些解决方案,再加上我也是研究了好多个开源项目的代码,最后才苦逼地整合出比较不错的实现效果,可以说跟微信基本一样(嘿嘿,只能说目前还没发现大Bug,若发现大家一起日后慢慢完善,这里我也只是给出了实现方案,拓展其他表情我并没有实现哈,不过代码中我实现了一个可拓展的fragment模板以便大

随机推荐