国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - Android如何實現社交應用中的評論與回復功能詳解

Android如何實現社交應用中的評論與回復功能詳解

2022-03-09 15:28水月沐風 Android

目前,各種App的社區(qū)或者用戶曬照片、發(fā)說說的地方,都提供了評論功能,為了更好地學習,自己把這個功能實現了一下,下面這篇文章主要給大家介紹了關于Android如何實現社交應用中的評論與回復功能的相關資料,需要的朋友可

前言

在Android的日常開發(fā)中,評論與回復功能是我們經常遇到的需求之一,其中評論與回復列表的展示一般在功能模塊中占比較大。對于需求改動和迭代較頻繁的公司來說,如何快速開發(fā)一個二級界面來適應我們的功能需求無疑優(yōu)先級更高一些。首先我們來看看其他社交類app的評論與回復列表如何展示的:

 Android如何實現社交應用中的評論與回復功能詳解Android如何實現社交應用中的評論與回復功能詳解

Twitter不用說了,全球知名社交平臺,上億用戶量,他們的評論回復都只展示一級數據(評論數據),其他更多內容(回復內容),是需要頁面跳轉去查看,知乎也類似。第一張圖是我們設計給我找的,他說要按照這個風格來,盡量將評論和回復內容在一個頁面展示。好吧,沒辦法,畢竟我們做前端的,UI要看設計臉色,數據要看后臺臉色????吹皆O計圖,我們腦海肯定第一時間聯想一下解決方案:用recyclerview?listview?不對,分析一下它的層級發(fā)現,評論是一個列表,里面的回復又是一個列表,難道用recyclerview或者listview的嵌套?抱著不確定的態(tài)度,立馬去網上查一下,果不其然,搜到的實現方式大多都是用嵌套實現的,來公司之前,其中一個項目里的評論回復功能就是用的嵌套listview,雖然處理了滑動沖突問題,但效果不佳,而且時常卡頓,所以,這里我肯定要換個思路。

網上還有說用自定義view實現的,但我發(fā)現大多沒有處理view的復用,而且開發(fā)成本大,暫時不予考慮。那怎么辦?無意中看到expandable這個關鍵詞,我突然想到谷歌很早之前出過一個擴展列表的控件 - ExpandableListView,但聽說比較老,存在一些問題。算了,試試再說,順便熟悉一下以前基礎控件的用法。

先來看一下最終的效果圖吧:

Android如何實現社交應用中的評論與回復功能詳解

這只是一個簡單的效果圖,你可以在此基礎上來完善它。好了,廢話不多說,下面讓我們來看看效果具體如何實現的吧。大家應該不難看出來,頁面整體采用了CoordinatorLayout來實現詳情頁的頂部視差效。同時,這里我采用ExpandableListView來實現多級列表,然后再解決它們的嵌套滑動問題。OK,我們先從ExpandableListView開始動手。

ExpandableListView

官方對于ExpandableListView給出這樣的解釋:A view that shows items in a vertically scrolling two-level list. This differs from the ListView by allowing two levels: groups which can individually be expanded to show its children. The items come from the ExpandableListAdapter associated with this view.

簡單來說,ExpandableListView是一個用于垂直方向滾動的二級列表視圖,ExpandableListView與listview不同之處在于,它可以實現二級分組,并通過ExpandableListAdapter來綁定數據和視圖。下面我們來一起實現上圖的效果。

布局中定義

首先,我們需要在xml的布局文件中聲明ExpandableListView:

?
1
2
3
4
5
6
7
8
<ExpandableListView
 android:id="@+id/detail_page_lv_comment"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:divider="@null"
 android:layout_marginBottom="64dp"
 android:listSelector="@android:color/transparent"
 android:scrollbars="none"/>

這里需要說明兩個問題:

  • ExpandableListView默認為它的item加上了點擊效果,由于item里面還包含了childItem,所以,點擊后,整個item里面的內容都會有點擊效果。我們可以取消其點擊特效,避免其影響用戶體驗,只需要設置如上代碼中的listSelector即可。
  • ExpandableListView具有默認的分割線,可以通過divider屬性將其隱藏。

設置Adapter

正如使用listView那樣,我們需要為ExpandableListView設置一個適配器Adapter,為其綁定數據和視圖。ExpandableListView的adapter需要繼承自ExpandableListAdapter,具體代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
 * Author: Moos
 * E-mail: moosphon@gmail.com
 * Date: 18/4/20.
 * Desc: 評論與回復列表的適配器
 */
 
