Android QQ 공간 동적 인터페이스 공유 기능 모방

먼저 효과 보기:


아주 적은 코드 로 동적 상세 정보 와 2 급 댓 글 의 데이터 획득 과 처리,UI 디 스 플레이 와 상호작용 을 실현 하고 높 은 디 스 플레이,높 은 재 활용,높 은 유연성 을 실현 합 니 다.
동적 목록 인터페이스 Moment ListFragment 는 드 롭 다운 리 셋 과 업 로드,퍼 지 검색 을 지원 하 며 빠 른 미끄럼 을 반복 하 는 것 이 유창 합 니 다.
캐 시 메커니즘 은 데 이 터 를 시작 인터페이스 후 순식간에 불 러 올 수 있 도록 합 니 다.

동적 상세 인터페이스 Moment Activity 지원(취소)좋아요 누 르 기,댓 글 삭제,이름 누 르 고 개인 정보 로 건 너 뛰 기 등.
한 장의 그림 만 있 을 때 그림 이 확대 되 어 표시 되 고 한 장 이 넘 으 면 구 궁 격 으로 표시 된다.

사용 하 는 Comment Container View 와 Moment View 는 모두 독립 된 구성 요소 로 단독으로 사용 할 수도 있 고 ListView 나 다른 View Group 에 추가 할 수도 있 습 니 다.
댓 글 ContainerView 재 활용

CommentContainerView.java

setOnCommentClickListener    :         
createView           :   View
bindView            :        View
setMaxShowCount         :         ,     
setComment           :     
addCommentView         :     View
 package apijson.demo.client.view;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import apijson.demo.client.R;
import apijson.demo.client.model.CommentItem;
import apijson.demo.client.view.CommentView.OnCommentClickListener;
import zuo.biao.library.base.BaseView;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.StringUtil;
/**    
 * @author Lemon
 * @use
CommentContainerView commentContainerView = new CommentContainerView(context, inflater);
adapter   convertView = commentContainerView.getView();//[   .DemoAdapter]         
containerView.addView(commentContainerView.getConvertView());
commentContainerView.bindView(data);
commentContainerView.setOnClickPictureListener(onClickPictureListener);//   
commentContainerView.setOnDataChangedListener(onDataChangedListener);data = commentContainerView.getData();//   
commentContainerView.setOnClickListener(onClickListener);//   
...
 */
