Android 高仿微信朋友圈拍照上傳功能
模仿微信朋友圈發(fā)布動態(tài),輸入文字支持文字多少高度自增,有一個最小輸入框高度,輸入文字有限制,不過這些都很easy!
1. PhotoPicker的使用
這是一個支持選擇多張圖片,點擊圖片放大,圖片之間左右滑動互相切換的庫,同時支持圖片刪除的庫,效果類似微信。
(1) 添加PhotoPicker的架包
(2) 使用
選擇圖片:安卓6.0以后需要在代碼中添加讀寫sd卡和相機的權(quán)限 當(dāng)然清單文件中也需要添加的
PhotoPicker.builder()
.setPhotoCount(maxPhoto) //設(shè)置最多選擇的圖片數(shù)量
.setShowCamera(true) //是否顯示相機按鈕
.setSelected(photos) //設(shè)置已經(jīng)選好的圖片
.start(SendDynamicActivity.this); //上下文參數(shù) 需要傳activity
查看圖片:
PhotoPreview.builder()
.setPhotos(photos) //設(shè)置選擇好的圖片
.setCurrentItem(position) //設(shè)置當(dāng)前選擇的條目
.setShowDeleteButton(true) //是否顯示刪除按鈕
.start(this);
2. 發(fā)布朋友圈頁面
代碼比較簡單直接上
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
* 發(fā)布朋友圈
*/
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("發(fā)布");
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);
//實現(xiàn)拖拽排序
final ItemTouchHelper touchHelper = new ItemTouchHelper(callBack);
//調(diào)用ItemTouchHelper的attachToRecyclerView方法建立聯(lián)系
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());
}
//權(quán)限
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", "權(quán)限外全部通過");
PhotoPicker.builder()
.setPhotoCount(maxPhoto)
.setShowCamera(true)
.setSelected(photos)
.start(SendDynamicActivity.this);
}
@Override
public void onDenied(List<String> permissions) {
LogUtil.e(permissions.toString() ,"權(quán)限拒絕");
}
});
}
//查看圖片
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容易造成內(nèi)存溢出
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);
}
}
//拖拽排序相關(guān)
@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);
}
//滑動刪除相關(guān)
@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 實現(xiàn)
MyItemTouchHelperCallback callBack = new MyItemTouchHelperCallback(mPhotoAdapter); //實現(xiàn)拖拽排序 final ItemTouchHelper touchHelper = new ItemTouchHelper(callBack); //調(diào)用ItemTouchHelper的attachToRecyclerView方法建立聯(lián)系 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; //拖拽的標(biāo)志
int swipeFlags = 0; //刪除的標(biāo)志
int position = viewHolder.getAdapterPosition();
if(position == mAdapter.getDatas().size() - 1){ // 如果是最后一個條目 則既不能拖拽也不能刪除
dragFlags = 0;
swipeFlags = 0;
} else if(layoutManager instanceof GridLayoutManager || layoutManager instanceof StaggeredGridLayoutManager){//網(wǎng)格布局 則支持上下左右拖拽 不支持刪除
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; //只允許從上向下側(cè)滑
}else if(orientation == LinearLayoutManager.VERTICAL){ //豎向listview列表
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允許上下的拖動
swipeFlags = ItemTouchHelper.LEFT; //只允許從右向左側(cè)滑刪除
}
}else{ //最后一個條目既不能拖拽也不能刪除 相當(dāng)于更多
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;
}
//從靜止?fàn)顟B(tài)變?yōu)橥献Щ蛘呋瑒拥臅r候會回調(diào)該方法,參數(shù)actionState表示當(dāng)前的狀態(tài)。 開始拖拽的時候給item添加一個背景色,然后在拖拽完成的時候還原
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
//拖拽的時候才設(shè)置背景顏色
// if (actionState != ItemTouchHelper.ACTION_STATE_IDLE && actionState != ItemTouchHelper.ACTION_STATE_SWIPE) {
// viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
// }
super.onSelectedChanged(viewHolder, actionState);
}
//當(dāng)用戶操作完畢某個item并且其動畫也結(jié)束后會調(diào)用該方法
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//重置改變,防止由于復(fù)用而導(dǎo)致的顯示問題
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setBackgroundColor(0);
}
//我們可以在這個方法內(nèi)實現(xiàn)我們自定義的交互規(guī)則或者自定義的動畫效果
@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) 具體實現(xiàn)方法
//拖拽排序相關(guān)
@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);
}
//滑動刪除相關(guān)
@Override
public void onItemDel(int pos) {
if(pos == mDatas.size() - 1)
return;
mDatas.remove(pos);
notifyItemRemoved(pos);
}
5. 聯(lián)系方式
qq:1509815887@qq.com
email : zlc921022@163.com
phone : 18684732678
總結(jié)
以上所述是小編給大家介紹的Android 高仿微信朋友圈拍照上傳功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Android Studio報:“Attribute application@theme or @ icon ”問題的解
這篇文章主要給大家介紹了關(guān)于Android Studio報:“Attribute application@theme or @ icon ”問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
Android開發(fā)中給EditText控件添加TextWatcher監(jiān)聽實現(xiàn)對輸入字?jǐn)?shù)的限制(推薦)
這篇文章主要介紹了Android開發(fā)中給EditText控件添加TextWatcher監(jiān)聽實現(xiàn)對輸入字?jǐn)?shù)的限制(推薦)的相關(guān)資料,需要的朋友可以參考下2016-11-11
關(guān)于OkHttp中response.body().string()的用法解析
這篇文章主要介紹了關(guān)于OkHttp中response.body().string()的用法解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
Android中通過訪問本地相冊或者相機設(shè)置用戶頭像實例
本篇文章主要介紹了Android中通過訪問本地相冊或者相機設(shè)置用戶頭像,具有一定的參考價值,有興趣的可以了解一下。2017-01-01