public class CommentExpandAdapter extends BaseExpandableListAdapter {
 private static final String TAG = "CommentExpandAdapter";
 private List<CommentDetailBean> commentBeanList;
 private Context context;
 
 public CommentExpandAdapter(Context context, List<CommentDetailBean> commentBeanList) {
 this.context = context;
 this.commentBeanList = commentBeanList;
 }
 
 @Override
 public int getGroupCount() {
 return commentBeanList.size();
 }
 
 @Override
 public int getChildrenCount(int i) {
 if(commentBeanList.get(i).getReplyList() == null){
 return 0;
 }else {
 return commentBeanList.get(i).getReplyList().size()>0 ? commentBeanList.get(i).getReplyList().size():0;
 }
 
 }
 
 @Override
 public Object getGroup(int i) {
 return commentBeanList.get(i);
 }
 
 @Override
 public Object getChild(int i, int i1) {
 return commentBeanList.get(i).getReplyList().get(i1);
 }
 
 @Override
 public long getGroupId(int groupPosition) {
 return groupPosition;
 }
 
 @Override
 public long getChildId(int groupPosition, int childPosition) {
 return getCombinedChildId(groupPosition, childPosition);
 }
 
 @Override
 public boolean hasStableIds() {
 return true;
 }
 boolean isLike = false;
 
 @Override
 public View getGroupView(final int groupPosition, boolean isExpand, View convertView, ViewGroup viewGroup) {
 final GroupHolder groupHolder;
 
 if(convertView == null){
 convertView = LayoutInflater.from(context).inflate(R.layout.comment_item_layout, viewGroup, false);
 groupHolder = new GroupHolder(convertView);
 convertView.setTag(groupHolder);
 }else {
 groupHolder = (GroupHolder) convertView.getTag();
 }
 Glide.with(context).load(R.drawable.user_other)
 .diskCacheStrategy(DiskCacheStrategy.RESULT)
 .error(R.mipmap.ic_launcher)
 .centerCrop()
 .into(groupHolder.logo);
 groupHolder.tv_name.setText(commentBeanList.get(groupPosition).getNickName());
 groupHolder.tv_time.setText(commentBeanList.get(groupPosition).getCreateDate());
 groupHolder.tv_content.setText(commentBeanList.get(groupPosition).getContent());
 groupHolder.iv_like.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 if(isLike){
  isLike = false;
  groupHolder.iv_like.setColorFilter(Color.parseColor("#aaaaaa"));
 }else {
  isLike = true;
  groupHolder.iv_like.setColorFilter(Color.parseColor("#FF5C5C"));
 }
 }
 });
 
 return convertView;
 }
 
 @Override
 public View getChildView(final int groupPosition, int childPosition, boolean b, View convertView, ViewGroup viewGroup) {
 final ChildHolder childHolder;
 if(convertView == null){
 convertView = LayoutInflater.from(context).inflate(R.layout.comment_reply_item_layout,viewGroup, false);
 childHolder = new ChildHolder(convertView);
 convertView.setTag(childHolder);
 }
 else {
 childHolder = (ChildHolder) convertView.getTag();
 }
 
 String replyUser = commentBeanList.get(groupPosition).getReplyList().get(childPosition).getNickName();
 if(!TextUtils.isEmpty(replyUser)){
 childHolder.tv_name.setText(replyUser + ":");
 }
 
 childHolder.tv_content.setText(commentBeanList.get(groupPosition).getReplyList().get(childPosition).getContent());
 
 return convertView;
 }
 
 @Override
 public boolean isChildSelectable(int i, int i1) {
 return true;
 }
 
 private class GroupHolder{
 private CircleImageView logo;
 private TextView tv_name, tv_content, tv_time;
 private ImageView iv_like;
 public GroupHolder(View view) {
 logo = view.findViewById(R.id.comment_item_logo);
 tv_content = view.findViewById(R.id.comment_item_content);
 tv_name = view.findViewById(R.id.comment_item_userName);
 tv_time = view.findViewById(R.id.comment_item_time);
 iv_like = view.findViewById(R.id.comment_item_like);
 }
 }
 
 private class ChildHolder{
 private TextView tv_name, tv_content;
 public ChildHolder(View view) {
 tv_name = (TextView) view.findViewById(R.id.reply_item_user);
 tv_content = (TextView) view.findViewById(R.id.reply_item_content);
 }
 }
}