public class CommentContainerView extends BaseView<List<CommentItem>> {
  private static final String TAG = "CommentContainerView";
  private OnCommentClickListener onCommentClickListener;
  /**        
   * @param onCommentClickListener
   */
  public void setOnCommentClickListener(OnCommentClickListener onCommentClickListener) {
    this.onCommentClickListener = onCommentClickListener;
  }
  public CommentContainerView(Activity context, Resources resources) {
    super(context, resources);
  }
  private LayoutInflater inflater;
  public ViewGroup llCommentContainerViewContainer;
  public View tvCommentContainerViewMore;
  @SuppressLint("InflateParams")
  @Override
  public View createView(LayoutInflater inflater) {
    this.inflater = inflater;
    convertView = inflater.inflate(R.layout.comment_container_view, null);
    llCommentContainerViewContainer = findViewById(R.id.llCommentContainerViewContainer);
    tvCommentContainerViewMore = findViewById(R.id.tvCommentContainerViewMore);
    return convertView;
  }
  @Override
  public void bindView(List<CommentItem> list){
    llCommentContainerViewContainer.setVisibility(list == null || list.isEmpty() ? View.GONE : View.VISIBLE);
    if (list == null) {
      Log.w(TAG, "bindView data_ == null >> data_ = new List<CommentItem>();");
      list = new ArrayList<CommentItem>();
    }
    this.data = list;
    //   
    setComment(list);
  }
  private int maxShowCount = 3;
  /**        ,     
   * @param maxShowCount <= 0 ?      :      
   */
  public void setMaxShowCount(int maxShowCount) {
    this.maxShowCount = maxShowCount;
  }
  /**    
   * @param list
   */
  public void setComment(List<CommentItem> list) {
    int count = list == null ? 0 : list.size();
    boolean showMore = maxShowCount > 0 && count > maxShowCount;
    tvCommentContainerViewMore.setVisibility(showMore ? View.VISIBLE : View.GONE);
    llCommentContainerViewContainer.removeAllViews();
    llCommentContainerViewContainer.setVisibility(count <= 0 ? View.GONE : View.VISIBLE);
    if (count > 0) {
      if (showMore) {
        list = list.subList(0, maxShowCount);
      }
      for (int i = 0; i < list.size(); i++) {
        addCommentView(i, list.get(i));
      }
    }
  }
  /**    
   * @param index
   * @param comment
   */
  @SuppressLint("InflateParams")
  private void addCommentView(final int index, final CommentItem comment) {
    if (comment == null) {
      Log.e(TAG, "addCommentView comment == null >> return; ");
      return;
    }
    String content = StringUtil.getTrimedString(comment.getComment().getContent());
    if (StringUtil.isNotEmpty(content, true) == false) {
      Log.e(TAG, "addCommentView StringUtil.isNotEmpty(content, true) == false >> return; ");
      return;
    }
    CommentTextView commentView = (CommentTextView) inflater.inflate(R.layout.comment_item, null);
    commentView.setView(comment);
    if (onCommentClickListener != null) {
      commentView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
          onCommentClickListener.onCommentClick(comment, position, index, false);
        }
      });
      commentView.setOnLongClickListener(new OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
          onCommentClickListener.onCommentClick(comment, position, index, true);
          return true;
        }
      });
    }
    llCommentContainerViewContainer.addView(commentView);
  }
}
comment_container_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  style="@style/ll_vertical_match_wrap" >
  <LinearLayout
    android:id="@+id/llCommentContainerViewContainer"
    style="@style/ll_vertical_match_wrap" >
  </LinearLayout>
  <TextView
    android:id="@+id/tvCommentContainerViewMore"
    style="@style/text_small_blue"
    android:layout_width="match_parent"
    android:background="@drawable/bg_item_to_alpha"
    android:gravity="left|center_vertical"
    android:paddingBottom="4dp"
    android:paddingTop="4dp"
    android:text="    " />
</LinearLayout>
MomentView 재 활용

MomentView.java

setOnPictureClickListener    :         
createView           :   View
bindView            :        View
setPraise            :     
setShowComment         :         
getShowComment         :            
setComment           :     
setPicture           :        
toComment            :          
getData             :          
isLoggedIn           :        ,          
praise             : (  )  
onDialogButtonClick       :          ,      
onHttpResponse         :   Http       ,    
onClick             :       ,              
onItemClick           :          ,       , setOnPictureClickListener    
package apijson.demo.client.view;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import apijson.demo.client.R;
import apijson.demo.client.activity_fragment.LoginActivity;
import apijson.demo.client.activity_fragment.MomentActivity;
import apijson.demo.client.activity_fragment.UserActivity;
import apijson.demo.client.activity_fragment.UserListActivity;
import apijson.demo.client.application.APIJSONApplication;
import apijson.demo.client.model.CommentItem;
import apijson.demo.client.model.Moment;
import apijson.demo.client.model.MomentItem;
import apijson.demo.client.model.User;
import apijson.demo.client.util.HttpRequest;
import apijson.demo.client.view.CommentView.OnCommentClickListener;
import zuo.biao.apijson.JSONResponse;
import zuo.biao.library.base.BaseView;
import zuo.biao.library.manager.CacheManager;
import zuo.biao.library.manager.HttpManager.OnHttpResponseListener;
import zuo.biao.library.model.Entry;
import zuo.biao.library.ui.AlertDialog;
import zuo.biao.library.ui.AlertDialog.OnDialogButtonClickListener;
import zuo.biao.library.ui.GridAdapter;
import zuo.biao.library.ui.WebViewActivity;
import zuo.biao.library.util.ImageLoaderUtil;
import zuo.biao.library.util.Log;
import zuo.biao.library.util.ScreenUtil;
import zuo.biao.library.util.StringUtil;
import zuo.biao.library.util.TimeUtil;
/**  
 * @author Lemon
 * @use
MomentView momentView = new MomentView(context, inflater);
adapter   convertView = momentView.getView();//[   .DemoAdapter]         
containerView.addView(momentView.getConvertView());
momentView.bindView(data);
momentView.setOnPictureClickListener(onPictureClickListener);//   
momentView.setOnDataChangedListener(onDataChangedListener);data = momentView.getData();//   
momentView.setOnClickListener(onClickListener);//   
...
 */
