国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿QQ空間動態界面分享功能

2019-10-23 18:30:18
字體:
來源:轉載
供稿:網友

先看看效果:

android,仿QQ空間,android動態界面android,仿QQ空間,android動態界面android,仿QQ空間,android動態界面

android,仿QQ空間,android動態界面android,仿QQ空間,android動態界面android,仿QQ空間,android動態界面

用極少的代碼實現了 動態詳情 及 二級評論 的 數據獲取與處理 和 UI顯示與交互,并且高解耦、高復用、高靈活。

動態列表界面MomentListFragment支持 下拉刷新與上拉加載 和 模糊搜索,反復快速滑動仍然非常流暢。

緩存機制使得數據可在啟動界面后瞬間加載完成。

android,仿QQ空間,android動態界面

動態詳情界面MomentActivity支持 (取消)點贊、(刪除)評論、點擊姓名跳到個人詳情 等。

只有1張圖片時圖片放大顯示,超過1張則按九宮格顯示。

android,仿QQ空間,android動態界面

用到的CommentContainerView和MomentView都是獨立的組件,既可單獨使用,也可用于ListView或添加至其它ViewGroup等。

CommentContainerView復用

android,仿QQ空間,android動態界面android,仿QQ空間,android動態界面

CommentContainerView.java

setOnCommentClickListener    : 設置點擊評論監聽createView           : 創建ViewbindView            : 綁定數據并顯示ViewsetMaxShowCount         : 設置最多顯示數量,超過則折疊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 * @useCommentContainerView 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復用

android,仿QQ空間,android動態界面android,仿QQ空間,android動態界面

MomentView.java

setOnPictureClickListener    : 設置點擊圖片監聽createView           : 創建ViewbindView            : 綁定數據并顯示ViewsetPraise            : 設置點贊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 * @useMomentView 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的Java類:

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行        二級評論(姓名、內容)的顯示

為什么沒有實現MomentListFragment對應的XML布局?

因為MomentListFragment繼承BaseHttpListFragment,內部用XListView作為缺省列表View,所以可以不用自己實現了。

實現數據獲取、提交和處理的Java類:

HttpRequest           +175行       數據的獲取和提交(getMoment,...,deleteComment)CommentUtil           140行       單層評論和和二級評論的處理Comment             56行        評論數據CommentItem           99行        評論的顯示和交互數據Moment             43行        動態數據MomentItem           272行       動態的顯示和交互數據User              103行       用戶數據

(注:未列出的代碼文件要么和動態無關,要么APIJSON或ZBLibrary已提供。server.model里的類由服務端提供)

 仿QQ空間和微信朋友圈,高解耦高復用高靈活

android,仿QQ空間,android動態界面

下載試用(測試服務器地址:139.196.140.118:8080)

APIJSONClientApp.apk

源碼及文檔(記得給個Star哦)

https://github.com/TommyLemon/APIJSON

以上所述是小編給大家介紹的Android仿QQ空間動態界面分享功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 清镇市| 嘉祥县| 水富县| 元朗区| 天全县| 阿克陶县| 清新县| 鱼台县| 大方县| 临泉县| 原平市| 台南县| 阳春市| 礼泉县| 永寿县| 永兴县| 改则县| 台东市| 静宁县| 茶陵县| 张家港市| 济阳县| 锡林郭勒盟| 聊城市| 咸丰县| 昌黎县| 平乐县| 车险| 贵阳市| 文化| 缙云县| 万盛区| 板桥市| 嘉定区| 滁州市| 青浦区| 饶平县| 周至县| 兴国县| 若羌县| 南丰县|