一般情況下,我們自定義自己的ExpandableListAdapter后,需要實現以下幾個方法:

  • 構造方法,這個應該無需多說了,一般用來初始化數據等操作。
  • getGroupCount,返回group分組的數量,在當前需求中指代評論的數量。
  • getChildrenCount,返回所在group中child的數量,這里指代當前評論對應的回復數目。
  • getGroup,返回group的實際數據,這里指的是當前評論數據。
  • getChild,返回group中某個child的實際數據,這里指的是當前評論的某個回復數據。
  • getGroupId,返回分組的id,一般將當前group的位置傳給它。
  • getChildId,返回分組中某個child的id,一般也將child當前位置傳給它,不過為了避免重復,可以使用getCombinedChildId(groupPosition, childPosition);來獲取id并返回。
  • hasStableIds,表示分組和子選項是否持有穩(wěn)定的id,這里返回true即可。
  • isChildSelectable,表示分組中的child是否可以選中,這里返回true。
  • getGroupView,即返回group的視圖,一般在這里進行一些數據和視圖綁定的工作,一般為了復用和高效,可以自定義ViewHolder,用法與listview一樣,這里就不多說了。
  • getChildView,返回分組中child子項的視圖,比較容易理解,第一個參數是當前group所在的位置,第二個參數是當前child所在位置。

這里的數據是我自己做的模擬數據,不過應該算是較為通用的格式了,大體格式如下:

Android如何實現社交應用中的評論與回復功能詳解

一般情況下,我們后臺會通過接口返回給我們一部分數據,如果想要查看更多評論,需要跳轉到“更多頁面”去查看,這里為了方便,我們只考慮加載部分數據。

Activity中使用

接下來,我們就需要在activity中顯示評論和回復的二級列表了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
private ExpandableListView expandableListView;
private CommentExpandAdapter adapter;
private CommentBean commentBean;
private List<CommentDetailBean> commentsList;
 
...
 
@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 initView();
 }
 
 private void initView() {
 
 expandableListView = findViewById(R.id.detail_page_lv_comment);
 initExpandableListView(commentsList);
 }
 
 /**
 * 初始化評論和回復列表
 */
 private void initExpandableListView(final List<CommentDetailBean> commentList){
 expandableListView.setGroupIndicator(null);
 //默認展開所有回復
 adapter = new CommentExpandAdapter(this, commentList);
 expandableListView.setAdapter(adapter);
 for(int i = 0; i<commentList.size(); i++){
  expandableListView.expandGroup(i);
 }
 expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
  @Override
  public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long l) {
  boolean isExpanded = expandableListView.isGroupExpanded(groupPosition);
  Log.e(TAG, "onGroupClick: 當前的評論id>>>"+commentList.get(groupPosition).getId());
 
//  if(isExpanded){
//   expandableListView.collapseGroup(groupPosition);
//  }else {
//   expandableListView.expandGroup(groupPosition, true);
//  }
 
  return true;
  }
 });
 
 expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
  @Override
  public boolean onChildClick(ExpandableListView expandableListView, View view, int groupPosition, int childPosition, long l) {
  Toast.makeText(MainActivity.this,"點擊了回復",Toast.LENGTH_SHORT).show();
  return false;
  }
 });
 
 expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
  @Override
  public void onGroupExpand(int groupPosition) {
  //toast("展開第"+groupPosition+"個分組");
 
  }
 });
 
 }
 
 /**
 * by moos on 2018/04/20
 * func:生成測試數據
 * @return 評論數據
 */
 private List<CommentDetailBean> generateTestData(){
 Gson gson = new Gson();
 commentBean = gson.fromJson(testJson, CommentBean.class);
 List<CommentDetailBean> commentList = commentBean.getData().getList();
 return commentList;
 }

就以上代碼作一下簡單說明:

1、ExpandableListView在默認情況下會為我們自帶分組的icon(??),當前需求下,我們根本不需要展示,可以通過expandableListView.setGroupIndicator(null)來隱藏。

2、一般情況下,我們可能需要默認展開所有的分組,我就可以通過循環(huán)來調用expandableListView.expandGroup(i);方法。

3、ExpandableListView為我們提供了group和child的點擊事件,分別通過setOnGroupClickListener和setOnChildClickListener來設置。值得注意的是,group的點擊事件里如果我們返回的是false,那么我們點擊group就會自動展開,但我這里碰到一個問題,當我返回false時,第一條評論數據會多出一條。通過百度查找方法,雖然很多類似問題,但終究沒有解決,最后我返回了ture,并通過以下代碼手動展開和收縮就可以了:

