├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── AndroidTimelineView.iml
├── README.md
├── android-timeline-view-lib
├── .gitignore
├── android-timeline-view-lib.iml
├── bintray-publish-github.gradle
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── net
│ │ └── datafans
│ │ └── android
│ │ └── timeline
│ │ ├── adapter
│ │ ├── BaseLineCellAdapter.java
│ │ ├── CellAdapterManager.java
│ │ ├── TextImageLineCellAdapter.java
│ │ └── user
│ │ │ ├── BaseUserLineCellAdapter.java
│ │ │ ├── TextImageUserLineCellAdapter.java
│ │ │ └── UserCellAdapterManager.java
│ │ ├── controller
│ │ ├── BaseTimelineViewController.java
│ │ ├── TimelineViewController.java
│ │ └── UserTimelineViewController.java
│ │ ├── event
│ │ ├── CommentClickEvent.java
│ │ └── UserClickEvent.java
│ │ ├── item
│ │ ├── BaseLineItem.java
│ │ ├── LineCommentItem.java
│ │ ├── LineItemType.java
│ │ ├── LineLikeItem.java
│ │ ├── TextImageLineItem.java
│ │ └── user
│ │ │ ├── BaseUserLineItem.java
│ │ │ ├── TextImageUserLineItem.java
│ │ │ └── UserLineItemType.java
│ │ └── view
│ │ ├── BaseLineCell.java
│ │ ├── TextImageLineCell.java
│ │ ├── commentInput
│ │ └── CommentInputView.java
│ │ ├── imagegrid
│ │ └── ImageGridView.java
│ │ ├── likeCmt
│ │ └── LikeCommentView.java
│ │ ├── span
│ │ ├── LinkTouchMovementMethod.java
│ │ └── TouchSpan.java
│ │ └── user
│ │ ├── BaseUserLineCell.java
│ │ └── TextImageUserLineCell.java
│ └── res
│ ├── drawable-hdpi
│ └── like_cmt_bg.9.png
│ ├── drawable-mdpi
│ └── like_cmt_bg.9.png
│ ├── drawable-xhdpi
│ └── like_cmt_bg.9.png
│ ├── drawable-xxhdpi
│ └── like_cmt_bg.9.png
│ ├── drawable
│ ├── comment_edit_text_bg.xml
│ ├── comment_send_btn_bg.xml
│ └── header_avatar_bg.xml
│ ├── layout
│ ├── base_cell.xml
│ ├── base_user_cell.xml
│ ├── comment_input.xml
│ ├── header.xml
│ ├── like_comment.xml
│ ├── nine_image_grid.xml
│ └── user_text_image_cell.xml
│ ├── mipmap-xxhdpi
│ ├── album_like.png
│ ├── album_operation.png
│ ├── toolbar_comment.png
│ └── toolbar_like.png
│ └── values
│ ├── colors.xml
│ └── strings.xml
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── net
│ │ └── datafans
│ │ └── androidtimelineview
│ │ ├── MainActivity.java
│ │ └── UserFeedActivity.java
│ └── res
│ ├── layout
│ ├── activity_main.xml
│ └── activity_user_feed.xml
│ ├── menu
│ ├── menu_main.xml
│ └── menu_user_feed.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | AndroidTimelineView
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/AndroidTimelineView.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidTimelineView
2 | 仿微信朋友圈
3 |
4 |
5 | compile('net.datafans:android-timeline-view-lib:1.0.+')
6 |
7 | iOS版本: https://github.com/anyunzhong/DFTimelineView
8 |
9 |
10 | 
11 |
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/android-timeline-view-lib.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
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 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/bintray-publish-github.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: 'com.jfrog.bintray'
4 |
5 | version = "1.0.10"
6 |
7 | def siteUrl = 'https://github.com/anyunzhong/AndroidTimelineView' // 项目的主页
8 | def gitUrl = 'https://github.com/anyunzhong/AndroidTimelineView.git' // Git仓库的url
9 | group = "net.datafans" // Maven Group ID for the artifact,一般填你唯一的包名
10 |
11 | install {
12 | repositories.mavenInstaller {
13 | // This generates POM.xml with proper parameters
14 | pom {
15 | project {
16 | packaging 'aar'
17 | // Add your description here
18 | name 'AndroidTimelineView' //项目描述
19 | url siteUrl
20 | // Set your license
21 | licenses {
22 | license {
23 | name 'The Apache Software License, Version 2.0'
24 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
25 | }
26 | }
27 | developers {
28 | developer {
29 | id 'anyunzhong' //填写的一些基本信息
30 | name 'Allen Zhong'
31 | email '2642754767@qq.com'
32 | }
33 | }
34 | scm {
35 | connection gitUrl
36 | developerConnection gitUrl
37 | url siteUrl
38 | }
39 | }
40 | }
41 | }
42 | }
43 | task sourcesJar(type: Jar) {
44 | from android.sourceSets.main.java.srcDirs
45 | classifier = 'sources'
46 | }
47 | task javadoc(type: Javadoc) {
48 | source = android.sourceSets.main.java.srcDirs
49 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
50 | }
51 | task javadocJar(type: Jar, dependsOn: javadoc) {
52 | classifier = 'javadoc'
53 | from javadoc.destinationDir
54 | }
55 | artifacts {
56 | //archives javadocJar
57 | archives sourcesJar
58 | }
59 | Properties properties = new Properties()
60 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
61 | bintray {
62 | user = properties.getProperty("bintray.user")
63 | key = properties.getProperty("bintray.apikey")
64 | configurations = ['archives']
65 | pkg {
66 | repo = "maven"
67 | name = "AndroidTimelineView" //发布到JCenter上的项目名字
68 | websiteUrl = siteUrl
69 | vcsUrl = gitUrl
70 | licenses = ["Apache-2.0"]
71 | publish = true
72 | }
73 | }
--------------------------------------------------------------------------------
/android-timeline-view-lib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | compile('net.datafans:android-common-lib:1.2.85')
24 | {
25 | exclude group: 'com.google.android', module: 'support-v4'
26 | }
27 | }
28 |
29 | apply from: 'bintray-publish-github.gradle'
30 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/zhonganyun/Documents/Java/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/adapter/BaseLineCellAdapter.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.adapter;
2 |
3 | import android.content.Context;
4 |
5 | import net.datafans.android.common.widget.table.TableViewCell;
6 |
7 | /**
8 | * Created by zhonganyun on 15/10/6.
9 | */
10 | public abstract class BaseLineCellAdapter {
11 |
12 | private Context context;
13 |
14 | public Context getContext() {
15 | return context;
16 | }
17 |
18 | public void setContext(Context context) {
19 | this.context = context;
20 | }
21 |
22 | public abstract TableViewCell getCell();
23 | }
24 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/adapter/CellAdapterManager.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.adapter;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * Created by zhonganyun on 15/10/06.
8 | */
9 | public class CellAdapterManager {
10 |
11 | private static final CellAdapterManager manager = new CellAdapterManager();
12 |
13 | private Map adapterMap = new HashMap<>();
14 |
15 | public static CellAdapterManager sharedInstance() {
16 | return manager;
17 | }
18 |
19 | public void registerAdapter(Integer type, BaseLineCellAdapter adapter) {
20 | adapterMap.put(type, adapter);
21 | }
22 |
23 | public BaseLineCellAdapter getAdapter(Integer type) {
24 | return adapterMap.get(type);
25 | }
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/adapter/TextImageLineCellAdapter.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.adapter;
2 |
3 | import net.datafans.android.common.widget.table.TableViewCell;
4 | import net.datafans.android.timeline.R;
5 | import net.datafans.android.timeline.view.TextImageLineCell;
6 |
7 | /**
8 | * Created by zhonganyun on 15/10/6.
9 | */
10 | public class TextImageLineCellAdapter extends BaseLineCellAdapter {
11 |
12 |
13 | @Override
14 | public TableViewCell getCell() {
15 | return new TextImageLineCell(R.layout.base_cell, getContext());
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/adapter/user/BaseUserLineCellAdapter.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.adapter.user;
2 |
3 | import android.content.Context;
4 |
5 | import net.datafans.android.common.widget.table.TableViewCell;
6 |
7 | /**
8 | * Created by zhonganyun on 15/10/6.
9 | */
10 | public abstract class BaseUserLineCellAdapter {
11 |
12 | private Context context;
13 |
14 | public Context getContext() {
15 | return context;
16 | }
17 |
18 | public void setContext(Context context) {
19 | this.context = context;
20 | }
21 |
22 | public abstract TableViewCell getCell();
23 | }
24 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/adapter/user/TextImageUserLineCellAdapter.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.adapter.user;
2 |
3 | import net.datafans.android.common.widget.table.TableViewCell;
4 | import net.datafans.android.timeline.R;
5 | import net.datafans.android.timeline.adapter.BaseLineCellAdapter;
6 | import net.datafans.android.timeline.view.TextImageLineCell;
7 | import net.datafans.android.timeline.view.user.TextImageUserLineCell;
8 |
9 | /**
10 | * Created by zhonganyun on 15/10/6.
11 | */
12 | public class TextImageUserLineCellAdapter extends BaseUserLineCellAdapter {
13 |
14 |
15 | @Override
16 | public TableViewCell getCell() {
17 | return new TextImageUserLineCell(R.layout.base_user_cell, getContext());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/adapter/user/UserCellAdapterManager.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.adapter.user;
2 |
3 | import net.datafans.android.timeline.adapter.BaseLineCellAdapter;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | /**
9 | * Created by zhonganyun on 15/10/06.
10 | */
11 | public class UserCellAdapterManager {
12 |
13 | private static final UserCellAdapterManager manager = new UserCellAdapterManager();
14 |
15 | private Map adapterMap = new HashMap<>();
16 |
17 | public static UserCellAdapterManager sharedInstance() {
18 | return manager;
19 | }
20 |
21 | public void registerAdapter(Integer type, BaseUserLineCellAdapter adapter) {
22 | adapterMap.put(type, adapter);
23 | }
24 |
25 | public BaseUserLineCellAdapter getAdapter(Integer type) {
26 | return adapterMap.get(type);
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/controller/BaseTimelineViewController.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.controller;
2 |
3 | import android.graphics.Color;
4 | import android.graphics.drawable.ColorDrawable;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.view.WindowManager;
8 | import android.widget.TextView;
9 |
10 | import net.datafans.android.common.helper.DipHelper;
11 | import net.datafans.android.common.widget.controller.TableViewController;
12 | import net.datafans.android.common.widget.imageview.CommonImageView;
13 | import net.datafans.android.timeline.R;
14 |
15 | /**
16 | * Created by zhonganyun on 15/10/17.
17 | */
18 | public abstract class BaseTimelineViewController extends TableViewController {
19 |
20 | private CommonImageView coverView;
21 |
22 | protected CommonImageView userAvatarView;
23 |
24 | protected TextView userNickView;
25 |
26 | protected TextView signView;
27 |
28 | protected int coverWidth;
29 | protected int coverHeight;
30 |
31 | protected int userAvatarSize;
32 |
33 |
34 | protected int userId;
35 |
36 |
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 |
42 | tableView.getAdapter().getListView().setSelector(new ColorDrawable(Color.TRANSPARENT));
43 | tableView.hideDivider();
44 | }
45 |
46 | @Override
47 | protected int getStatusBarColor() {
48 | return Color.rgb(30, 35, 46);
49 | }
50 |
51 |
52 | @Override
53 | protected View getTableHeaderView() {
54 | View header = getLayoutInflater().inflate(R.layout.header, null);
55 | coverView = (CommonImageView) header.findViewById(R.id.cover);
56 |
57 |
58 | WindowManager wm = this.getWindowManager();
59 | int width = wm.getDefaultDisplay().getWidth();
60 | coverWidth = width;
61 | coverHeight = DipHelper.dip2px(this, 200);
62 |
63 |
64 | userAvatarView = (CommonImageView) header.findViewById(R.id.userAvatar);
65 |
66 | userAvatarView.setOnClickListener(new View.OnClickListener() {
67 | @Override
68 | public void onClick(View view) {
69 | onClickHeaderUserAvatar();
70 | }
71 | });
72 | userAvatarSize = 160;
73 |
74 | userNickView = (TextView) header.findViewById(R.id.userNick);
75 | signView = (TextView) header.findViewById(R.id.sign);
76 | return header;
77 | }
78 |
79 | protected abstract void onClickHeaderUserAvatar();
80 |
81 |
82 | protected void setCover(String url) {
83 | coverView.loadImage(url);
84 | }
85 |
86 | protected void setUserAvatar(String url) {
87 | userAvatarView.loadImage(url);
88 | }
89 |
90 | protected void setUserNick(String nick) {
91 | userNickView.setText(nick);
92 | }
93 |
94 | protected void setUserId(int userId){
95 | this.userId = userId;
96 | }
97 |
98 |
99 | protected void setUserSign(String sign) {
100 | signView.setText(sign);
101 | }
102 |
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/controller/TimelineViewController.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.controller;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.os.Bundle;
7 | import android.text.SpannableString;
8 | import android.text.Spanned;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.view.ViewTreeObserver;
12 | import android.view.WindowManager;
13 | import android.widget.RelativeLayout;
14 |
15 | import net.datafans.android.common.helper.LogHelper;
16 | import net.datafans.android.common.widget.table.TableViewCell;
17 | import net.datafans.android.common.widget.table.refresh.RefreshControlType;
18 | import net.datafans.android.timeline.adapter.BaseLineCellAdapter;
19 | import net.datafans.android.timeline.adapter.CellAdapterManager;
20 | import net.datafans.android.timeline.adapter.TextImageLineCellAdapter;
21 | import net.datafans.android.timeline.event.CommentClickEvent;
22 | import net.datafans.android.timeline.event.UserClickEvent;
23 | import net.datafans.android.timeline.item.BaseLineItem;
24 | import net.datafans.android.timeline.item.LineCommentItem;
25 | import net.datafans.android.timeline.item.LineItemType;
26 | import net.datafans.android.timeline.item.LineLikeItem;
27 | import net.datafans.android.timeline.view.BaseLineCell;
28 | import net.datafans.android.timeline.view.commentInput.CommentInputView;
29 | import net.datafans.android.timeline.view.span.TouchSpan;
30 |
31 | import java.util.ArrayList;
32 | import java.util.HashMap;
33 | import java.util.List;
34 | import java.util.Map;
35 |
36 | import de.greenrobot.event.EventBus;
37 |
38 | /**
39 | * Created by zhonganyun on 15/10/6.
40 | */
41 | public abstract class TimelineViewController extends BaseTimelineViewController implements CommentInputView.Delegate, BaseLineCell.BaseLineCellDelegate {
42 |
43 |
44 | private View rootView;
45 |
46 | private List items = new ArrayList<>();
47 |
48 | private CommentInputView inputView;
49 |
50 | private long currentItemId;
51 |
52 | private BaseLineCell currentOptCell;
53 |
54 | private Map itemMap = new HashMap<>();
55 | private Map commentItemMap = new HashMap<>();
56 |
57 | private boolean isKeyboardShow = false;
58 |
59 | @Override
60 | protected void onCreate(Bundle savedInstanceState) {
61 |
62 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
63 |
64 | super.onCreate(savedInstanceState);
65 |
66 | initAdapters();
67 |
68 | rootView = getRootView(this);
69 | rootView.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
70 |
71 |
72 | tableView.getAdapter().getListView().setSelector(new ColorDrawable(Color.TRANSPARENT));
73 | tableView.hideDivider();
74 |
75 | initCommentInputView();
76 |
77 | EventBus.getDefault().register(this);
78 | }
79 |
80 |
81 | private void initAdapters(){
82 | CellAdapterManager manager = CellAdapterManager.sharedInstance();
83 |
84 | TextImageLineCellAdapter imageLineCellAdapter = new TextImageLineCellAdapter();
85 | imageLineCellAdapter.setContext(this);
86 | manager.registerAdapter(LineItemType.TextImage, imageLineCellAdapter);
87 | }
88 |
89 |
90 | private void initCommentInputView() {
91 | inputView = new CommentInputView(this);
92 | inputView.setVisibility(View.GONE);
93 | inputView.setDelegate(this);
94 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
95 | containerParent.addView(inputView, params);
96 | }
97 |
98 |
99 |
100 |
101 |
102 | @Override
103 | protected RefreshControlType getRefreshControlType() {
104 |
105 | return RefreshControlType.BGANormal;
106 | }
107 |
108 | @Override
109 | public int getRows(int section) {
110 |
111 | return items.size();
112 | }
113 |
114 | @Override
115 | public TableViewCell getTableViewCell(int section, int row) {
116 |
117 | BaseLineItem item = items.get(row);
118 | BaseLineCellAdapter adapter = getAdapter(item.itemType);
119 | BaseLineCell cell = (BaseLineCell) adapter.getCell();
120 | cell.setDelegate(this);
121 | return cell;
122 | }
123 |
124 |
125 | @Override
126 | public int getItemViewType(int section, int row) {
127 |
128 | BaseLineItem item = getEntity(section, row);
129 | if (item.itemType == LineItemType.TextImage)
130 | return 0;
131 | return 100000;
132 | }
133 |
134 | @Override
135 | public int getItemViewTypeCount() {
136 |
137 | return 1;
138 | }
139 |
140 | @Override
141 | public BaseLineItem getEntity(int section, int row) {
142 | return items.get(row);
143 | }
144 |
145 | @Override
146 | public void onClickRow(int section, int row) {
147 |
148 | }
149 |
150 | @Override
151 | public void onRefresh() {
152 |
153 | }
154 |
155 | @Override
156 | public void onLoadMore() {
157 |
158 | }
159 |
160 |
161 | @SuppressWarnings("unused")
162 | public void onEvent(Object event) {
163 | if (event instanceof CommentClickEvent) {
164 | CommentClickEvent commentClickEvent = (CommentClickEvent) event;
165 | inputView.show();
166 | inputView.setCommentId(commentClickEvent.uniqueId);
167 | LineCommentItem commentItem = commentItemMap.get(commentClickEvent.uniqueId);
168 | if (commentItem != null)
169 | inputView.setPlaceHolder(" 回复:" + commentItem.userNick);
170 | currentItemId = commentClickEvent.itemId;
171 | } else if (event instanceof UserClickEvent) {
172 | UserClickEvent userClickEvent = (UserClickEvent) event;
173 | onUserClick(userClickEvent.userId);
174 | }
175 | }
176 |
177 |
178 | private BaseLineCellAdapter getAdapter(int itemType) {
179 | CellAdapterManager manager = CellAdapterManager.sharedInstance();
180 | return manager.getAdapter(itemType);
181 | }
182 |
183 |
184 | protected void addItem(BaseLineItem item) {
185 | items.add(item);
186 | itemMap.put(item.itemId, item);
187 | genLikeSpanStr(item);
188 | genCommentSpanStr(item);
189 | }
190 |
191 |
192 | protected void addLikeItem(LineLikeItem likeItem, long itemId) {
193 | BaseLineItem item = itemMap.get(itemId);
194 | if (item == null) return;
195 |
196 | item.likes.add(0, likeItem);
197 | genLikeSpanStr(item);
198 | tableView.reloadData();
199 | }
200 |
201 |
202 | protected void addCommentItem(LineCommentItem commentItem, long itemId, long replyCommentId) {
203 | BaseLineItem item = itemMap.get(itemId);
204 | if (item == null) return;
205 |
206 | if (replyCommentId > 0) {
207 | LineCommentItem replyCommentItem = commentItemMap.get(replyCommentId);
208 | if (replyCommentItem == null) return;
209 | commentItem.replyUserNick = replyCommentItem.userNick;
210 | commentItem.replyUserId = replyCommentItem.userId;
211 | }
212 |
213 | item.comments.add(commentItem);
214 | genCommentSpanStr(item);
215 | }
216 |
217 | @Override
218 | public void onCommentCreate(long commentId, String text) {
219 | //Log.e(Config.TAG, "commentId: " +commentId + " itemId: " + currentItemId);
220 | onCommentCreate(currentItemId, commentId, text);
221 | }
222 |
223 | protected abstract void onCommentCreate(long itemId, long commentId, String text);
224 |
225 |
226 | @Override
227 | public void onLikeClick(long itemId) {
228 | onLikeCreate(itemId);
229 | }
230 |
231 |
232 | protected abstract void onLikeCreate(long itemId);
233 |
234 |
235 | @Override
236 | public void onAlbumOptViewClick(BaseLineCell cell) {
237 | currentOptCell = cell;
238 | }
239 |
240 | @Override
241 | public void onCommentClick(long itemId) {
242 | currentItemId = itemId;
243 | inputView.show();
244 | inputView.setCommentId(0);
245 |
246 | }
247 |
248 | @Override
249 | public void onCellClick() {
250 | if (currentOptCell != null)
251 | currentOptCell.hideAlbumOptView();
252 | }
253 |
254 | protected abstract void onUserClick(int userId);
255 |
256 |
257 | @Override
258 | protected void onClickHeaderUserAvatar() {
259 | onUserClick(userId);
260 | }
261 |
262 | private void genLikeSpanStr(BaseLineItem item) {
263 |
264 | List likes = item.likes;
265 |
266 | StringBuilder builder = new StringBuilder();
267 | for (int i = 0; i < likes.size(); i++) {
268 | LineLikeItem like = likes.get(i);
269 | builder.append(like.userNick);
270 | if (i != (likes.size() - 1))
271 | builder.append(", ");
272 | }
273 |
274 |
275 | SpannableString spannableString = new SpannableString(builder.toString());
276 |
277 | int position = 0;
278 | for (int i = 0; i < likes.size(); i++) {
279 | LineLikeItem like = likes.get(i);
280 | spannableString.setSpan(new TouchSpan(this, like.userId), position, position + like.userNick.length(),
281 | Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
282 | position += like.userNick.length() + 2;
283 | }
284 |
285 | item.likeSpanStr = spannableString;
286 |
287 | }
288 |
289 |
290 | private void genCommentSpanStr(BaseLineItem item) {
291 |
292 |
293 | item.commentSpanStrs.clear();
294 |
295 | List comments = item.comments;
296 |
297 | for (int i = 0; i < comments.size(); i++) {
298 |
299 | LineCommentItem comment = comments.get(i);
300 |
301 | commentItemMap.put(comment.commentId, comment);
302 |
303 | StringBuilder builder = new StringBuilder();
304 | builder.append(comment.userNick);
305 | if (comment.replyUserNick != null) {
306 | builder.append("回复");
307 | builder.append(comment.replyUserNick);
308 | }
309 | builder.append(": ");
310 | builder.append(comment.text);
311 |
312 | SpannableString spannableString = new SpannableString(builder.toString());
313 |
314 |
315 | if (comment.replyUserNick == null) {
316 |
317 | spannableString.setSpan(new TouchSpan(this, comment.userId), 0, comment.userNick.length(),
318 | Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
319 | } else {
320 |
321 | int position = 0;
322 | spannableString.setSpan(new TouchSpan(this, comment.userId), position, position + comment.userNick.length(),
323 | Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
324 |
325 | position += comment.userNick.length() + 2; //2="回复"
326 | spannableString.setSpan(new TouchSpan(this, comment.replyUserId), position, position + comment.replyUserNick.length(),
327 | Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
328 | }
329 |
330 | item.commentSpanStrs.add(spannableString);
331 | }
332 | }
333 |
334 | private ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
335 | @Override
336 | public void onGlobalLayout() {
337 |
338 | int heightDiff = rootView.getHeight() - containerParent.getHeight();
339 |
340 | if (heightDiff > 300) {
341 | LogHelper.debug("键盘弹出状态");
342 | isKeyboardShow = true;
343 | } else {
344 | LogHelper.debug("键盘收起状态");
345 | if (isKeyboardShow)
346 | inputView.hide();
347 |
348 | isKeyboardShow = false;
349 |
350 | }
351 | }
352 | };
353 |
354 | private static View getRootView(Activity context) {
355 | return ((ViewGroup) context.findViewById(android.R.id.content)).getChildAt(0);
356 | }
357 |
358 | }
359 |
360 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/controller/UserTimelineViewController.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.controller;
2 |
3 | import android.os.Bundle;
4 |
5 | import net.datafans.android.common.widget.table.TableViewCell;
6 | import net.datafans.android.common.widget.table.refresh.RefreshControlType;
7 | import net.datafans.android.timeline.adapter.user.BaseUserLineCellAdapter;
8 | import net.datafans.android.timeline.adapter.user.TextImageUserLineCellAdapter;
9 | import net.datafans.android.timeline.adapter.user.UserCellAdapterManager;
10 | import net.datafans.android.timeline.item.user.BaseUserLineItem;
11 | import net.datafans.android.timeline.item.user.UserLineItemType;
12 | import net.datafans.android.timeline.view.user.BaseUserLineCell;
13 |
14 | import java.util.ArrayList;
15 | import java.util.Calendar;
16 | import java.util.Date;
17 | import java.util.List;
18 |
19 | /**
20 | * Created by zhonganyun on 15/10/6.
21 | */
22 | public abstract class UserTimelineViewController extends BaseTimelineViewController implements BaseUserLineCell.Delegate {
23 |
24 | private List items = new ArrayList<>();
25 |
26 | private int currentYear;
27 |
28 | private int currentMonth;
29 |
30 | private int currentDay;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 |
35 | initAdapters();
36 |
37 | super.onCreate(savedInstanceState);
38 |
39 | }
40 |
41 |
42 | private void initAdapters(){
43 | UserCellAdapterManager manager = UserCellAdapterManager.sharedInstance();
44 | TextImageUserLineCellAdapter imageLineCellAdapter = new TextImageUserLineCellAdapter();
45 | imageLineCellAdapter.setContext(this);
46 | manager.registerAdapter(UserLineItemType.TextImage, imageLineCellAdapter);
47 | }
48 |
49 |
50 | @Override
51 | protected RefreshControlType getRefreshControlType() {
52 |
53 | return RefreshControlType.BGANormal;
54 | }
55 |
56 | @Override
57 | public int getRows(int section) {
58 |
59 | return items.size();
60 | }
61 |
62 | @Override
63 | public TableViewCell getTableViewCell(int section, int row) {
64 |
65 | BaseUserLineItem item = items.get(row);
66 | BaseUserLineCellAdapter adapter = getAdapter(item.itemType);
67 | BaseUserLineCell cell = (BaseUserLineCell) adapter.getCell();
68 | cell.setDelegate(this);
69 | return cell;
70 | }
71 |
72 |
73 | @Override
74 | public int getItemViewType(int section, int row) {
75 |
76 | BaseUserLineItem item = getEntity(section, row);
77 | if (item.itemType == UserLineItemType.TextImage)
78 | return 0;
79 | return 100000;
80 | }
81 |
82 | @Override
83 | public int getItemViewTypeCount() {
84 |
85 | return 1;
86 | }
87 |
88 | @Override
89 | public BaseUserLineItem getEntity(int section, int row) {
90 | return items.get(row);
91 | }
92 |
93 | @Override
94 | public void onClickRow(int section, int row) {
95 |
96 | }
97 |
98 | @Override
99 | public void onRefresh() {
100 |
101 | }
102 |
103 | @Override
104 | public void onLoadMore() {
105 |
106 | }
107 |
108 |
109 | private BaseUserLineCellAdapter getAdapter(int itemType) {
110 | UserCellAdapterManager manager = UserCellAdapterManager.sharedInstance();
111 | return manager.getAdapter(itemType);
112 | }
113 |
114 |
115 | protected void addItem(BaseUserLineItem item) {
116 | items.add(item);
117 |
118 | Calendar calendar = Calendar.getInstance();
119 | calendar.setTime(new Date(item.ts));
120 |
121 | int year = calendar.get(Calendar.YEAR);
122 | int month = calendar.get(Calendar.MONTH)-1;
123 | int day = calendar.get(Calendar.DAY_OF_MONTH);
124 |
125 | item.year = year;
126 | item.month = month;
127 | item.day = day;
128 |
129 | if (currentYear == year && currentMonth == month && currentDay == day){
130 | item.isShowTime = false;
131 | }else{
132 | item.isShowTime = true;
133 | }
134 |
135 | currentYear = year;
136 | currentMonth = month;
137 | currentDay = day;
138 | }
139 |
140 | @Override
141 | protected void onClickHeaderUserAvatar() {
142 |
143 | }
144 | }
145 |
146 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/event/CommentClickEvent.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.event;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/12.
5 | */
6 | public class CommentClickEvent {
7 | public long uniqueId;
8 | public long itemId;
9 | }
10 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/event/UserClickEvent.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.event;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/14.
5 | */
6 | public class UserClickEvent {
7 | public int userId;
8 |
9 | public UserClickEvent(int userId) {
10 | this.userId = userId;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/BaseLineItem.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item;
2 |
3 | import android.text.SpannableString;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * Created by zhonganyun on 15/10/6.
10 | */
11 | public abstract class BaseLineItem {
12 |
13 | public long itemId;
14 | public int itemType;
15 |
16 | public int userId;
17 | public String userNick;
18 | public String userAvatar;
19 |
20 | public String title;
21 |
22 | public String location;
23 |
24 | public long ts;
25 |
26 | public List likes = new ArrayList<>();
27 | public List comments = new ArrayList<>();
28 |
29 | public SpannableString likeSpanStr;
30 |
31 | public List commentSpanStrs = new ArrayList<>();
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/LineCommentItem.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/6.
5 | */
6 | public class LineCommentItem {
7 | public long commentId;
8 | public int userId;
9 | public String userNick;
10 | public int replyUserId;
11 | public String replyUserNick;
12 | public String text;
13 |
14 | @Override
15 | public String toString() {
16 | return "LineCommentItem{" +
17 | "commentId=" + commentId +
18 | ", userId=" + userId +
19 | ", userNick='" + userNick + '\'' +
20 | ", replyUserId=" + replyUserId +
21 | ", replyUserNick='" + replyUserNick + '\'' +
22 | ", text='" + text + '\'' +
23 | '}';
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/LineItemType.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/6.
5 | */
6 | public class LineItemType {
7 |
8 | public static final int TextImage = 1;
9 | public static final int Share = 2;
10 | }
11 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/LineLikeItem.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/6.
5 | */
6 | public class LineLikeItem {
7 | public int userId;
8 | public String userNick;
9 | }
10 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/TextImageLineItem.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by zhonganyun on 15/10/6.
8 | */
9 | public class TextImageLineItem extends BaseLineItem {
10 |
11 | public TextImageLineItem(){
12 |
13 | this.itemType = LineItemType.TextImage;
14 | }
15 |
16 | public String text;
17 | public String parsedText;
18 | public List thumbImages = new ArrayList<>();
19 | public List srcImages = new ArrayList<>();
20 | public int width;
21 | public int height;
22 | }
23 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/user/BaseUserLineItem.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item.user;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/17.
5 | */
6 | public class BaseUserLineItem {
7 |
8 | public long itemId;
9 | public int itemType;
10 | public long ts;
11 | public int year;
12 | public int month;
13 | public int day;
14 | public boolean isShowTime;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/user/TextImageUserLineItem.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item.user;
2 |
3 | import net.datafans.android.timeline.item.LineItemType;
4 |
5 | /**
6 | * Created by zhonganyun on 15/10/17.
7 | */
8 | public class TextImageUserLineItem extends BaseUserLineItem {
9 |
10 |
11 | public TextImageUserLineItem(){
12 |
13 | this.itemType = UserLineItemType.TextImage;
14 | }
15 |
16 |
17 | public String cover;
18 | public String text;
19 | public int photoCount;
20 | }
21 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/item/user/UserLineItemType.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.item.user;
2 |
3 | /**
4 | * Created by zhonganyun on 15/10/6.
5 | */
6 | public class UserLineItemType {
7 |
8 | public static final int TextImage = 1;
9 | public static final int Share = 2;
10 | }
11 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/BaseLineCell.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.widget.ImageView;
6 | import android.widget.LinearLayout;
7 | import android.widget.TextView;
8 |
9 | import net.datafans.android.common.helper.TimeHelper;
10 | import net.datafans.android.common.widget.imageview.CommonImageView;
11 | import net.datafans.android.common.widget.table.TableViewCell;
12 | import net.datafans.android.timeline.R;
13 | import net.datafans.android.timeline.event.UserClickEvent;
14 | import net.datafans.android.timeline.item.BaseLineItem;
15 | import net.datafans.android.timeline.view.likeCmt.LikeCommentView;
16 |
17 | import de.greenrobot.event.EventBus;
18 |
19 | /**
20 | * Created by zhonganyun on 15/10/6.
21 | */
22 | public abstract class BaseLineCell extends TableViewCell {
23 |
24 |
25 | private CommonImageView userAvatarView;
26 | private TextView userNickView;
27 | private TextView titleView;
28 | private TextView locationView;
29 | private TextView timeView;
30 |
31 | protected LinearLayout contentView;
32 |
33 |
34 | private LikeCommentView likeCommentView;
35 |
36 |
37 | private ImageView albumOptView;
38 |
39 | private LinearLayout albumToolbar;
40 |
41 | private boolean isToolbarShow = false;
42 |
43 | private View toolLikeView;
44 | private View toolCommentView;
45 |
46 | private BaseLineCellDelegate delegate;
47 |
48 |
49 | private BaseLineItem item;
50 |
51 |
52 | public BaseLineCell(int layout, Context context) {
53 | super(layout, context);
54 |
55 | cell.setOnClickListener(new View.OnClickListener() {
56 | @Override
57 | public void onClick(View view) {
58 | if (delegate != null)
59 | delegate.onCellClick();
60 | }
61 | });
62 | userAvatarView = (CommonImageView) cell.findViewById(R.id.userAvatar);
63 | userAvatarView.setOnClickListener(new View.OnClickListener() {
64 | @Override
65 | public void onClick(View view) {
66 | EventBus.getDefault().post(new UserClickEvent(BaseLineCell.this.item.userId));
67 | }
68 | });
69 | userNickView = (TextView) cell.findViewById(R.id.userNick);
70 | titleView = (TextView) cell.findViewById(R.id.title);
71 |
72 | contentView = (LinearLayout) cell.findViewById(R.id.content);
73 |
74 |
75 | locationView = (TextView) cell.findViewById(R.id.location);
76 |
77 | timeView = (TextView) cell.findViewById(R.id.time);
78 |
79 |
80 | likeCommentView = (LikeCommentView) cell.findViewById(R.id.likeCmt);
81 |
82 |
83 | albumOptView = (ImageView) cell.findViewById(R.id.album_opt);
84 | albumToolbar = (LinearLayout) cell.findViewById(R.id.album_toolbar);
85 |
86 | albumOptView.setOnClickListener(new View.OnClickListener() {
87 | @Override
88 | public void onClick(View view) {
89 | swicthToolbar();
90 | if (delegate != null)
91 | delegate.onAlbumOptViewClick(BaseLineCell.this);
92 | }
93 | });
94 |
95 |
96 | toolLikeView = cell.findViewById(R.id.toolbarLike);
97 |
98 | toolLikeView.setOnClickListener(new View.OnClickListener() {
99 | @Override
100 | public void onClick(View view) {
101 | swicthToolbar();
102 | if (delegate != null) {
103 | delegate.onLikeClick(item.itemId);
104 | }
105 | }
106 | });
107 |
108 | toolCommentView = cell.findViewById(R.id.toolbarComment);
109 | toolCommentView.setOnClickListener(new View.OnClickListener() {
110 | @Override
111 | public void onClick(View view) {
112 | swicthToolbar();
113 | if (delegate != null) {
114 | delegate.onCommentClick(item.itemId);
115 | }
116 | }
117 | });
118 |
119 |
120 | }
121 |
122 |
123 | private void swicthToolbar() {
124 | if (!isToolbarShow)
125 | albumToolbar.setVisibility(View.VISIBLE);
126 | else
127 | albumToolbar.setVisibility(View.GONE);
128 |
129 | isToolbarShow = !isToolbarShow;
130 | }
131 |
132 |
133 | @Override
134 | protected void refresh(BaseLineItem item) {
135 |
136 | this.item = item;
137 |
138 |
139 | userAvatarView.loadImage(item.userAvatar);
140 | userNickView.setText(item.userNick);
141 | if (item.title == null) {
142 | titleView.setVisibility(View.GONE);
143 | } else {
144 | titleView.setVisibility(View.VISIBLE);
145 | titleView.setText(item.title);
146 | }
147 |
148 | if (item.location == null) {
149 | locationView.setVisibility(View.GONE);
150 | } else {
151 | locationView.setVisibility(View.VISIBLE);
152 | locationView.setText(item.location);
153 | }
154 |
155 | timeView.setText(TimeHelper.prettyTime(item.ts));
156 |
157 | if (item.likes.isEmpty() && item.comments.isEmpty()) {
158 | likeCommentView.setVisibility(View.GONE);
159 | } else {
160 | likeCommentView.setVisibility(View.VISIBLE);
161 | likeCommentView.updateWithItem(item);
162 | }
163 |
164 | }
165 |
166 | public void setDelegate(BaseLineCellDelegate delegate) {
167 | this.delegate = delegate;
168 | }
169 |
170 |
171 | public void hideAlbumOptView() {
172 | if (!isToolbarShow) return;
173 | swicthToolbar();
174 | }
175 |
176 |
177 | public interface BaseLineCellDelegate {
178 |
179 | void onAlbumOptViewClick(BaseLineCell cell);
180 |
181 | void onLikeClick(long itemId);
182 |
183 | void onCommentClick(long itemId);
184 |
185 | void onCellClick();
186 | }
187 | }
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/TextImageLineCell.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.graphics.drawable.Drawable;
6 | import android.text.Html;
7 | import android.text.Spanned;
8 | import android.text.TextPaint;
9 | import android.text.style.ClickableSpan;
10 | import android.text.util.Linkify;
11 | import android.util.TypedValue;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.view.WindowManager;
15 | import android.widget.LinearLayout;
16 | import android.widget.TextView;
17 |
18 | import net.datafans.android.common.helper.DipHelper;
19 | import net.datafans.android.common.helper.LogHelper;
20 | import net.datafans.android.common.helper.ResHelper;
21 | import net.datafans.android.common.helper.face.FaceHelper;
22 | import net.datafans.android.timeline.R;
23 | import net.datafans.android.timeline.item.BaseLineItem;
24 | import net.datafans.android.timeline.item.TextImageLineItem;
25 | import net.datafans.android.timeline.view.imagegrid.ImageGridView;
26 |
27 | /**
28 | * Created by zhonganyun on 15/10/6.
29 | */
30 | public class TextImageLineCell extends BaseLineCell {
31 |
32 |
33 | private TextView textView;
34 |
35 | private ImageGridView imageGridView;
36 |
37 | public TextImageLineCell(int layout, Context context) {
38 | super(layout, context);
39 |
40 | textView = new TextView(context);
41 | textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
42 | textView.setLineSpacing(0f, 1.1f);
43 | textView.setAutoLinkMask(Linkify.ALL);
44 | textView.setLinkTextColor(context.getResources().getColor(R.color.hl));
45 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
46 | params.setMargins(0, 0, 0, DipHelper.dip2px(context, 7));
47 | contentView.addView(textView, params);
48 |
49 |
50 | WindowManager wm = (WindowManager) context
51 | .getSystemService(Context.WINDOW_SERVICE);
52 | int width = wm.getDefaultDisplay().getWidth();
53 | float scale = DipHelper.px2dip(context, width) / (float) DipHelper.px2dip(context, 1080);
54 | imageGridView = new ImageGridView(context, DipHelper.dip2px(context, scale * 240));
55 | LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
56 | contentView.addView(imageGridView, imageParams);
57 |
58 |
59 | }
60 |
61 |
62 | @Override
63 | protected void refresh(BaseLineItem item) {
64 | super.refresh(item);
65 |
66 | TextImageLineItem textImageLineItem = (TextImageLineItem) item;
67 |
68 |
69 | if (textImageLineItem == null) {
70 | textView.setVisibility(View.GONE);
71 | } else {
72 | textView.setVisibility(View.VISIBLE);
73 | //textView.setText(textImageLineItem.text);
74 |
75 | //替换表情标签
76 | String source = textImageLineItem.parsedText;
77 | if (source == null) {
78 | source = FaceHelper.replace(context, textImageLineItem.text);
79 | textImageLineItem.parsedText = source;
80 | }
81 |
82 |
83 | Spanned spanned = Html.fromHtml(source, imageGetter, null);
84 | textView.setText(spanned);
85 |
86 |
87 | }
88 |
89 | if (textImageLineItem != null)
90 | imageGridView.updateWithImage(textImageLineItem.thumbImages);
91 |
92 | }
93 |
94 |
95 | private class ClickSpan extends ClickableSpan {
96 |
97 | private String value;
98 |
99 | public ClickSpan(String value) {
100 | this.value = value;
101 | }
102 |
103 | @Override
104 | public void onClick(View v) {
105 |
106 | LogHelper.debug("" + value);
107 | }
108 |
109 | @Override
110 | public void updateDrawState(TextPaint ds) {
111 | ds.setColor(Color.RED);
112 | ds.setUnderlineText(false);
113 | }
114 | }
115 |
116 |
117 | private Html.ImageGetter imageGetter = new Html.ImageGetter() {
118 | @Override
119 | public Drawable getDrawable(String source) {
120 | int resId = ResHelper.getMipmapResId(source);
121 | Drawable d = context.getResources().getDrawable(resId);
122 | if (d != null)
123 | d.setBounds(0, 0, (int) (d.getIntrinsicWidth() * 1.5), (int) (d.getIntrinsicHeight() * 1.5));
124 | return d;
125 | }
126 | };
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/commentInput/CommentInputView.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.commentInput;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.view.inputmethod.InputMethodManager;
8 | import android.widget.Button;
9 | import android.widget.EditText;
10 | import android.widget.FrameLayout;
11 | import android.widget.RelativeLayout;
12 |
13 | import net.datafans.android.timeline.R;
14 |
15 | import java.util.Map;
16 |
17 | /**
18 | * Created by zhonganyun on 15/10/12.
19 | */
20 | public class CommentInputView extends FrameLayout {
21 |
22 | private Context context;
23 |
24 | private EditText editText;
25 | private Button sendButton;
26 | private View mask;
27 |
28 | private long commentId;
29 |
30 | private Delegate delegate;
31 |
32 | public CommentInputView(Context context) {
33 | super(context);
34 | this.context = context;
35 | initView();
36 | }
37 |
38 |
39 | private void initView() {
40 | View inputView = LayoutInflater.from(context).inflate(R.layout.comment_input, null);
41 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
42 | addView(inputView, params);
43 |
44 | mask = inputView.findViewById(R.id.mask);
45 | editText = (EditText) inputView.findViewById(R.id.input);
46 | sendButton = (Button) inputView.findViewById(R.id.sendButton);
47 |
48 |
49 | mask.setOnClickListener(new OnClickListener() {
50 | @Override
51 | public void onClick(View view) {
52 | hide();
53 | }
54 | });
55 |
56 | sendButton.setOnClickListener(new OnClickListener() {
57 | @Override
58 | public void onClick(View view) {
59 | hide();
60 | if (delegate == null) return;
61 |
62 | String text = editText.getText().toString();
63 |
64 | editText.setText("");
65 |
66 | if (text.equals("")) return;
67 |
68 | delegate.onCommentCreate(commentId, text);
69 | }
70 | });
71 |
72 | }
73 |
74 | public void show() {
75 | setVisibility(VISIBLE);
76 | editText.requestFocus();
77 | InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
78 | inputManager.showSoftInput(editText, 0);
79 |
80 | }
81 |
82 |
83 | public void hide() {
84 | setVisibility(GONE);
85 | setPlaceHolder("");
86 | InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
87 | inputManager.hideSoftInputFromWindow(editText.getWindowToken(), 0);
88 | }
89 |
90 |
91 | public void setPlaceHolder(String text){
92 | editText.setHint(text);
93 | }
94 |
95 |
96 |
97 | public void setDelegate(Delegate delegate) {
98 | this.delegate = delegate;
99 | }
100 |
101 | public void setCommentId(long commentId) {
102 | this.commentId = commentId;
103 | }
104 |
105 |
106 | public static interface Delegate {
107 |
108 | void onCommentCreate(long commentId, String text);
109 | }
110 |
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/imagegrid/ImageGridView.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.imagegrid;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.FrameLayout;
10 |
11 | import com.loopj.android.image.SmartImageView;
12 |
13 | import net.datafans.android.common.widget.imageview.CommonImageView;
14 | import net.datafans.android.timeline.R;
15 |
16 | import java.lang.reflect.Field;
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | /**
21 | * Created by zhonganyun on 15/10/6.
22 | */
23 | public class ImageGridView extends FrameLayout {
24 |
25 | private int maxWidth;
26 |
27 | private Context context;
28 |
29 |
30 | private List imageViews = new ArrayList<>();
31 |
32 | private SmartImageView imageViewOne;
33 |
34 | public ImageGridView(Context context, int maxWidth) {
35 | super(context);
36 |
37 | this.context = context;
38 |
39 | this.maxWidth = maxWidth;
40 |
41 | initView();
42 | }
43 |
44 | public ImageGridView(Context context, AttributeSet attrs) {
45 | super(context, attrs);
46 | }
47 |
48 | private void initView() {
49 |
50 | View view = LayoutInflater.from(context).inflate(R.layout.nine_image_grid, null);
51 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
52 | addView(view, params);
53 |
54 | for (int i = 0; i < 9; i++) {
55 |
56 | int id = getId("image_" + i);
57 | if (id != 0) {
58 | CommonImageView imageView = (CommonImageView) view.findViewById(id);
59 | imageView.setMinimumHeight((maxWidth - 6) / 3);
60 | imageView.setMinimumWidth((maxWidth - 6) / 3);
61 | imageViews.add(imageView);
62 | }
63 | }
64 |
65 |
66 | imageViewOne = (SmartImageView) view.findViewById(R.id.image_one);
67 |
68 |
69 | }
70 |
71 | public void updateWithImage(List images) {
72 |
73 | if (images.size() == 1) {
74 | imageViewOne.setVisibility(VISIBLE);
75 | imageViewOne.setImageUrl(images.get(0));
76 | } else {
77 | imageViewOne.setVisibility(GONE);
78 | }
79 |
80 |
81 | for (int i = 0; i < imageViews.size(); i++) {
82 | CommonImageView imageView = imageViews.get(i);
83 |
84 | if (images.size() == 1) {
85 | imageView.setVisibility(GONE);
86 | } else {
87 | if (images.size() == 4) {
88 | if (i == 0 || i == 1) {
89 | imageView.setVisibility(VISIBLE);
90 | imageView.loadImage(images.get(i));
91 | } else if (i == 3 || i == 4) {
92 | imageView.setVisibility(VISIBLE);
93 | imageView.loadImage(images.get(i - 1));
94 | } else {
95 | imageView.setVisibility(GONE);
96 | }
97 | } else {
98 | if (i < images.size()) {
99 | imageView.setVisibility(VISIBLE);
100 | imageView.loadImage(images.get(i));
101 | } else {
102 | imageView.setVisibility(GONE);
103 | }
104 | }
105 | }
106 | }
107 |
108 | }
109 |
110 | private int getId(String name) {
111 | try {
112 |
113 | Field field = R.id.class.getField(name);
114 |
115 | return field.getInt(new R.drawable());
116 |
117 | } catch (Exception e) {
118 | return 0;
119 | }
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/likeCmt/LikeCommentView.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.likeCmt;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.FrameLayout;
9 | import android.widget.LinearLayout;
10 | import android.widget.TextView;
11 |
12 | import net.datafans.android.common.helper.DipHelper;
13 | import net.datafans.android.timeline.R;
14 | import net.datafans.android.timeline.item.BaseLineItem;
15 | import net.datafans.android.timeline.item.LineCommentItem;
16 | import net.datafans.android.timeline.item.LineLikeItem;
17 | import net.datafans.android.timeline.view.span.LinkTouchMovementMethod;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * Created by zhonganyun on 15/10/7.
24 | */
25 | public class LikeCommentView extends FrameLayout {
26 |
27 |
28 | private Context context;
29 |
30 | private TextView likeView;
31 |
32 | private View likeLayout;
33 |
34 | private View dividerView;
35 |
36 | private LinearLayout commentLayout;
37 |
38 | private List commentViews = new ArrayList<>();
39 |
40 | public LikeCommentView(Context context) {
41 | super(context);
42 | this.context = context;
43 | initView();
44 | }
45 |
46 | public LikeCommentView(Context context, AttributeSet attrs) {
47 | super(context, attrs);
48 |
49 | this.context = context;
50 |
51 | initView();
52 | }
53 |
54 |
55 | private void initView() {
56 |
57 | View view = LayoutInflater.from(context).inflate(R.layout.like_comment, null);
58 | addView(view);
59 |
60 | likeView = (TextView) view.findViewById(R.id.likes);
61 | likeView.setMovementMethod(new LinkTouchMovementMethod());
62 | likeView.setClickable(false);
63 | likeView.setLinksClickable(true);
64 |
65 | likeLayout = view.findViewById(R.id.likeLayout);
66 |
67 |
68 | dividerView = view.findViewById(R.id.divider);
69 |
70 | commentLayout = (LinearLayout) view.findViewById(R.id.commentLayout);
71 |
72 | }
73 |
74 | public void updateWithItem(BaseLineItem item) {
75 |
76 |
77 | List likes = item.likes;
78 | List comments = item.comments;
79 |
80 | if (likes.isEmpty()) {
81 | likeLayout.setVisibility(GONE);
82 | dividerView.setVisibility(GONE);
83 | } else {
84 | likeLayout.setVisibility(VISIBLE);
85 |
86 | if (comments.isEmpty()) {
87 | dividerView.setVisibility(GONE);
88 | } else {
89 | dividerView.setVisibility(VISIBLE);
90 | }
91 |
92 |
93 | if (item.likeSpanStr != null)
94 | likeView.setText(item.likeSpanStr);
95 | }
96 |
97 | if (comments.isEmpty()) {
98 |
99 | commentLayout.setVisibility(GONE);
100 |
101 |
102 | for (TextView textView : commentViews) {
103 | textView.setText("");
104 | textView.setVisibility(GONE);
105 | }
106 | } else {
107 |
108 | commentLayout.setVisibility(VISIBLE);
109 |
110 |
111 | int textViewCount = commentViews.size();
112 | for (int i=0; i 0 && i < textViewCount) {
127 | textView = commentViews.get(i);
128 | }else{
129 |
130 | textView = new TextView(context);
131 | textView.setMovementMethod(new LinkTouchMovementMethod());
132 | textView.setClickable(false);
133 | textView.setLinksClickable(true);
134 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
135 | params.setMargins(0,0,0, DipHelper.dip2px(context,2));
136 | commentLayout.addView(textView, params);
137 | commentViews.add(textView);
138 | }
139 |
140 |
141 | LineCommentItem commentItem = item.comments.get(i);
142 |
143 | LinkTouchMovementMethod method = (LinkTouchMovementMethod) textView.getMovementMethod();
144 | method.setUniqueId(commentItem.commentId);
145 | method.setItemId(item.itemId);
146 |
147 | textView.setVisibility(VISIBLE);
148 | textView.setText(item.commentSpanStrs.get(i));
149 | }
150 |
151 | }
152 | }
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/span/LinkTouchMovementMethod.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.span;
2 |
3 | import android.text.Layout;
4 | import android.text.Selection;
5 | import android.text.Spannable;
6 | import android.text.method.LinkMovementMethod;
7 | import android.view.MotionEvent;
8 | import android.widget.TextView;
9 |
10 | import net.datafans.android.common.helper.LogHelper;
11 | import net.datafans.android.timeline.event.CommentClickEvent;
12 |
13 | import de.greenrobot.event.EventBus;
14 |
15 | /**
16 | * Created by zhonganyun on 15/10/12.
17 | */
18 | public class LinkTouchMovementMethod extends LinkMovementMethod {
19 |
20 | private TouchSpan mPressedSpan;
21 |
22 | private long uniqueId;
23 | private long itemId;
24 |
25 | @Override
26 | public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) {
27 | if (event.getAction() == MotionEvent.ACTION_DOWN) {
28 | mPressedSpan = getPressedSpan(textView, spannable, event);
29 | if (mPressedSpan != null) {
30 | mPressedSpan.setPressed(true);
31 | Selection.setSelection(spannable, spannable.getSpanStart(mPressedSpan),
32 | spannable.getSpanEnd(mPressedSpan));
33 | }
34 | } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
35 | TouchSpan touchedSpan = getPressedSpan(textView, spannable, event);
36 | if (mPressedSpan != null && touchedSpan != mPressedSpan) {
37 | mPressedSpan.setPressed(false);
38 | mPressedSpan = null;
39 | Selection.removeSelection(spannable);
40 | }
41 | } else {
42 | if (mPressedSpan != null) {
43 | mPressedSpan.setPressed(false);
44 | super.onTouchEvent(textView, spannable, event);
45 | }else{
46 | if (event.getAction() == MotionEvent.ACTION_UP) {
47 | LogHelper.debug("点击了label其它地方: " + uniqueId);
48 | CommentClickEvent commentClickEvent = new CommentClickEvent();
49 | commentClickEvent.uniqueId = uniqueId;
50 | commentClickEvent.itemId = itemId;
51 | EventBus.getDefault().post(commentClickEvent);
52 | }
53 | }
54 | mPressedSpan = null;
55 | Selection.removeSelection(spannable);
56 | }
57 | return true;
58 | }
59 |
60 | TouchSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent event) {
61 |
62 | int x = (int) event.getX();
63 | int y = (int) event.getY();
64 |
65 | x -= textView.getTotalPaddingLeft();
66 | y -= textView.getTotalPaddingTop();
67 |
68 | x += textView.getScrollX();
69 | y += textView.getScrollY();
70 |
71 | Layout layout = textView.getLayout();
72 | int line = layout.getLineForVertical(y);
73 | int off = layout.getOffsetForHorizontal(line, x);
74 |
75 | TouchSpan[] link = spannable.getSpans(off, off, TouchSpan.class);
76 | TouchSpan touchedSpan = null;
77 | if (link.length > 0) {
78 | touchedSpan = link[0];
79 | }
80 | return touchedSpan;
81 | }
82 |
83 | public void setUniqueId(long uniqueId) {
84 | this.uniqueId = uniqueId;
85 | }
86 |
87 | public void setItemId(long itemId) {
88 | this.itemId = itemId;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/span/TouchSpan.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.span;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.text.TextPaint;
6 | import android.text.style.ClickableSpan;
7 | import android.view.View;
8 |
9 | import net.datafans.android.common.helper.LogHelper;
10 | import net.datafans.android.timeline.R;
11 | import net.datafans.android.timeline.event.UserClickEvent;
12 |
13 | import de.greenrobot.event.EventBus;
14 |
15 | /**
16 | * Created by zhonganyun on 15/10/12.
17 | */
18 | public class TouchSpan extends ClickableSpan {
19 |
20 | private boolean mIsPressed;
21 | private int mPressedBackgroundColor;
22 | private int mNormalTextColor;
23 | private int mPressedTextColor;
24 |
25 |
26 | private int userId;
27 |
28 | public TouchSpan(Context context, int userId){
29 | this.userId = userId;
30 | mNormalTextColor = context.getResources().getColor(R.color.hl);
31 | mPressedTextColor = mNormalTextColor;
32 | mPressedBackgroundColor = Color.LTGRAY;
33 |
34 | }
35 |
36 | public TouchSpan(int normalTextColor, int pressedTextColor, int pressedBackgroundColor) {
37 | mNormalTextColor = normalTextColor;
38 | mPressedTextColor = pressedTextColor;
39 | mPressedBackgroundColor = pressedBackgroundColor;
40 | }
41 |
42 | public void setPressed(boolean isSelected) {
43 | mIsPressed = isSelected;
44 | }
45 |
46 | @Override
47 | public void updateDrawState(TextPaint ds) {
48 | super.updateDrawState(ds);
49 | ds.setColor(mIsPressed ? mPressedTextColor : mNormalTextColor);
50 | ds.bgColor = mIsPressed ? mPressedBackgroundColor : 0x00eeeeee;
51 | ds.setUnderlineText(false);
52 | }
53 |
54 | @Override
55 | public void onClick(View widget) {
56 | LogHelper.debug("" + userId);
57 | EventBus.getDefault().post(new UserClickEvent(userId));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/user/BaseUserLineCell.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.user;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.widget.LinearLayout;
6 | import android.widget.TextView;
7 |
8 | import net.datafans.android.common.widget.table.TableViewCell;
9 | import net.datafans.android.timeline.R;
10 | import net.datafans.android.timeline.item.user.BaseUserLineItem;
11 |
12 | /**
13 | * Created by zhonganyun on 15/10/17.
14 | */
15 | public class BaseUserLineCell extends TableViewCell {
16 |
17 |
18 | private View topSpace;
19 | private TextView timeDayView;
20 | private TextView timeMonthView;
21 | protected LinearLayout contentView;
22 |
23 |
24 | private Delegate delegate;
25 |
26 | private BaseUserLineItem item;
27 |
28 |
29 | public BaseUserLineCell(int layout, Context context) {
30 | super(layout, context);
31 |
32 | topSpace = cell.findViewById(R.id.topSpace);
33 |
34 | timeDayView = (TextView) cell.findViewById(R.id.timeDay);
35 |
36 | timeMonthView = (TextView) cell.findViewById(R.id.timeMonth);
37 |
38 | contentView = (LinearLayout) cell.findViewById(R.id.content);
39 | contentView.setOnClickListener(new View.OnClickListener() {
40 | @Override
41 | public void onClick(View view) {
42 | if (delegate == null) return;
43 | delegate.onClickItem(item);
44 | }
45 | });
46 |
47 |
48 | }
49 |
50 | @Override
51 | protected void refresh(BaseUserLineItem item) {
52 |
53 | this.item = item;
54 |
55 | if (item.isShowTime) {
56 | topSpace.setVisibility(View.VISIBLE);
57 | if (item.day < 10) {
58 | timeDayView.setText(String.format("0%d", item.day));
59 | } else {
60 | timeDayView.setText(String.valueOf(item.day));
61 | }
62 |
63 | timeMonthView.setText(String.format("%d月", item.month));
64 | } else {
65 | topSpace.setVisibility(View.GONE);
66 |
67 | timeDayView.setText("");
68 | timeMonthView.setText("");
69 | }
70 | }
71 |
72 | public void setDelegate(Delegate delegate) {
73 | this.delegate = delegate;
74 | }
75 |
76 |
77 | public interface Delegate {
78 | void onClickItem(BaseUserLineItem item);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/java/net/datafans/android/timeline/view/user/TextImageUserLineCell.java:
--------------------------------------------------------------------------------
1 | package net.datafans.android.timeline.view.user;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.TextView;
8 |
9 | import net.datafans.android.common.widget.imageview.CommonImageView;
10 | import net.datafans.android.timeline.R;
11 | import net.datafans.android.timeline.item.user.BaseUserLineItem;
12 | import net.datafans.android.timeline.item.user.TextImageUserLineItem;
13 |
14 | /**
15 | * Created by zhonganyun on 15/10/17.
16 | */
17 | public class TextImageUserLineCell extends BaseUserLineCell {
18 |
19 |
20 | private CommonImageView coverView;
21 |
22 | private TextView textView;
23 |
24 | private TextView photoCountView;
25 |
26 | public TextImageUserLineCell(int layout, Context context) {
27 | super(layout, context);
28 |
29 | View view = LayoutInflater.from(context).inflate(R.layout.user_text_image_cell, null);
30 | contentView.addView(view);
31 |
32 | coverView = (CommonImageView) view.findViewById(R.id.cover);
33 |
34 | textView = (TextView) view.findViewById(R.id.text);
35 |
36 | photoCountView = (TextView) view.findViewById(R.id.photoCount);
37 | }
38 |
39 |
40 | @Override
41 | protected void refresh(BaseUserLineItem item) {
42 | super.refresh(item);
43 | TextImageUserLineItem textImageUserLineItem = null;
44 |
45 | if (item instanceof TextImageUserLineItem) {
46 | textImageUserLineItem = (TextImageUserLineItem) item;
47 | }
48 |
49 | if (textImageUserLineItem == null) return;
50 |
51 | if (textImageUserLineItem.cover == null){
52 | coverView.setVisibility(View.GONE);
53 | photoCountView.setVisibility(View.GONE);
54 |
55 | textView.setMaxLines(4);
56 |
57 | contentView.setBackgroundColor(Color.rgb(240,240,240));
58 | }else{
59 | coverView.loadImage(textImageUserLineItem.cover);
60 | coverView.setVisibility(View.VISIBLE);
61 | photoCountView.setVisibility(View.VISIBLE);
62 | if (textImageUserLineItem.photoCount > 1){
63 | photoCountView.setText(String.format("共%d张",textImageUserLineItem.photoCount));
64 | }else{
65 | photoCountView.setText("");
66 | }
67 |
68 | textView.setMaxLines(3);
69 | contentView.setBackgroundColor(Color.TRANSPARENT);
70 |
71 | }
72 |
73 | textView.setText(textImageUserLineItem.text);
74 |
75 | }
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable-hdpi/like_cmt_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/drawable-hdpi/like_cmt_bg.9.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable-mdpi/like_cmt_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/drawable-mdpi/like_cmt_bg.9.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable-xhdpi/like_cmt_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/drawable-xhdpi/like_cmt_bg.9.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable-xxhdpi/like_cmt_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/drawable-xxhdpi/like_cmt_bg.9.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable/comment_edit_text_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
12 |
13 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable/comment_send_btn_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
12 |
13 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/drawable/header_avatar_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/base_cell.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
13 |
14 |
19 |
20 |
25 |
26 |
31 |
32 |
39 |
40 |
47 |
48 |
49 |
50 |
51 |
58 |
59 |
60 |
61 |
62 |
66 |
67 |
68 |
72 |
73 |
79 |
80 |
81 |
88 |
89 |
97 |
98 |
103 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
119 |
120 |
121 |
122 |
133 |
134 |
140 |
146 |
153 |
154 |
155 |
159 |
160 |
166 |
167 |
173 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/base_user_cell.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
18 |
19 |
22 |
23 |
31 |
32 |
42 |
43 |
44 |
45 |
46 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/comment_input.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
10 |
11 |
18 |
19 |
28 |
29 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/header.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
21 |
22 |
27 |
28 |
29 |
38 |
39 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/like_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
23 |
24 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/nine_image_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
19 |
26 |
27 |
28 |
35 |
36 |
37 |
44 |
45 |
46 |
47 |
53 |
54 |
55 |
62 |
63 |
64 |
71 |
72 |
73 |
80 |
81 |
82 |
83 |
89 |
90 |
91 |
98 |
99 |
100 |
107 |
108 |
109 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/layout/user_text_image_cell.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
19 |
20 |
30 |
31 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/album_like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/album_like.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/album_operation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/album_operation.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/toolbar_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/toolbar_comment.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/toolbar_like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/android-timeline-view-lib/src/main/res/mipmap-xxhdpi/toolbar_like.png
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #4f6591
5 | #25255b
6 |
7 |
--------------------------------------------------------------------------------
/android-timeline-view-lib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AndroidTimelineView
3 |
4 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
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 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | applicationId "net.datafans.androidtimelineview"
9 | minSdkVersion 14
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile project(':android-timeline-view-lib')
24 | }
25 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/zhonganyun/Documents/Java/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/net/datafans/androidtimelineview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package net.datafans.androidtimelineview;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | import net.datafans.android.common.helper.LogHelper;
7 | import net.datafans.android.timeline.controller.TimelineViewController;
8 | import net.datafans.android.timeline.item.LineCommentItem;
9 | import net.datafans.android.timeline.item.LineItemType;
10 | import net.datafans.android.timeline.item.LineLikeItem;
11 | import net.datafans.android.timeline.item.TextImageLineItem;
12 |
13 | public class MainActivity extends TimelineViewController {
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 |
18 | addItems();
19 |
20 | super.onCreate(savedInstanceState);
21 |
22 | LogHelper.init("## timeline ##", true);
23 |
24 | setHeader();
25 |
26 | }
27 |
28 | @Override
29 | protected String getNavTitle() {
30 | return "朋友圈";
31 | }
32 |
33 |
34 | private void setHeader() {
35 | String coverUrl = String.format("http://file-cdn.datafans.net/temp/12.jpg_%dx%d.jpeg", coverWidth, coverHeight);
36 | setCover(coverUrl);
37 |
38 |
39 | String userAvatarUrl = String.format("http://file-cdn.datafans.net/avatar/1.jpeg_%dx%d.jpeg", userAvatarSize, userAvatarSize);
40 | setUserAvatar(userAvatarUrl);
41 |
42 |
43 | setUserNick("Allen");
44 |
45 | setUserSign("梦想还是要有的 万一实现了呢");
46 |
47 | setUserId(123456);
48 | }
49 |
50 |
51 | private TextImageLineItem textImageItem3;
52 |
53 | private void addItems() {
54 |
55 |
56 | TextImageLineItem textImageItem = new TextImageLineItem();
57 |
58 | textImageItem.itemId = 1;
59 | textImageItem.itemType = LineItemType.TextImage;
60 | textImageItem.userId = 10086;
61 | textImageItem.userAvatar = "http://file-cdn.datafans.net/avatar/1.jpeg";
62 | textImageItem.userNick = "Allen";
63 | textImageItem.title = "";
64 | textImageItem.text = "你是我的小苹果 小苹果 我爱你 就像老鼠爱大米 18680551720 [亲亲]";
65 |
66 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/11.jpg");
67 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/12.jpg");
68 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/13.jpg");
69 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/14.jpg");
70 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/15.jpg");
71 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/16.jpg");
72 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/17.jpg");
73 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/18.jpg");
74 | textImageItem.srcImages.add("http://file-cdn.datafans.net/temp/19.jpg");
75 |
76 |
77 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/11.jpg_160x160.jpeg");
78 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/12.jpg_160x160.jpeg");
79 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/13.jpg_160x160.jpeg");
80 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/14.jpg_160x160.jpeg");
81 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/15.jpg_160x160.jpeg");
82 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/16.jpg_160x160.jpeg");
83 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/17.jpg_160x160.jpeg");
84 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/18.jpg_160x160.jpeg");
85 | textImageItem.thumbImages.add("http://file-cdn.datafans.net/temp/19.jpg_160x160.jpeg");
86 |
87 | textImageItem.location = "中国 • 广州";
88 | textImageItem.ts = System.currentTimeMillis() - 10 * 60 * 1000;
89 |
90 |
91 | LineLikeItem likeItem1_1 = new LineLikeItem();
92 | likeItem1_1.userId = 10086;
93 | likeItem1_1.userNick = "Allen";
94 | textImageItem.likes.add(likeItem1_1);
95 |
96 |
97 | LineLikeItem likeItem1_2 = new LineLikeItem();
98 | likeItem1_2.userId = 10088;
99 | likeItem1_2.userNick = "奥巴马";
100 | textImageItem.likes.add(likeItem1_2);
101 |
102 |
103 | LineCommentItem commentItem1_1 = new LineCommentItem();
104 | commentItem1_1.commentId = 1000;
105 | commentItem1_1.userId = 10086;
106 | commentItem1_1.userNick = "习大大";
107 | commentItem1_1.text = "精彩 大家鼓掌";
108 | textImageItem.comments.add(commentItem1_1);
109 |
110 |
111 | LineCommentItem commentItem1_2 = new LineCommentItem();
112 | commentItem1_2.commentId = 100980;
113 | commentItem1_2.userId = 10088;
114 | commentItem1_2.userNick = "奥巴马";
115 | commentItem1_2.text = "欢迎来到美利坚";
116 | commentItem1_2.replyUserId = 10086;
117 | commentItem1_2.replyUserNick = "习大大";
118 | textImageItem.comments.add(commentItem1_2);
119 |
120 |
121 | LineCommentItem commentItem1_3 = new LineCommentItem();
122 | commentItem1_3.commentId = 456567;
123 | commentItem1_3.userId = 10010;
124 | commentItem1_3.userNick = "神雕侠侣";
125 | commentItem1_3.text = "呵呵";
126 | textImageItem.comments.add(commentItem1_3);
127 |
128 | addItem(textImageItem);
129 |
130 |
131 | TextImageLineItem textImageItem2 = new TextImageLineItem();
132 | textImageItem2.itemId = 2;
133 | textImageItem2.itemType = LineItemType.TextImage;
134 | textImageItem2.userId = 10088;
135 | textImageItem2.userAvatar = "http://file-cdn.datafans.net/avatar/2.jpg";
136 | textImageItem2.userNick = "奥巴马";
137 | textImageItem2.title = "发表了";
138 | textImageItem2.text = "京东JD.COM-专业的综合网上购物商城,销售超数万品牌、4020万种商品,http://jd.com 囊括家电、手机、电脑、服装、图书、母婴、个护、食品、旅游等13大品类。秉承客户为先的理念,京东所售商品为正品行货、全国联保、机打发票。@刘强东";
139 |
140 |
141 | textImageItem2.srcImages.add("http://file-cdn.datafans.net/temp/20.jpg");
142 | textImageItem2.srcImages.add("http://file-cdn.datafans.net/temp/21.jpg");
143 | textImageItem2.srcImages.add("http://file-cdn.datafans.net/temp/22.jpg");
144 | textImageItem2.srcImages.add("http://file-cdn.datafans.net/temp/23.jpg");
145 |
146 | textImageItem2.thumbImages.add("http://file-cdn.datafans.net/temp/20.jpg_160x160.jpeg");
147 | textImageItem2.thumbImages.add("http://file-cdn.datafans.net/temp/21.jpg_160x160.jpeg");
148 | textImageItem2.thumbImages.add("http://file-cdn.datafans.net/temp/22.jpg_160x160.jpeg");
149 | textImageItem2.thumbImages.add("http://file-cdn.datafans.net/temp/23.jpg_160x160.jpeg");
150 |
151 |
152 | LineLikeItem likeItem2_1 = new LineLikeItem();
153 | likeItem2_1.userId = 10086;
154 | likeItem2_1.userNick = "Allen";
155 | textImageItem2.likes.add(likeItem2_1);
156 |
157 | LineCommentItem commentItem2_1 = new LineCommentItem();
158 | commentItem2_1.commentId = 31000;
159 | commentItem2_1.userId = 10088;
160 | commentItem2_1.userNick = "奥巴马";
161 | commentItem2_1.text = "欢迎来到美利坚";
162 | commentItem2_1.replyUserId = 10086;
163 | commentItem2_1.replyUserNick = "习大大";
164 | textImageItem2.comments.add(commentItem2_1);
165 |
166 | LineCommentItem commentItem2_2 = new LineCommentItem();
167 | commentItem2_2.commentId = 166000;
168 | commentItem2_2.userId = 10010;
169 | commentItem2_2.userNick = "神雕侠侣";
170 | commentItem2_2.text = "大家好";
171 | textImageItem2.comments.add(commentItem2_2);
172 |
173 |
174 | addItem(textImageItem2);
175 |
176 |
177 | textImageItem3 = new TextImageLineItem();
178 | textImageItem3.itemId = 3;
179 | textImageItem3.itemType = LineItemType.TextImage;
180 | textImageItem3.userId = 10088;
181 | textImageItem3.userAvatar = "http://file-cdn.datafans.net/avatar/2.jpg";
182 | textImageItem3.userNick = "奥巴马";
183 | textImageItem3.title = "发表了";
184 | textImageItem3.text = "京东JD.COM-专业的综合网上购物商城";
185 |
186 | textImageItem3.srcImages.add("http://file-cdn.datafans.net/temp/21.jpg");
187 |
188 | textImageItem3.thumbImages.add("http://file-cdn.datafans.net/temp/21.jpg_480x270.jpeg");
189 |
190 |
191 | textImageItem3.width = 640;
192 | textImageItem3.height = 360;
193 |
194 | textImageItem3.location = "广州信息港";
195 |
196 | addItem(textImageItem3);
197 | }
198 |
199 |
200 | @Override
201 | public void onRefresh() {
202 | super.onRefresh();
203 |
204 | onEnd();
205 |
206 | }
207 |
208 |
209 | @Override
210 | public void onLoadMore() {
211 | super.onLoadMore();
212 |
213 |
214 | addItem(textImageItem3);
215 |
216 | onEnd();
217 |
218 | }
219 |
220 | @Override
221 | protected void onCommentCreate(long itemId, long commentId, String text) {
222 |
223 | LineCommentItem commentItem = new LineCommentItem();
224 | commentItem.commentId = System.currentTimeMillis();
225 | commentItem.userId = 10014;
226 | commentItem.userNick = "金三胖";
227 | commentItem.text = text;
228 | addCommentItem(commentItem, itemId, commentId);
229 | }
230 |
231 | @Override
232 | protected void onLikeCreate(long itemId) {
233 | LineLikeItem likeItem = new LineLikeItem();
234 | likeItem.userId = 1001188;
235 | likeItem.userNick = "酸菜鱼";
236 | addLikeItem(likeItem, itemId);
237 | }
238 |
239 |
240 | @Override
241 | protected void onUserClick(int userId) {
242 | LogHelper.debug("user-click: " + userId);
243 |
244 | Intent intent = new Intent(this, UserFeedActivity.class);
245 | startActivity(intent);
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/app/src/main/java/net/datafans/androidtimelineview/UserFeedActivity.java:
--------------------------------------------------------------------------------
1 | package net.datafans.androidtimelineview;
2 |
3 | import android.os.Bundle;
4 |
5 | import net.datafans.android.timeline.controller.UserTimelineViewController;
6 | import net.datafans.android.timeline.item.user.BaseUserLineItem;
7 | import net.datafans.android.timeline.item.user.TextImageUserLineItem;
8 |
9 | public class UserFeedActivity extends UserTimelineViewController {
10 |
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 |
14 | addItems();
15 | super.onCreate(savedInstanceState);
16 |
17 |
18 | setHeader();
19 | }
20 |
21 | @Override
22 | protected String getNavTitle() {
23 | return "Allen的相册";
24 | }
25 |
26 |
27 | private void setHeader() {
28 | String coverUrl = String.format("http://file-cdn.datafans.net/temp/12.jpg_%dx%d.jpeg", coverWidth, coverHeight);
29 | setCover(coverUrl);
30 |
31 |
32 | String userAvatarUrl = String.format("http://file-cdn.datafans.net/avatar/1.jpeg_%dx%d.jpeg", userAvatarSize, userAvatarSize);
33 | setUserAvatar(userAvatarUrl);
34 |
35 |
36 | setUserNick("Allen");
37 |
38 | setUserSign("梦想还是要有的 万一实现了呢");
39 |
40 | setUserId(123456);
41 | }
42 |
43 |
44 |
45 | private void addItems() {
46 |
47 | TextImageUserLineItem item = new TextImageUserLineItem();
48 | item.itemId = 1111;
49 | item.ts = 1444902955586L;
50 | item.cover = "http://file-cdn.datafans.net/temp/11.jpg_200x200.jpeg";
51 | item.photoCount = 5;
52 | item.text = "我说你二你就二";
53 | addItem(item);
54 |
55 |
56 | TextImageUserLineItem item2 = new TextImageUserLineItem();
57 | item2.itemId = 11222;
58 | item2.ts = 1444902951586L;
59 | item2.text = "阿里巴巴(1688.com)是全球企业间电子商务的著名品牌,为数千万网商提供海量商机信息和便捷安全的在线交易市场,也是商人们以商会友、真实互动的社区平台 ...";
60 |
61 | addItem(item2);
62 |
63 |
64 | TextImageUserLineItem item3 = new TextImageUserLineItem();
65 | item3.itemId = 22221111;
66 | item3.ts = 1444102855586L;
67 | item3.cover = "http://file-cdn.datafans.net/temp/15.jpg_200x200.jpeg";
68 | item3.photoCount = 8;
69 | addItem(item3);
70 |
71 |
72 | TextImageUserLineItem item4 = new TextImageUserLineItem();
73 | item4.itemId = 7771111;
74 | item4.ts = 1442912955586L;
75 | item4.cover = "http://file-cdn.datafans.net/temp/19.jpg_200x200.jpeg";
76 | item4.photoCount = 6;
77 | addItem(item4);
78 |
79 |
80 | TextImageUserLineItem item5 = new TextImageUserLineItem();
81 | item5.itemId = 9991111;
82 | item5.ts = 1442912945586L;
83 | item5.cover = "http://file-cdn.datafans.net/temp/14.jpg_200x200.jpeg";
84 | item5.photoCount = 2;
85 | item5.text = "京东JD.COM-专业的综合网上购物商城,销售超数万品牌、4020万种商品,http://jd.com 囊括家电、手机、电脑、服装、图书、母婴、个护、食品、旅游等13大品类。秉承客户为先的理念,京东所售商品为正品行货、全国联保、机打发票。@刘强东";
86 | addItem(item5);
87 |
88 |
89 | }
90 |
91 |
92 | @Override
93 | public void onRefresh() {
94 | super.onRefresh();
95 |
96 | onEnd();
97 | }
98 |
99 |
100 | @Override
101 | public void onLoadMore() {
102 | super.onLoadMore();
103 |
104 | onEnd();
105 | }
106 |
107 | @Override
108 | public void onClickItem(BaseUserLineItem item) {
109 |
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_user_feed.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_user_feed.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AndroidTimelineView
3 |
4 | Hello world!
5 | Settings
6 | UserFeedActivity
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.2.3'
9 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
10 | classpath 'com.github.dcendents:android-maven-plugin:1.2'
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | jcenter()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anyunzhong/AndroidTimelineView/1648c3764bb32058fe62a9403e81f44a161612e7/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Oct 06 16:06:58 GMT+08:00 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':android-timeline-view-lib'
2 |
--------------------------------------------------------------------------------