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

时间: 2017-10-11

Android 中RecyclerView顶部刷新实现详解

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

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

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

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中获取软键盘状态和软键盘高度

详解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使用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 NoSuchFieldError解决办法

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

Android添加ButterKnife时报错Error:(2, 0) Cannot add extension with name 'android'的解决办法

在添加ButterKnife的时候,根据它的Readme配置以后报错: Error:(2, 0) Cannot add extension with name 'android', as there is an extension already registered with that name. 解决方法如下: 默认我们在自己的module下添加后是这样的: apply plugin: 'com.android.application' apply plugin: 'com.android.

Android webview 遇到android.os.FileUriExposedException错误解决办法

Android webview 遇到android.os.FileUriExposedException错误解决办法 1. 在 Manifest 文件中添加: <manifest ...> <application ...> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider&

Android webveiw 出现栈错误解决办法

Android webveiw 出现栈错误解决办法 前言: 最近做一个项目,项目调试基础库的一个调试工具展示设备信息页面使用WebView.有一个应用集成调试基础库展示内容时出现 java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in privileged processes 因为应用是系统级别的,在AndroidManifest.xml中添加了android:sharedU

Caused by: android.os.NetworkOnMainThreadException错误解决办法

好久不写Android代码手都生了,找出自己之前写的程序发现跑不了了,也没啥特别的错误提示,就看到一句有用的错误Caused by: android.os.NetworkOnMainThreadException,查了下原因上在4.0之后在主线程里面执行Http请求都会报这个错,大概是怕Http请求时间太长造成程序假死的情况吧. 解决办法有两个思路,分别是: 第一种方法:直接忽视,强制使用(强烈不推荐,但是修改简单) 在MainActivity文件的setContentView(R.layout

使用Android studio创建的AIDL编译时找不到自定义类的解决办法

使用AS创建ADIL文件时AS会在main文件夹下给我们生成一个aidl文件夹和一个相同包名的包,通常我们会把所有和ADIL相关的类或文件放在这个包下,但是如果存在自定义的类时,程序编译时无法通过,提示找不到自定义的包.解决办法如下,在启动Module的build.gradle中加入如下代码: sourceSets { main { manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java', '

Android在view.requestFocus(0)返回false的解决办法

我们有时候想让listview的第一行自动获取到焦点,我们就会使用view.requestFocus(0)来操作,而有时候并不生效,debug后显示rerurn为false. 这是因为我们获取焦点太早,listview控件还为加载完毕.可以尝试一下方法解决: listview.post(new Runnable(){ @Override public void run(){ view.requestFocus(0); } }); 以上所述是小编给大家介绍的Android在view.request

Android DaggerActivityComponent错误解决办法详解

Android DaggerActivityComponent错误解决办法详解 在使用dagger2的过程中,如果修改了某个类的内容,第一次编译运行时总会报错:错误: 找不到符号 符号: 类 DaggerActivityComponent 位置: 程序包 com--的错误,然后再重新编译一次,才会正常运行,经过仔细的检查终于找到问题的根源: 错误的原因是build.gradle(Module:app)引入'com.google.dagger:dagger-compiler:2.0.2'使用的是c

Android PopupWindow被输入法弹上去之后无法恢复原位的解决办法

问题描述: 我的PopupWindow位于屏幕底部,它上面有一个EditText输入框,而当我点击这个EditText的时候,随着输入法的弹出,我的PopupWindow也会随着上升,但是当我结束输入,关闭输入法的时候,PopupWindow却没有随着输入法一下下滑,而是停在屏幕中间,下面显示的是Activity的背景色.(小米手机上出现,三星note上没有出现) 解决办法: 给PopupWindow增加一个属性:popWindow.setSoftInputMode(WindowManager.

Android ListView 和ScroolView 出现onmeasure空指针的解决办法

ListView 和ScroolView同时使用计算高度时onmeasure报空指针的解决办法 前言: 虽然Android 的设计者始终认为ListView.GridView+ScroolView组合使用并不是一种比较好的实现方法.但是在我们开发过程中又会经常使用到这样的需求,特别是在适配小屏幕手机的时候又必须要用这种让人不接受的设计,下面就来说一下在计算ListView或者GridView的过程中会出现onmeasure空指针的问题. 解决办法 当我发现listItem.measure(0,0