public class MomentView extends BaseView<MomentItem> implements OnClickListener
, OnHttpResponseListener, OnDialogButtonClickListener, OnItemClickListener {
  private static final String TAG = "MomentView";
  public interface OnPictureClickListener {
    void onClickPicture(int momentPosition, MomentView momentView, int pictureIndex);
  }
  private OnPictureClickListener onPictureClickListener;
  /**        
   * @param onPictureClickListener
   */
  public void setOnPictureClickListener(OnPictureClickListener onPictureClickListener) {
    this.onPictureClickListener = onPictureClickListener;
  }
  public MomentView(Activity context, Resources resources) {
    super(context, resources);
  }
  //UI   (  UI,             ,          )<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  private LayoutInflater inflater;
  public View llMomentViewContainer;
  public ImageView ivMomentViewHead;
  public TextView tvMomentViewName;
  public TextView tvMomentViewStatus;
  public TextView tvMomentViewContent;
  public GridView gvMomentView;
  public TextView tvMomentViewDate;
  public ImageView ivMomentViewPraise;
  public ImageView ivMomentViewComment;
  public ViewGroup llMomentViewPraise;
  public PraiseTextView tvMomentViewPraise;
  public View vMomentViewDivider;
  public ViewGroup llMomentViewCommentContainer;
  @SuppressLint("InflateParams")
  @Override
  public View createView(LayoutInflater inflater) {
    this.inflater = inflater;
    convertView = inflater.inflate(R.layout.moment_view, null);
    llMomentViewContainer = findViewById(R.id.llMomentViewContainer);
    ivMomentViewHead = findViewById(R.id.ivMomentViewHead, this);
    tvMomentViewName = findViewById(R.id.tvMomentViewName, this);
    tvMomentViewStatus = findViewById(R.id.tvMomentViewStatus, this);
    tvMomentViewContent = findViewById(R.id.tvMomentViewContent, this);
    gvMomentView = findViewById(R.id.gvMomentView);
    tvMomentViewDate = findViewById(R.id.tvMomentViewDate);
    ivMomentViewPraise = findViewById(R.id.ivMomentViewPraise, this);
    ivMomentViewComment = findViewById(R.id.ivMomentViewComment, this);
    llMomentViewPraise = findViewById(R.id.llMomentViewPraise, this);
    tvMomentViewPraise = findViewById(R.id.tvMomentViewPraise, this);
    vMomentViewDivider = findViewById(R.id.vMomentViewDivider);
    llMomentViewCommentContainer = findViewById(R.id.llMomentViewCommentContainer);
    return convertView;
  }
  private User user;
  private Moment moment;
  private long momentId;
  private long userId;
  private boolean isCurrentUser;
  private int status;
  public int getStatus() {
    return status;
  }
  @Override
  public void bindView(MomentItem data_){
    this.data = data_;
    llMomentViewContainer.setVisibility(data == null ? View.GONE : View.VISIBLE);
    if (data == null) {
      Log.w(TAG, "bindView data == null >> return;");
      return;
    }
    this.user = data.getUser();
    this.moment = data.getMoment();
    this.momentId = moment.getId();
    this.userId = moment.getUserId();
    this.isCurrentUser = APIJSONApplication.getInstance().isCurrentUser(moment.getUserId());
    this.status = data.getMyStatus();
    ImageLoaderUtil.loadImage(ivMomentViewHead, user.getHead());
    tvMomentViewName.setText(StringUtil.getTrimedString(user.getName()));
    tvMomentViewStatus.setText(StringUtil.getTrimedString(data.getStatusString()));
    tvMomentViewStatus.setVisibility(isCurrentUser ? View.VISIBLE : View.GONE);
    tvMomentViewContent.setVisibility(StringUtil.isNotEmpty(moment.getContent(), true) ? View.VISIBLE : View.GONE);
    tvMomentViewContent.setText(StringUtil.getTrimedString(moment.getContent()));
    tvMomentViewDate.setText(TimeUtil.getSmartDate(moment.getDate()));
    //   
    setPicture(moment.getPictureList());
    //   
    setPraise(data.getIsPraised(), data.getUserList());
    //   
    setComment(data.getCommentItemList());
    vMomentViewDivider.setVisibility(llMomentViewPraise.getVisibility() == View.VISIBLE
        && llMomentViewCommentContainer.getVisibility() == View.VISIBLE ? View.VISIBLE : View.GONE);
  }
  /**    
   * @param joined
   * @param list
   */
  private void setPraise(boolean joined, List<User> list) {
    ivMomentViewPraise.setImageResource(joined ? R.drawable.praised : R.drawable.praise);
    llMomentViewPraise.setVisibility(list == null || list.isEmpty() ? View.GONE : View.VISIBLE);
    if (llMomentViewPraise.getVisibility() == View.VISIBLE) {
      tvMomentViewPraise.setView(list);
    }
  }
  private boolean showComment = true;
  public void setShowComment(boolean showComment) {
    this.showComment = showComment;
  }
  public boolean getShowComment() {
    return showComment;
  }
  public CommentContainerView commentContainerView;
  /**    
   * @param list
   */
  public void setComment(List<CommentItem> list) {
    llMomentViewCommentContainer.setVisibility(showComment == false || list == null || list.isEmpty()
        ? View.GONE : View.VISIBLE);
    if (llMomentViewCommentContainer.getVisibility() != View.VISIBLE) {
      Log.i(TAG, "setComment llMomentViewCommentContainer.getVisibility() != View.VISIBLE >> return;");
      return;
    }
    if (commentContainerView == null) {
      commentContainerView = new CommentContainerView(context, resources);
      llMomentViewCommentContainer.removeAllViews();
      llMomentViewCommentContainer.addView(commentContainerView.createView(inflater));
      commentContainerView.setOnCommentClickListener(new OnCommentClickListener() {
        @Override
        public void onCommentClick(CommentItem item, int position, int index, boolean isLong) {
          toComment(item, true);
        }
      });
      commentContainerView.tvCommentContainerViewMore.setOnClickListener(this);
      commentContainerView.setMaxShowCount(5);
    }
    commentContainerView.bindView(list);
  }
  private GridAdapter adapter;
  /**    
   * @param pictureList
   */
  private void setPicture(List<String> pictureList) {
    List<Entry<String, String>> keyValueList = new ArrayList<Entry<String, String>>();
    if (pictureList != null) {
      for (String picture : pictureList) {
        keyValueList.add(new Entry<String, String>(picture, null));
      }
    }
    int pictureNum = keyValueList.size();
    gvMomentView.setVisibility(pictureNum <= 0 ? View.GONE : View.VISIBLE);
    if (pictureNum <= 0) {
      Log.i(TAG, "setList pictureNum <= 0 >> lvModel.setAdapter(null); return;");
      adapter = null;
      gvMomentView.setAdapter(null);
      return;
    }
    gvMomentView.setNumColumns(pictureNum <= 1 ? 1 : 3);
    if (adapter == null) {
      adapter = new GridAdapter(context).setHasName(false);
      gvMomentView.setAdapter(adapter);
    }
    adapter.refresh(keyValueList);
    gvMomentView.setOnItemClickListener(this);
    final int gridViewHeight = (int) (ScreenUtil.getScreenSize(context)[0]
        - convertView.getPaddingLeft() - convertView.getPaddingRight()
        - getDimension(R.dimen.moment_view_head_width));
    try {
      if (pictureNum >= 7) {
        gvMomentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, gridViewHeight));
      } else if (pictureNum >= 4) {
        gvMomentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, (gridViewHeight*2)/3));
      } else if (pictureNum >= 2) {
        gvMomentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, gridViewHeight / 3));
      } else {
        gvMomentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
      }
    } catch (Exception e) {
      Log.e(TAG, " setPictureGrid try int gridViewHeight;...>> catch" + e.getMessage());
    }
  }
  /**         
   * @param isToComment
   */
  private void toComment(boolean isToComment) {
    toComment(null, isToComment);
  }
  /**         
   * @param commentItem
   * @param isToComment comment    true
   */
  private void toComment(CommentItem commentItem, boolean isToComment) {
    if (commentItem == null) {
      commentItem = new CommentItem();
    }
    toActivity(MomentActivity.createIntent(context, momentId, isToComment
        , commentItem.getId(), commentItem.getUser().getId(), commentItem.getUser().getName()));
  }
  //UI   (  UI,             ,          )>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  //Data   (           ,          )<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  @Override
  public MomentItem getData() {//bindView(null)   data == null
    return llMomentViewContainer.getVisibility() == View.VISIBLE ? data : null;
  }
  /**       ,            
   * @return
   */
  private boolean isLoggedIn() {
    boolean isLoggedIn = APIJSONApplication.getInstance().isLoggedIn();
    if (isLoggedIn == false) {
      context.startActivity(LoginActivity.createIntent(context));
      context.overridePendingTransition(R.anim.bottom_push_in, R.anim.hold);
    }
    return isLoggedIn;
  }
  /**  
   * @param toPraise
   */
  public void praise(boolean toPraise) {
    if (data == null || toPraise == data.getIsPraised()) {
      Log.e(TAG, "praiseWork toPraise == moment.getIsPraise() >> return;");
      return;
    }
    //    setPraise(toPraise, data.getPraiseCount() + (toPraise ? 1 : -1));
    HttpRequest.praiseMoment(momentId, toPraise, toPraise ? HTTP_PRAISE : HTTP_CANCEL_PRAISE, this);
  }
  //Data   (           ,          )>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  //Event     (            )<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  @Override
  public void onDialogButtonClick(int requestCode, boolean isPositive) {
    if (isPositive && data != null) {
      data.setMyStatus(MomentItem.STATUS_DELETING);
      bindView(data);
      HttpRequest.deleteMoment(moment.getId(), HTTP_DELETE, this);
    }
  }
  public static final int HTTP_PRAISE = 1;
  public static final int HTTP_CANCEL_PRAISE = 2;
  public static final int HTTP_DELETE = 3;
  @Override
  public void onHttpResponse(int requestCode, String result, Exception e) {
    if (data == null) {
      Log.e(TAG, "onHttpResponse data == null >> return;");
      return;
    }
    JSONResponse response = new JSONResponse(result);
    JSONResponse response2 = response.getJSONResponse(Moment.class.getSimpleName());
    boolean isSucceed = JSONResponse.isSucceed(response2);
    switch (requestCode) {
    case HTTP_PRAISE:
    case HTTP_CANCEL_PRAISE:
      if (isSucceed) {
        data.setIsPraised(requestCode == HTTP_PRAISE);
        bindView(data);
      } else {
        showShortToast((requestCode == HTTP_PRAISE ? "  " : "    ") + "  ,        ");
      }
      break;
    case HTTP_DELETE:
      showShortToast(isSucceed ? R.string.delete_succeed : R.string.delete_failed);
      //  adapter.getCount()   。      ,     ,      adapter,             。
      if (isSucceed) {
        bindView(null);
        status = MomentItem.STATUS_DELETED;
        if (onDataChangedListener != null) {
          onDataChangedListener.onDataChanged();
        }
        CacheManager.getInstance().remove(MomentItem.class, "" + momentId);
      } else {
        data.setMyStatus(MomentItem.STATUS_NORMAL);
        bindView(data);
      }
      break;
    }
  }
  @Override
  public void onClick(View v) {
    if (data == null) {
      return;
    }
    if (status == MomentItem.STATUS_PUBLISHING) {
      showShortToast(R.string.publishing);
      return;
    }
    switch (v.getId()) {
    case R.id.ivMomentViewHead:
    case R.id.tvMomentViewName:
      toActivity(UserActivity.createIntent(context, userId));
      break;
    case R.id.tvMomentViewStatus:
      if (status == MomentItem.STATUS_NORMAL) {
        new AlertDialog(context, "", "    ", true, 0, this).show();
      }
      break;
    case R.id.tvMomentViewContent:
    case R.id.tvCommentContainerViewMore:
      toComment(false);
      break;
    case R.id.tvMomentViewPraise:
    case R.id.llMomentViewPraise:
      toActivity(UserListActivity.createIntent(context, data.getPraiseUserIdList())
          .putExtra(UserListActivity.INTENT_TITLE, "    "));
      break;
    default:
      if (isLoggedIn() == false) {
        return;
      }
      switch (v.getId()) {
      case R.id.ivMomentViewPraise:
        praise(! data.getIsPraised());
        break;
      case R.id.ivMomentViewComment:
        toComment(true);
        break;
      default:
        break;
      }
      break;
    }
  }
  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    if (status == MomentItem.STATUS_PUBLISHING) {
      showShortToast(R.string.publishing);
      return;
    }
    if (onPictureClickListener != null) {
      onPictureClickListener.onClickPicture(this.position, this, position);
    } else {
      toActivity(WebViewActivity.createIntent(context, null
          , adapter == null ? null : adapter.getItem(position).getKey()));
    }
  }
  //Event     (            )>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