?
1
2
3
4
5
if(isExpanded){
 expandableListView.collapseGroup(groupPosition);
}else {
 expandableListView.expandGroup(groupPosition, true);
}

4、此外,我們還可以通過setOnGroupExpandListener和setOnGroupCollapseListener來監(jiān)聽ExpandableListView的分組展開和收縮的狀態(tài)。

評論和回復功能

為了模擬整個評論和回復功能,我們還需要手動插入收據并刷新數據列表。這里我就簡單做一下模擬,請忽略一些UI上的細節(jié)。

插入評論數據

插入評論數據比較簡單,只需要在list中插入一條數據并刷新即可:

?
1
2
3
4
5
6
7
8
9
10
11
12
String commentContent = commentText.getText().toString().trim();
if(!TextUtils.isEmpty(commentContent)){
 
 //commentOnWork(commentContent);
 dialog.dismiss();
 CommentDetailBean detailBean = new CommentDetailBean("小明", commentContent,"剛剛");
 adapter.addTheCommentData(detailBean);
 Toast.makeText(MainActivity.this,"評論成功",Toast.LENGTH_SHORT).show();
 
}else {
 Toast.makeText(MainActivity.this,"評論內容不能為空",Toast.LENGTH_SHORT).show();
}

adapter中的addTheCommentData方法如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * by moos on 2018/04/20
 * func:評論成功后插入一條數據
 * @param commentDetailBean 新的評論數據
 */
public void addTheCommentData(CommentDetailBean commentDetailBean){
 if(commentDetailBean!=null){
 
 commentBeanList.add(commentDetailBean);
 notifyDataSetChanged();
 }else {
 throw new IllegalArgumentException("評論數據為空!");
 }
}

代碼比較容易理解,就不多做說明了。

插入回復數據

首先,我們需要實現點擊某一條評論,然后@ta,那么我們需要在group的點擊事件里彈起回復框:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
  @Override
  public boolean onGroupClick(ExpandableListView expandableListView, View view, int groupPosition, long l) {
 
  showReplyDialog(groupPosition);
  return true;
  }
 });
 
......
 
/**
 * by moos on 2018/04/20
 * func:彈出回復框
 */
 private void showReplyDialog(final int position){
 dialog = new BottomSheetDialog(this);
 View commentView = LayoutInflater.from(this).inflate(R.layout.comment_dialog_layout,null);
 final EditText commentText = (EditText) commentView.findViewById(R.id.dialog_comment_et);
 final Button bt_comment = (Button) commentView.findViewById(R.id.dialog_comment_bt);
 commentText.setHint("回復 " + commentsList.get(position).getNickName() + " 的評論:");
 dialog.setContentView(commentView);
 bt_comment.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
  String replyContent = commentText.getText().toString().trim();
  if(!TextUtils.isEmpty(replyContent)){
 
   dialog.dismiss();
   ReplyDetailBean detailBean = new ReplyDetailBean("小紅",replyContent);
   adapter.addTheReplyData(detailBean, position);
   Toast.makeText(MainActivity.this,"回復成功",Toast.LENGTH_SHORT).show();
  }else {
   Toast.makeText(MainActivity.this,"回復內容不能為空",Toast.LENGTH_SHORT).show();
  }
  }
 });
 commentText.addTextChangedListener(new TextWatcher() {
  @Override
  public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
 
  }
 
  @Override
  public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  if(!TextUtils.isEmpty(charSequence) && charSequence.length()>2){
   bt_comment.setBackgroundColor(Color.parseColor("#FFB568"));
  }else {
   bt_comment.setBackgroundColor(Color.parseColor("#D8D8D8"));
  }
  }
 
  @Override
  public void afterTextChanged(Editable editable) {
 
  }
 });
 dialog.show();
 }

插入回復的數據與上面插入評論類似,這里貼一下adapter中的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * by moos on 2018/04/20
 * func:回復成功后插入一條數據
 * @param replyDetailBean 新的回復數據
 */
public void addTheReplyData(ReplyDetailBean replyDetailBean, int groupPosition){
 if(replyDetailBean!=null){
 Log.e(TAG, "addTheReplyData: >>>>該刷新回復列表了:"+replyDetailBean.toString() );
 if(commentBeanList.get(groupPosition).getReplyList() != null ){
  commentBeanList.get(groupPosition).getReplyList().add(replyDetailBean);
 }else {
  List<ReplyDetailBean> replyList = new ArrayList<>();
  replyList.add(replyDetailBean);
  commentBeanList.get(groupPosition).setReplyList(replyList);
 }
 notifyDataSetChanged();
 }else {
 throw new IllegalArgumentException("回復數據為空!");
 }
}