moment_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  style="@style/match_wrap"
  android:descendantFocusability="blocksDescendants" >
  <LinearLayout
    android:id="@+id/llMomentViewContainer"
    style="@style/ll_horizontal_match_wrap"
    android:background="@color/white"
    android:gravity="top"
    android:padding="10dp" >
    <RelativeLayout
      android:id="@+id/rlMomentViewItemHead"
      android:layout_width="@dimen/moment_view_head_width"
      android:layout_height="@dimen/moment_view_head_height"
      android:paddingRight="@dimen/moment_view_head_padding_right" >
      <ImageView
        android:background="@color/alpha_3"
        android:id="@+id/ivMomentViewHead"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />
    </RelativeLayout>
    <LinearLayout
      style="@style/ll_vertical_match_wrap"
      android:layout_below="@+id/rlMomentViewItemHead"
      android:layout_toRightOf="@+id/rlMomentViewItemHead"
      android:gravity="left" >
      <LinearLayout
        style="@style/ll_horizontal_match_wrap"
        android:layout_height="match_parent" >
        <TextView
          android:id="@+id/tvMomentViewName"
          style="@style/text_small_blue"
          android:layout_width="match_parent"
          android:layout_weight="1"
          android:background="@drawable/bg_item_to_alpha"
          android:gravity="left"
          android:text="Name" />
        <TextView
          android:id="@+id/tvMomentViewStatus"
          style="@style/text_small_blue"
          android:background="@drawable/bg_item_to_alpha"
          android:text="   " />
      </LinearLayout>
      <TextView
        android:id="@+id/tvMomentViewContent"
        style="@style/text_small_black"
        android:layout_width="match_parent"
        android:layout_marginTop="5dp"
        android:background="@drawable/bg_item_to_alpha"
        android:gravity="left|top"
        android:maxLines="8"
        android:paddingBottom="5dp"
        android:text="This is a content..." />
      <apijson.demo.client.view.EmptyEventGridView
        android:id="@+id/gvMomentView"
        style="@style/wrap_wrap"
        android:focusable="false"
        android:horizontalSpacing="4dp"
        android:listSelector="@drawable/bg_item_to_alpha"
        android:numColumns="3"
        android:paddingTop="4dp"
        android:scrollbars="none"
        android:stretchMode="columnWidth"
        android:verticalSpacing="4dp" />
      <LinearLayout
        style="@style/ll_horizontal_match_wrap"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp" >
        <TextView
          android:id="@+id/tvMomentViewDate"
          style="@style/text_small_black"
          android:layout_width="match_parent"
          android:layout_weight="1"
          android:gravity="left"
          android:text="2015 12 " />
        <ImageView
          android:id="@+id/ivMomentViewPraise"
          style="@style/img_btn"
          android:layout_marginRight="18dp"
          android:background="@drawable/bg_item_to_alpha"
          android:src="@drawable/praise" />
        <ImageView
          android:id="@+id/ivMomentViewComment"
          style="@style/img_btn"
          android:background="@drawable/bg_item_to_alpha"
          android:src="@drawable/comment" />
      </LinearLayout>
      <LinearLayout
        style="@style/ll_vertical_match_wrap"
        android:layout_marginTop="5dp"
        android:background="@color/alpha_1"
        android:paddingLeft="8dp"
        android:paddingRight="8dp" >
        <LinearLayout
          android:id="@+id/llMomentViewPraise"
          style="@style/ll_horizontal_match_wrap"
          android:layout_height="wrap_content"
          android:layout_marginBottom="4dp"
          android:layout_marginTop="4dp"
          android:background="@drawable/bg_item_to_alpha"
          android:gravity="top" >
          <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:scaleType="fitXY"
            android:src="@drawable/praise" />
          <apijson.demo.client.view.PraiseTextView
            android:id="@+id/tvMomentViewPraise"
            style="@style/text_small_blue"
            android:background="@drawable/bg_item_to_alpha"
            android:gravity="left|top"
            android:lineSpacingExtra="4dp"
            android:text="     " />
        </LinearLayout>
        <View
          android:id="@+id/vMomentViewDivider"
          style="@style/divider_horizontal_1px" />
        <LinearLayout
          android:id="@+id/llMomentViewCommentContainer"
          style="@style/ll_vertical_match_wrap"
          android:paddingBottom="4dp"
          android:paddingTop="4dp" >
        </LinearLayout>
      </LinearLayout>
    </LinearLayout>
  </LinearLayout>