需要注意一點,由于不一定所有的評論都有回復數據,所以在插入數據前我們要判斷ReplyList是否為空,如果不為空,直接獲取當前評論的回復列表,并插入數據;如果為空,需要new一個ReplyList,插入數據后還要為評論set一下ReplyList。

解決CoordinatorLayout與ExpandableListView嵌套問題

如果你不需要使用CoordinatorLayout或者NestedScrollView,可以跳過本小節(jié)。一般情況下,我們產品為了更好的用戶體驗,還需要我們加上類似的頂部視差效果或者下拉刷新等,這就要我們處理一些常見的嵌套滑動問題了。

由于CoordinatorLayout實現NestedScrollingParent接口,RecycleView實現了NestedScrollingChild接口,所以就可以在NestedScrollingChildHelper的幫助下實現嵌套滑動,那么我們也可以通過自定義的ExpandableListView實現NestedScrollingChild接口來達到同樣的效果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
 * Author: Moos
 * E-mail: moosphon@gmail.com
 * Date: 18/4/20.
 * Desc: 自定義ExpandableListView,解決與CoordinatorLayout滑動沖突問題
 */
 
public class CommentExpandableListView extends ExpandableListView implements NestedScrollingChild{
 private NestedScrollingChildHelper mScrollingChildHelper;
 
 
 public CommentExpandableListView(Context context, AttributeSet attrs) {
 super(context, attrs);
 mScrollingChildHelper = new NestedScrollingChildHelper(this);
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  setNestedScrollingEnabled(true);
 }
 
 }
 
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
 super.onMeasure(widthMeasureSpec, expandSpec);
 
 }
 
 @Override
 public void setNestedScrollingEnabled(boolean enabled) {
 mScrollingChildHelper.setNestedScrollingEnabled(enabled);
 }
 
 @Override
 public boolean isNestedScrollingEnabled() {
 return mScrollingChildHelper.isNestedScrollingEnabled();
 }
 
 @Override
 public boolean startNestedScroll(int axes) {
 return mScrollingChildHelper.startNestedScroll(axes);
 }
 
 @Override
 public void stopNestedScroll() {
 mScrollingChildHelper.stopNestedScroll();
 }
 
 @Override
 public boolean hasNestedScrollingParent() {
 return mScrollingChildHelper.hasNestedScrollingParent();
 }
 
 @Override
 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
     int dyUnconsumed, int[] offsetInWindow) {
 return mScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
  dxUnconsumed, dyUnconsumed, offsetInWindow);
 }
 
 @Override
 public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
 return mScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
 }
 
 @Override
 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
 return mScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
 }
 
 @Override
 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
 return mScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
 }
}

代碼就不解釋了,畢竟這不是本篇文章等重點,大家可以去網上查閱NestedScrollView相關文章或者源碼去對照理解。

完整的布局代碼比較多,這里就不貼了,大家可以去github上面查看:https://github.com/Moosphan/CommentWithReplyView-master

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://blog.csdn.net/s1674521/article/details/80075220

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产高清视频一区 | 婷婷五综合 | 中文字幕一区二区三区乱码图片 | 91视频进入 | 日韩视频在线观看 | 天天干女人网 | 亚洲国产aⅴ成人精品无吗 成人午夜视频在线观看 | 日韩精品在线一区 | 狠狠躁夜夜躁人人爽天天天天97 | 亚洲高清在线视频 | 一二三四区视频在线观看 | 国产麻豆一区二区三区 | 免费视频一区 | 亚洲成人精品一区 | 亚洲精品一区二区在线 | 国产日韩久久 | 国产精品美女久久久久久久网站 | 日本不卡一区二区三区在线观看 | 国产成人午夜 | 久久精品一级 | 黄毛片| 亚洲成人免费观看 | 羞羞网站免费观看 | av亚洲在线 | 大桥未久亚洲精品久久久强制中出 | 久久国际影院 | 精品99在线 | 日韩国产| 玖玖爱视频在线 | 青娱乐国产精品视频 | 欧美三级视频 | 国产精品久久久久国产a级 最新国产视频 | 亚洲精品www久久久久久广东 | 黄色三级免费网站 | av观看 | 日韩电影在线一区 | 丝袜+亚洲+另类+欧美+变态 | 久久99精品久久久久久久青青日本 | 日韩一二三 | 中文在线观看www | 国产在线中文字幕 |