</RelativeLayout>
이 프로젝트 는 ZBLibrary 의 빠 른 개발 프레임 워 크 를 사 용 했 기 때문에 QQ 공간 과 위 챗 모멘트 를 모방 하 는 복잡 한 인터페이스 는 아주 적은 코드 만 사 용 했 고 높 은 디 결합,높 은 재 활용,높 은 유연성 을 가 집 니 다.
서버 는 APIJSON(Server)프로젝트 로 신속하게 구축 되 었 습 니 다.클 라 이언 트 App 과 서버 는 APIJSON-JSON 전송 구조 프로 토 콜 을 통 해 통신 되 고 매우 편리 하 며 유연 하 며 대량의 인터페이스 와 문 서 를 절약 합 니 다!
올해 RxJava 는 특히 인기 가 많아 서 베 이 징 시장 에서 거의 필수 기능 이기 때문에 저 는 이 프로젝트 를 RxJava 버 전 으로 만 들 었 습 니 다.교류 와 지 도 를 환영 합 니 다.
UI 구현 자바 클래스:

MomentListFragment       395                  
MomentActivity         616                  、     (        )
MomentAdapter          67                
CommentAdapter         82                
MomentView           495                (    、  、   )
EmptyEventGridView       56                    (              View)
PraiseTextView         129                     (          ,               )
CommentView           153            (  、  、  )      (  、   ),        
CommentContainerView      172                    (     )
CommentTextView         122            (  、  )      (  、   )
UI 의 XML 레이아웃 구현:

moment_activity         47                   
moment_view           148             
comment_view          87             (  、  、  )   
comment_container_view     20                  
comment_item          10             (  、  )   
왜 Moment ListFragment 에 대응 하 는 XML 레이아웃 을 실현 하지 못 했 습 니까?
Moment ListFragment 는 BaseHttpListFragment 를 계승 하고 내 부 는 XListView 를 결 성 목록 View 로 사용 하기 때문에 스스로 실현 하지 않 아 도 된다.
데이터 가 져 오기,제출,처 리 를 위 한 자바 클래스:

HttpRequest           +175                (getMoment,...,deleteComment)
CommentUtil           140                     
Comment             56             
CommentItem           99                   
Moment             43             
MomentItem           272                  
User              103            
(비고:열거 되 지 않 은 코드 파일 은 동적 과 무관 하거나 APIJSON 또는 ZBLibrary 가 제공 합 니 다.server.model 의 클래스 는 서버 에서 제공 합 니 다)
 QQ 공간 과 위 챗 모멘트 를 모방 하여 높 은 디 결합 과 높 은 재 활용 이 유연 합 니 다.

테스트 서버 주소:139.196.140.118:8080 다운로드
APIJSONClientApp.apk
원본 및 문서(Star 에 게 주 십시오)
https://github.com/TommyLemon/APIJSON
위 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 안 드 로 이 드 모 의 QQ 공간 동적 인터페이스 공유 기능 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 저 에 게 메 시 지 를 남 겨 주세요.소 편 은 신속하게 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기