Commit e964d03e0d170da48d804423605ba422cba8c47c

Authored by 陶汉栋
1 parent 2f8fe45c
Exists in yxb_dev and in 1 other branch developer

no message

Showing 222 changed files with 11254 additions and 15 deletions   Show diff stats
.idea/gradle.xml
... ... @@ -10,6 +10,7 @@
10 10 <option value="$PROJECT_DIR$" />
11 11 <option value="$PROJECT_DIR$/app" />
12 12 <option value="$PROJECT_DIR$/mvpsdk" />
  13 + <option value="$PROJECT_DIR$/mychartlibrary" />
13 14 <option value="$PROJECT_DIR$/processor" />
14 15 <option value="$PROJECT_DIR$/roundedimageview-2.2.1" />
15 16 </set>
... ...
.idea/modules.xml
... ... @@ -4,6 +4,7 @@
4 4 <modules>
5 5 <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
6 6 <module fileurl="file://$PROJECT_DIR$/mvpsdk/mvpsdk.iml" filepath="$PROJECT_DIR$/mvpsdk/mvpsdk.iml" />
  7 + <module fileurl="file://$PROJECT_DIR$/mychartlibrary/mychartlibrary.iml" filepath="$PROJECT_DIR$/mychartlibrary/mychartlibrary.iml" />
7 8 <module fileurl="file://$PROJECT_DIR$/parentwork.iml" filepath="$PROJECT_DIR$/parentwork.iml" />
8 9 <module fileurl="file://$PROJECT_DIR$/processor/processor.iml" filepath="$PROJECT_DIR$/processor/processor.iml" />
9 10 <module fileurl="file://$PROJECT_DIR$/roundedimageview-2.2.1/roundedimageview-2.2.1.iml" filepath="$PROJECT_DIR$/roundedimageview-2.2.1/roundedimageview-2.2.1.iml" />
... ...
app/build.gradle
... ... @@ -81,11 +81,8 @@ greendao {
81 81 schemaVersion 1//数据库版本升级
82 82 }
83 83 dependencies {
84   -
85 84 implementation fileTree(include: ['*.jar'], dir: 'libs')
86   - implementation 'com.android.support:appcompat-v7:26.1.0'
87 85 implementation 'com.android.support.constraint:constraint-layout:1.0.2'
88   - implementation 'com.android.support:support-v4:26.1.0'
89 86 testImplementation 'junit:junit:4.12'
90 87 androidTestImplementation 'com.android.support.test:runner:1.0.1'
91 88 androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
... ... @@ -97,6 +94,19 @@ dependencies {
97 94 compile 'me.leolin:ShortcutBadger:1.1.19@aar'
98 95 annotationProcessor 'com.google.dagger:dagger-compiler:2.12'
99 96 compile files('libs/processor.jar')
100   -
101 97 compile 'com.contrarywind:Android-PickerView:4.1.3'
102   -}
103 98 \ No newline at end of file
  99 + implementation files('libs/gesture-imageview.jar')
  100 + implementation 'com.android.support:support-v4:27.1.0'
  101 + implementation project(':mychartlibrary')
  102 +}
  103 +
  104 +configurations.all {
  105 + resolutionStrategy.eachDependency { DependencyResolveDetails details ->
  106 + def requested = details.requested
  107 + if (requested.group == 'com.android.support') {
  108 + if (!requested.name.startsWith("multidex")) {
  109 + details.useVersion '26.1.0'
  110 + }
  111 + }
  112 + }
  113 +}
... ...
app/libs/gesture-imageview.jar 0 → 100644
No preview for this file type
app/libs/processor.jar
No preview for this file type
app/src/main/AndroidManifest.xml
... ... @@ -48,6 +48,7 @@
48 48 <!-- 接收 SDK 消息广播权限, 第三方 APP 接入时,请将 com.netease.nim.demo 替换为自己的包名 -->
49 49 <uses-permission android:name="com.shunzhi.parent.permission.RECEIVE_MSG" />
50 50 <uses-permission android:name="android.permission.CALL_PHONE" />
  51 + <uses-permission android:name="android.permission.RECORD_AUDIO" />
51 52  
52 53 <application
53 54 android:name=".AppContext"
... ... @@ -117,7 +118,6 @@
117 118 android:name="com.amap.api.v2.apikey"
118 119 android:value="1d130afb822d8a1019e6592cbaf10bcc" />
119 120  
120   -
121 121 <provider
122 122 android:name="android.support.v4.content.FileProvider"
123 123 android:authorities="com.shunzhi.parent.fileprovider"
... ... @@ -147,6 +147,12 @@
147 147 <!-- android:screenOrientation="portrait" -->
148 148 <!-- android:windowSoftInputMode="adjustPan|stateAlwaysHidden" /> -->
149 149 <activity
  150 + android:name=".ui.activity.chartroom.RecyclerViewChatActivity"
  151 + android:theme="@style/AppBarTheme"
  152 + android:windowSoftInputMode="adjustResize|stateHidden"
  153 + android:screenOrientation="portrait"
  154 + />
  155 + <activity
150 156 android:name=".ui.activity.MyChildActivity"
151 157 android:screenOrientation="portrait" />
152 158 <activity
... ... @@ -178,6 +184,11 @@
178 184 android:launchMode="singleInstance"
179 185 android:screenOrientation="portrait"
180 186 android:windowSoftInputMode="adjustPan|stateHidden" />
  187 +
  188 + <activity android:name=".ui.activity.chartroom.ImageViewActivity"
  189 + android:launchMode="singleInstance"
  190 + android:screenOrientation="portrait"
  191 + android:windowSoftInputMode="adjustPan|stateHidden"/>
181 192 <activity
182 193 android:name=".ui.activity.binding.CheckInfoActivity"
183 194 android:launchMode="singleInstance"
... ... @@ -212,21 +223,20 @@
212 223 android:name=".ui.activity.BankActivity"
213 224 android:launchMode="singleInstance"
214 225 android:windowSoftInputMode="adjustPan|stateAlwaysHidden" />
215   -
216 226 <activity
217 227 android:name=".ui.activity.apply.ApplyReplaceCardActivity"
218 228 android:launchMode="singleInstance"
219 229 android:windowSoftInputMode="adjustPan|stateAlwaysHidden" />
220   -
221 230 <activity
222 231 android:name=".ui.activity.apply.ApplySigninActivity"
223 232 android:launchMode="singleInstance" />
224 233  
225 234 <service
226 235 android:name=".ui.service.BadgeIntentService"
227   - android:exported="false"></service>
  236 + android:exported="false" />
228 237  
229   - <activity android:name=".ui.activity.message.MesageActivity"></activity>
  238 + <activity android:name=".ui.activity.message.MesageActivity" />
  239 + <activity android:name=".ui.activity.message.LeaverMessagesActivity"></activity>
230 240 </application>
231 241  
232 242 </manifest>
233 243 \ No newline at end of file
... ...
app/src/main/java/com/shunzhi/parent/AppContext.java
... ... @@ -5,7 +5,6 @@ import android.content.Context;
5 5 import android.content.Intent;
6 6 import android.content.SharedPreferences;
7 7 import android.text.TextUtils;
8   -import android.util.Log;
9 8  
10 9 import com.amap.api.location.AMapLocation;
11 10 import com.amap.api.location.AMapLocationClient;
... ... @@ -18,6 +17,7 @@ import com.netease.nimlib.sdk.StatusBarNotificationConfig;
18 17 import com.netease.nimlib.sdk.auth.LoginInfo;
19 18 import com.share.mvpsdk.global.GlobalApplication;
20 19 import com.share.mvpsdk.helper.RetrofitCreateHelper;
  20 +import com.shunzhi.mychartlibrary.db.BaseManager;
21 21 import com.shunzhi.parent.bean.message.DaoMaster;
22 22 import com.shunzhi.parent.bean.message.DaoSession;
23 23 import com.shunzhi.parent.dbhelper.GreenDaoDatabaseOpenHelper;
... ... @@ -70,7 +70,7 @@ public class AppContext extends GlobalApplication {
70 70 NIMClient.init(this, loginInfo(), options());
71 71 if (null==AppConfig.getAppConfig(getContext()).get(AppConfig.DISTRICT))
72 72 AppConfig.getAppConfig(getContext()).set(AppConfig.DISTRICT,"越城区");
73   -
  73 + BaseManager.initOpenHelper(this);
74 74 if (inMainProcess(this)) {
75 75 //开启地图地位
76 76 initMapLocal();
... ...
app/src/main/java/com/shunzhi/parent/api/GetLeaveMessageListAPI.java 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +package com.shunzhi.parent.api;
  2 +
  3 +import com.google.gson.JsonObject;
  4 +
  5 +import io.reactivex.Observable;
  6 +import retrofit2.http.GET;
  7 +import retrofit2.http.Query;
  8 +
  9 +public interface GetLeaveMessageListAPI {
  10 +
  11 + @GET("api/XAWebCommon/GetLeaveMessageList")
  12 + Observable<JsonObject> GetLeaveMessageList(@Query("puserid") String puserid,@Query("suserid")String suserid);
  13 +
  14 +}
... ...
app/src/main/java/com/shunzhi/parent/contract/leavermessage/LeaverMessage.java 0 → 100644
... ... @@ -0,0 +1,34 @@
  1 +package com.shunzhi.parent.contract.leavermessage;
  2 +
  3 +public class LeaverMessage {
  4 +
  5 + public String id;
  6 +
  7 + public String sendUserId;
  8 +
  9 + public String receiveUserId;
  10 +
  11 + public String content;
  12 +
  13 + public String isRead;
  14 +
  15 + public String isRecall;
  16 +
  17 + public String intime;
  18 +
  19 + public String type;
  20 +
  21 + @Override
  22 + public String toString() {
  23 + return "LeaverMessage{" +
  24 + "id='" + id + '\'' +
  25 + ", sendUserId='" + sendUserId + '\'' +
  26 + ", receiveUserId='" + receiveUserId + '\'' +
  27 + ", content='" + content + '\'' +
  28 + ", isRead='" + isRead + '\'' +
  29 + ", isRecall='" + isRecall + '\'' +
  30 + ", intime='" + intime + '\'' +
  31 + ", type='" + type + '\'' +
  32 + '}';
  33 + }
  34 +}
... ...
app/src/main/java/com/shunzhi/parent/contract/leavermessage/LeaverMessageContract.java 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +package com.shunzhi.parent.contract.leavermessage;
  2 +
  3 +import com.google.gson.JsonObject;
  4 +import com.share.mvpsdk.base.BasePresenter;
  5 +import com.share.mvpsdk.base.IBaseActivity;
  6 +import com.share.mvpsdk.base.IBaseModel;
  7 +
  8 +import java.util.List;
  9 +
  10 +import io.reactivex.Observable;
  11 +
  12 +public interface LeaverMessageContract {
  13 +
  14 + public abstract class MyLeaverMessagePresenter extends BasePresenter<ILeaverMessageModel,ILeverMessageView>{
  15 +
  16 + public abstract void GetLeaveMessageList(String puserid,String suserid);
  17 +
  18 + }
  19 +
  20 + interface ILeaverMessageModel extends IBaseModel {
  21 +
  22 + Observable<JsonObject> GetLeaveMessageList(String puserid, String suserid);
  23 +
  24 + }
  25 +
  26 + interface ILeverMessageView extends IBaseActivity{
  27 +
  28 + abstract void ShowLeaverMessageList(List<LeaverMessage> leaverMessageList);
  29 +
  30 + }
  31 +}
... ...
app/src/main/java/com/shunzhi/parent/model/leavermessage/LeaverMessageModel.java 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +package com.shunzhi.parent.model.leavermessage;
  2 +
  3 +
  4 +import com.google.gson.JsonObject;
  5 +import com.share.mvpsdk.helper.RetrofitCreateHelper;
  6 +import com.share.mvpsdk.helper.RxHelper;
  7 +import com.shunzhi.parent.AppConfig;
  8 +import com.shunzhi.parent.api.GetLeaveMessageListAPI;
  9 +import com.shunzhi.parent.contract.leavermessage.LeaverMessageContract;
  10 +
  11 +import io.reactivex.Observable;
  12 +
  13 +public class LeaverMessageModel implements LeaverMessageContract.ILeaverMessageModel{
  14 +
  15 +
  16 + @Override
  17 + public Observable GetLeaveMessageList(String puserid, String suserid) {
  18 + return RetrofitCreateHelper.getInstance().createApi(GetLeaveMessageListAPI.class, AppConfig.BASE_URL)
  19 + .GetLeaveMessageList(puserid,suserid).compose(RxHelper.<JsonObject>rxSchedulerHelper());
  20 + }
  21 +
  22 + public static LeaverMessageContract.ILeaverMessageModel newInstance() {
  23 + return new LeaverMessageModel();
  24 + }
  25 +}
... ...
app/src/main/java/com/shunzhi/parent/presenter/leavermessage/LeaverMessagePresenter.java 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +package com.shunzhi.parent.presenter.leavermessage;
  2 +
  3 +import com.share.mvpsdk.base.BasePresenter;
  4 +import com.shunzhi.parent.contract.leavermessage.LeaverMessageContract;
  5 +import com.shunzhi.parent.model.leavermessage.LeaverMessageModel;
  6 +
  7 +public class LeaverMessagePresenter extends LeaverMessageContract.MyLeaverMessagePresenter{
  8 + @Override
  9 + public LeaverMessageContract.ILeaverMessageModel getModel() {
  10 + return LeaverMessageModel.newInstance();
  11 + }
  12 +
  13 + @Override
  14 + public void onStart() {
  15 +
  16 + }
  17 +
  18 + @Override
  19 + public void GetLeaveMessageList(String puserid, String suserid) {
  20 +
  21 + }
  22 +
  23 + public static BasePresenter newInstance() {
  24 + return new LeaverMessagePresenter();
  25 + }
  26 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/activity/chartroom/ImageViewActivity.java 0 → 100644
... ... @@ -0,0 +1,116 @@
  1 +package com.shunzhi.parent.ui.activity.chartroom;
  2 +
  3 +import android.content.Intent;
  4 +import android.os.Bundle;
  5 +import android.support.v4.app.Fragment;
  6 +import android.support.v4.app.FragmentActivity;
  7 +import android.support.v4.app.FragmentManager;
  8 +import android.support.v4.app.FragmentPagerAdapter;
  9 +import android.support.v4.view.ViewPager;
  10 +import android.support.v4.view.ViewPager.OnPageChangeListener;
  11 +import android.widget.TextView;
  12 +
  13 +
  14 +import com.shunzhi.parent.R;
  15 +import com.shunzhi.parent.ui.activity.chartroom.fragment.ImageViewFragment;
  16 +
  17 +import java.util.ArrayList;
  18 +import java.util.List;
  19 +
  20 +public class ImageViewActivity extends FragmentActivity {
  21 + private ArrayList<String> imageList;
  22 + private List<Fragment> fragList;
  23 + private ViewPager imageVp;
  24 + private TextView currentTv;
  25 + private TextView totalTv;
  26 + private int currentPage;
  27 +
  28 + @Override
  29 + protected void onCreate(Bundle savedInstanceState) {
  30 + super.onCreate(savedInstanceState);
  31 + Intent intent = getIntent();
  32 + Bundle bundle = intent.getExtras();
  33 + if (bundle != null) {
  34 + if (bundle.containsKey("images")) {
  35 + imageList = bundle.getStringArrayList("images");
  36 + }
  37 + if (bundle.containsKey("clickedIndex")) {
  38 + currentPage = bundle.getInt("clickedIndex");
  39 + }
  40 + }
  41 + setContentView(R.layout.activity_images_view);
  42 + findView();
  43 + init();
  44 + }
  45 +
  46 + private void init() {
  47 + totalTv.setText("/" + imageList.size());
  48 + fragList = new ArrayList<Fragment>();
  49 + for (int i = 0; i < imageList.size(); i++) {
  50 + ImageViewFragment imageVF = new ImageViewFragment();
  51 + imageVF.setImageUrl(imageList.get(i));
  52 + fragList.add(imageVF);
  53 + }
  54 + // 类似缓存
  55 + imageVp.setOffscreenPageLimit(imageList.size());
  56 + imageVp.setAdapter(new ImageViewFPAdapter(getSupportFragmentManager()));
  57 + imageVp.setOnPageChangeListener(new OnPageChangeListener() {
  58 +
  59 + @Override
  60 + public void onPageSelected(int index) {
  61 + currentPage = index;
  62 + currentTv.setText((index + 1) + "");
  63 + fragList.get(currentPage).onPause(); // 调用切换前Fargment的onPause()
  64 + if (fragList.get(index).isAdded()) {
  65 + fragList.get(index).onResume(); // 调用切换后Fargment的onResume()
  66 + }
  67 + }
  68 +
  69 + @Override
  70 + public void onPageScrolled(int arg0, float arg1, int arg2) {
  71 +
  72 + }
  73 +
  74 + @Override
  75 + public void onPageScrollStateChanged(int arg0) {
  76 +
  77 + }
  78 + });
  79 + imageVp.setCurrentItem(currentPage);
  80 + currentTv.setText((currentPage + 1) + "");
  81 + }
  82 +
  83 + protected void findView() {
  84 + imageVp = (ViewPager) findViewById(R.id.images_vp);
  85 + currentTv = (TextView) findViewById(R.id.imageView_current_tv);
  86 + totalTv = (TextView) findViewById(R.id.imageView_total_tv);
  87 + }
  88 +
  89 + class ImageViewFPAdapter extends FragmentPagerAdapter {
  90 + protected FragmentManager fm;
  91 +
  92 + public ImageViewFPAdapter(FragmentManager fm) {
  93 + super(fm);
  94 + this.fm = fm;
  95 + }
  96 +
  97 + @Override
  98 + public Fragment getItem(int arg0) {
  99 + return fragList.get(arg0);
  100 + }
  101 +
  102 + @Override
  103 + public int getCount() {
  104 + return fragList.size();
  105 + }
  106 + }
  107 +
  108 + @Override
  109 + protected void onDestroy() {
  110 + if (fragList.size() > 0) {
  111 + for (Fragment fragment : fragList)
  112 + fragment.onDestroy();
  113 + }
  114 + super.onDestroy();
  115 + }
  116 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/activity/chartroom/RecyclerViewChatActivity.java 0 → 100644
... ... @@ -0,0 +1,442 @@
  1 +package com.shunzhi.parent.ui.activity.chartroom;
  2 +
  3 +import android.graphics.Rect;
  4 +import android.os.Bundle;
  5 +import android.os.Handler;
  6 +import android.os.Message;
  7 +import android.support.v7.widget.LinearLayoutManager;
  8 +import android.support.v7.widget.RecyclerView;
  9 +import android.view.View;
  10 +import android.view.ViewTreeObserver;
  11 +
  12 +import com.shunzhi.mychartlibrary.BaseActivity;
  13 +import com.shunzhi.mychartlibrary.db.ChatMessageBean;
  14 +import com.shunzhi.parent.ui.activity.chartroom.adapter.ChatListViewAdapter;
  15 +import com.shunzhi.parent.ui.activity.chartroom.adapter.ChatRecyclerAdapter;
  16 +import com.shunzhi.mychartlibrary.animator.SlideInOutBottomItemAnimator;
  17 +import com.shunzhi.mychartlibrary.common.ChatConst;
  18 +import com.shunzhi.mychartlibrary.utils.KeyBoardUtils;
  19 +import com.shunzhi.mychartlibrary.widget.AudioRecordButton;
  20 +import com.shunzhi.mychartlibrary.widget.pulltorefresh.PullToRefreshRecyclerView;
  21 +import com.shunzhi.mychartlibrary.widget.pulltorefresh.WrapContentLinearLayoutManager;
  22 +import com.shunzhi.mychartlibrary.widget.pulltorefresh.base.PullToRefreshView;
  23 +
  24 +import java.lang.ref.WeakReference;
  25 +
  26 +public class RecyclerViewChatActivity extends BaseActivity {
  27 + private PullToRefreshRecyclerView myList;
  28 + private ChatRecyclerAdapter tbAdapter;
  29 + private SendMessageHandler sendMessageHandler;
  30 + private WrapContentLinearLayoutManager wcLinearLayoutManger;
  31 +
  32 + @Override
  33 + protected void onCreate(Bundle savedInstanceState) {
  34 + super.onCreate(savedInstanceState);
  35 + }
  36 +
  37 + @Override
  38 + protected void findView() {
  39 + super.findView();
  40 + pullList.setSlideView(new PullToRefreshView(this).getSlideView(PullToRefreshView.RECYCLERVIEW));
  41 + myList = (PullToRefreshRecyclerView) pullList.returnMylist();
  42 + }
  43 +
  44 + @Override
  45 + protected void onResume() {
  46 + // TODO Auto-generated method stub
  47 + super.onResume();
  48 + }
  49 +
  50 + @Override
  51 + protected void onDestroy() {
  52 + tblist.clear();
  53 + tbAdapter.notifyDataSetChanged();
  54 + myList.setAdapter(null);
  55 + sendMessageHandler.removeCallbacksAndMessages(null);
  56 + super.onDestroy();
  57 + }
  58 +
  59 + @Override
  60 + protected void init() {
  61 + setTitle(getIntent().getStringExtra("childName"));
  62 + tbAdapter = new ChatRecyclerAdapter(this, tblist,getIntent().getStringExtra("childPhoto"));
  63 + wcLinearLayoutManger = new WrapContentLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
  64 + myList.setLayoutManager(wcLinearLayoutManger);
  65 + myList.setItemAnimator(new SlideInOutBottomItemAnimator(myList));
  66 + myList.setAdapter(tbAdapter);
  67 + sendMessageHandler = new SendMessageHandler(this);
  68 + tbAdapter.isPicRefresh = true;
  69 + tbAdapter.notifyDataSetChanged();
  70 + tbAdapter.setSendErrorListener(new ChatRecyclerAdapter.SendErrorListener() {
  71 +
  72 + @Override
  73 + public void onClick(int position) {
  74 + // TODO Auto-generated method stub
  75 + ChatMessageBean tbub = tblist.get(position);
  76 + if (tbub.getType() == ChatRecyclerAdapter.TO_USER_VOICE) {
  77 + sendVoice(tbub.getUserVoiceTime(), tbub.getUserVoicePath());
  78 + tblist.remove(position);
  79 + } else if (tbub.getType() == ChatRecyclerAdapter.TO_USER_IMG) {
  80 + sendImage(tbub.getImageLocal());
  81 + tblist.remove(position);
  82 + }
  83 + }
  84 +
  85 + });
  86 + tbAdapter.setVoiceIsReadListener(new ChatRecyclerAdapter.VoiceIsRead() {
  87 +
  88 + @Override
  89 + public void voiceOnClick(int position) {
  90 + // TODO Auto-generated method stub
  91 + for (int i = 0; i < tbAdapter.unReadPosition.size(); i++) {
  92 + if (tbAdapter.unReadPosition.get(i).equals(position + "")) {
  93 + tbAdapter.unReadPosition.remove(i);
  94 + break;
  95 + }
  96 + }
  97 + }
  98 +
  99 + });
  100 + voiceBtn.setAudioFinishRecorderListener(new AudioRecordButton.AudioFinishRecorderListener() {
  101 +
  102 + @Override
  103 + public void onFinished(float seconds, String filePath) {
  104 + // TODO Auto-generated method stub
  105 + sendVoice(seconds, filePath);
  106 + }
  107 +
  108 + @Override
  109 + public void onStart() {
  110 + // TODO Auto-generated method stub
  111 + tbAdapter.stopPlayVoice();
  112 + }
  113 + });
  114 + myList.setOnScrollListener(new RecyclerView.OnScrollListener() {
  115 +
  116 + @Override
  117 + public void onScrollStateChanged(RecyclerView view, int scrollState) {
  118 + // TODO Auto-generated method stub
  119 + switch (scrollState) {
  120 + case RecyclerView.SCROLL_STATE_IDLE:
  121 + tbAdapter.handler.removeCallbacksAndMessages(null);
  122 + tbAdapter.setIsGif(true);
  123 + tbAdapter.isPicRefresh = false;
  124 + tbAdapter.notifyDataSetChanged();
  125 + break;
  126 + case RecyclerView.SCROLL_STATE_DRAGGING:
  127 + tbAdapter.handler.removeCallbacksAndMessages(null);
  128 + tbAdapter.setIsGif(false);
  129 + tbAdapter.isPicRefresh = true;
  130 + reset();
  131 + KeyBoardUtils.hideKeyBoard(RecyclerViewChatActivity.this,
  132 + mEditTextContent);
  133 + break;
  134 + default:
  135 + break;
  136 + }
  137 + }
  138 +
  139 + @Override
  140 + public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
  141 + super.onScrolled(recyclerView, dx, dy);
  142 + }
  143 + });
  144 + controlKeyboardLayout(activityRootView, pullList);
  145 + super.init();
  146 + }
  147 +
  148 + /**
  149 + * @param root 最外层布局
  150 + * @param needToScrollView 要滚动的布局,就是说在键盘弹出的时候,你需要试图滚动上去的View,在键盘隐藏的时候,他又会滚动到原来的位置的布局
  151 + */
  152 + private void controlKeyboardLayout(final View root, final View needToScrollView) {
  153 + root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  154 +
  155 + private Rect r = new Rect();
  156 +
  157 + @Override
  158 + public void onGlobalLayout() {
  159 + //获取当前界面可视部分
  160 + RecyclerViewChatActivity.this.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
  161 + //获取屏幕的高度
  162 + int screenHeight = RecyclerViewChatActivity.this.getWindow().getDecorView().getRootView().getHeight();
  163 + //此处就是用来获取键盘的高度的, 在键盘没有弹出的时候 此高度为0 键盘弹出的时候为一个正数
  164 + int heightDifference = screenHeight - r.bottom;
  165 + int recyclerHeight = 0;
  166 + if (wcLinearLayoutManger != null) {
  167 + recyclerHeight = wcLinearLayoutManger.getRecyclerHeight();
  168 + }
  169 + if (heightDifference == 0 || heightDifference == bottomStatusHeight) {
  170 + needToScrollView.scrollTo(0, 0);
  171 + } else {
  172 + if (heightDifference < recyclerHeight) {
  173 + int contentHeight = wcLinearLayoutManger == null ? 0 : wcLinearLayoutManger.getHeight();
  174 + if (recyclerHeight < contentHeight) {
  175 + listSlideHeight = heightDifference - (contentHeight - recyclerHeight);
  176 + needToScrollView.scrollTo(0, listSlideHeight);
  177 + } else {
  178 + listSlideHeight = heightDifference;
  179 + needToScrollView.scrollTo(0, listSlideHeight);
  180 + }
  181 + } else {
  182 + listSlideHeight = 0;
  183 + }
  184 + }
  185 + }
  186 + });
  187 + }
  188 +
  189 + @Override
  190 + protected void loadRecords() {
  191 + isDown = true;
  192 + if (pagelist != null) {
  193 + pagelist.clear();
  194 + }
  195 + pagelist = mChatDbManager.loadPages(page, number);
  196 + position = pagelist.size();
  197 + if (pagelist.size() != 0) {
  198 + pagelist.addAll(tblist);
  199 + tblist.clear();
  200 + tblist.addAll(pagelist);
  201 + if (imageList != null) {
  202 + imageList.clear();
  203 + }
  204 + if (imagePosition != null) {
  205 + imagePosition.clear();
  206 + }
  207 + int key = 0;
  208 + int position = 0;
  209 + for (ChatMessageBean cmb : tblist) {
  210 + if (cmb.getType() == ChatListViewAdapter.FROM_USER_IMG || cmb.getType() == ChatListViewAdapter.TO_USER_IMG) {
  211 + imageList.add(cmb.getImageLocal());
  212 + imagePosition.put(key, position);
  213 + position++;
  214 + }
  215 + key++;
  216 + }
  217 + tbAdapter.setImageList(imageList);
  218 + tbAdapter.setImagePosition(imagePosition);
  219 + sendMessageHandler.sendEmptyMessage(PULL_TO_REFRESH_DOWN);
  220 + if (page == 0) {
  221 + pullList.refreshComplete();
  222 + pullList.setPullGone();
  223 + } else {
  224 + page--;
  225 + }
  226 + } else {
  227 + if (page == 0) {
  228 + pullList.refreshComplete();
  229 + pullList.setPullGone();
  230 + }
  231 + }
  232 + }
  233 +
  234 + static class SendMessageHandler extends Handler {
  235 + WeakReference<RecyclerViewChatActivity> mActivity;
  236 +
  237 + SendMessageHandler(RecyclerViewChatActivity activity) {
  238 + mActivity = new WeakReference<RecyclerViewChatActivity>(activity);
  239 + }
  240 +
  241 + @Override
  242 + public void handleMessage(Message msg) {
  243 + // TODO Auto-generated method stub
  244 + RecyclerViewChatActivity theActivity = mActivity.get();
  245 + if (theActivity != null) {
  246 + switch (msg.what) {
  247 + case REFRESH:
  248 + theActivity.tbAdapter.isPicRefresh = true;
  249 + theActivity.tbAdapter.notifyDataSetChanged();
  250 + int position = theActivity.tbAdapter.getItemCount() - 1 < 0 ? 0 : theActivity.tbAdapter.getItemCount() - 1;
  251 + theActivity.myList.smoothScrollToPosition(position);
  252 + break;
  253 + case SEND_OK:
  254 + theActivity.mEditTextContent.setText("");
  255 + theActivity.tbAdapter.isPicRefresh = true;
  256 + theActivity.tbAdapter.notifyItemInserted(theActivity.tblist
  257 + .size() - 1);
  258 + theActivity.myList.smoothScrollToPosition(theActivity.tbAdapter.getItemCount() - 1);
  259 + break;
  260 + case RECERIVE_OK:
  261 + theActivity.tbAdapter.isPicRefresh = true;
  262 + theActivity.tbAdapter.notifyItemInserted(theActivity.tblist
  263 + .size() - 1);
  264 + theActivity.myList.smoothScrollToPosition(theActivity.tbAdapter.getItemCount() - 1);
  265 + break;
  266 + case PULL_TO_REFRESH_DOWN:
  267 + theActivity.pullList.refreshComplete();
  268 + theActivity.tbAdapter.notifyDataSetChanged();
  269 + theActivity.myList.smoothScrollToPosition(theActivity.position - 1);
  270 + theActivity.isDown = false;
  271 + break;
  272 + default:
  273 + break;
  274 + }
  275 + }
  276 + }
  277 +
  278 + }
  279 +
  280 + /**
  281 + * 发送文字
  282 + */
  283 + @Override
  284 + protected void sendMessage() {
  285 + new Thread(new Runnable() {
  286 + @Override
  287 + public void run() {
  288 + String content = mEditTextContent.getText().toString();
  289 + tblist.add(getTbub(userName, ChatListViewAdapter.TO_USER_MSG, content, null, null,
  290 + null, null, null, 0f, ChatConst.COMPLETED));
  291 + sendMessageHandler.sendEmptyMessage(SEND_OK);
  292 + RecyclerViewChatActivity.this.content = content;
  293 + receriveHandler.sendEmptyMessageDelayed(0, 1000);
  294 + }
  295 + }).start();
  296 + }
  297 +
  298 + /**
  299 + * 接收文字
  300 + */
  301 + String content = "";
  302 +
  303 + private void receriveMsgText(final String content) {
  304 + new Thread(new Runnable() {
  305 + @Override
  306 + public void run() {
  307 + String message = "回复:" + content;
  308 + ChatMessageBean tbub = new ChatMessageBean();
  309 + tbub.setUserName(userName);
  310 + String time = returnTime();
  311 + tbub.setUserContent(message);
  312 + tbub.setTime(time);
  313 + tbub.setType(ChatListViewAdapter.FROM_USER_MSG);
  314 + tblist.add(tbub);
  315 + sendMessageHandler.sendEmptyMessage(RECERIVE_OK);
  316 + mChatDbManager.insert(tbub);
  317 + }
  318 + }).start();
  319 + }
  320 +
  321 + /**
  322 + * 发送图片
  323 + */
  324 + int i = 0;
  325 +
  326 + @Override
  327 + protected void sendImage(final String filePath) {
  328 + new Thread(new Runnable() {
  329 + @Override
  330 + public void run() {
  331 + if (i == 0) {
  332 + tblist.add(getTbub(userName, ChatListViewAdapter.TO_USER_IMG, null, null, null, filePath, null, null,
  333 + 0f, ChatConst.SENDING));
  334 + } else if (i == 1) {
  335 + tblist.add(getTbub(userName, ChatListViewAdapter.TO_USER_IMG, null, null, null, filePath, null, null,
  336 + 0f, ChatConst.SENDERROR));
  337 + } else if (i == 2) {
  338 + tblist.add(getTbub(userName, ChatListViewAdapter.TO_USER_IMG, null, null, null, filePath, null, null,
  339 + 0f, ChatConst.COMPLETED));
  340 + i = -1;
  341 + }
  342 + imageList.add(tblist.get(tblist.size() - 1).getImageLocal());
  343 + imagePosition.put(tblist.size() - 1, imageList.size() - 1);
  344 + sendMessageHandler.sendEmptyMessage(SEND_OK);
  345 + RecyclerViewChatActivity.this.filePath = filePath;
  346 + receriveHandler.sendEmptyMessageDelayed(1, 3000);
  347 + i++;
  348 + }
  349 + }).start();
  350 + }
  351 +
  352 + /**
  353 + * 接收图片
  354 + */
  355 + String filePath = "";
  356 +
  357 + private void receriveImageText(final String filePath) {
  358 + new Thread(new Runnable() {
  359 + @Override
  360 + public void run() {
  361 + ChatMessageBean tbub = new ChatMessageBean();
  362 + tbub.setUserName(userName);
  363 + String time = returnTime();
  364 + tbub.setTime(time);
  365 + tbub.setImageLocal(filePath);
  366 + tbub.setType(ChatListViewAdapter.FROM_USER_IMG);
  367 + tblist.add(tbub);
  368 + imageList.add(tblist.get(tblist.size() - 1).getImageLocal());
  369 + imagePosition.put(tblist.size() - 1, imageList.size() - 1);
  370 + sendMessageHandler.sendEmptyMessage(RECERIVE_OK);
  371 + mChatDbManager.insert(tbub);
  372 + }
  373 + }).start();
  374 + }
  375 +
  376 + /**
  377 + * 发送语音
  378 + */
  379 + @Override
  380 + protected void sendVoice(final float seconds, final String filePath) {
  381 + new Thread(new Runnable() {
  382 + @Override
  383 + public void run() {
  384 + tblist.add(getTbub(userName, ChatListViewAdapter.TO_USER_VOICE, null, null, null, null, filePath,
  385 + null, seconds, ChatConst.SENDING));
  386 + sendMessageHandler.sendEmptyMessage(SEND_OK);
  387 + RecyclerViewChatActivity.this.seconds = seconds;
  388 + voiceFilePath = filePath;
  389 + receriveHandler.sendEmptyMessageDelayed(2, 3000);
  390 + }
  391 + }).start();
  392 + }
  393 +
  394 + /**
  395 + * 接收语音
  396 + */
  397 + float seconds = 0.0f;
  398 + String voiceFilePath = "";
  399 +
  400 + private void receriveVoiceText(final float seconds, final String filePath) {
  401 + new Thread(new Runnable() {
  402 + @Override
  403 + public void run() {
  404 + ChatMessageBean tbub = new ChatMessageBean();
  405 + tbub.setUserName(userName);
  406 + String time = returnTime();
  407 + tbub.setTime(time);
  408 + tbub.setUserVoiceTime(seconds);
  409 + tbub.setUserVoicePath(filePath);
  410 + tbAdapter.unReadPosition.add(tblist.size() + "");
  411 + tbub.setType(ChatListViewAdapter.FROM_USER_VOICE);
  412 + tblist.add(tbub);
  413 + sendMessageHandler.sendEmptyMessage(RECERIVE_OK);
  414 + mChatDbManager.insert(tbub);
  415 + }
  416 + }).start();
  417 + }
  418 +
  419 + /**
  420 + * 为了模拟接收延迟
  421 + */
  422 + private Handler receriveHandler = new Handler() {
  423 + @Override
  424 + public void handleMessage(Message msg) {
  425 + super.handleMessage(msg);
  426 + switch (msg.what) {
  427 + case 0:
  428 + receriveMsgText(content);
  429 + break;
  430 + case 1:
  431 + receriveImageText(filePath);
  432 + break;
  433 + case 2:
  434 + receriveVoiceText(seconds, voiceFilePath);
  435 + break;
  436 + default:
  437 + break;
  438 + }
  439 + }
  440 + };
  441 +
  442 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/activity/chartroom/adapter/ChatListViewAdapter.java 0 → 100644
... ... @@ -0,0 +1,826 @@
  1 +package com.shunzhi.parent.ui.activity.chartroom.adapter;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.app.Activity;
  5 +import android.content.Context;
  6 +import android.content.Intent;
  7 +import android.graphics.drawable.AnimationDrawable;
  8 +import android.media.MediaPlayer;
  9 +import android.os.Handler;
  10 +import android.os.Message;
  11 +import android.util.DisplayMetrics;
  12 +import android.view.LayoutInflater;
  13 +import android.view.View;
  14 +import android.view.ViewGroup;
  15 +import android.view.WindowManager;
  16 +import android.view.animation.Animation;
  17 +import android.view.animation.AnimationUtils;
  18 +import android.view.animation.LinearInterpolator;
  19 +import android.widget.BaseAdapter;
  20 +import android.widget.FrameLayout;
  21 +import android.widget.ImageView;
  22 +import android.widget.LinearLayout;
  23 +import android.widget.TextView;
  24 +
  25 +
  26 +import com.shunzhi.mychartlibrary.db.ChatMessageBean;
  27 +import com.shunzhi.parent.R;
  28 +import com.shunzhi.parent.ui.activity.chartroom.ImageViewActivity;
  29 +import com.shunzhi.mychartlibrary.common.ChatConst;
  30 +import com.shunzhi.mychartlibrary.utils.FileSaveUtil;
  31 +import com.shunzhi.mychartlibrary.utils.ImageCheckoutUtil;
  32 +import com.shunzhi.mychartlibrary.widget.BubbleImageView;
  33 +import com.shunzhi.mychartlibrary.widget.GifTextView;
  34 +import com.shunzhi.mychartlibrary.widget.MediaManager;
  35 +
  36 +import java.io.File;
  37 +import java.lang.ref.WeakReference;
  38 +import java.math.BigDecimal;
  39 +import java.text.DateFormat;
  40 +import java.text.SimpleDateFormat;
  41 +import java.util.ArrayList;
  42 +import java.util.HashMap;
  43 +import java.util.List;
  44 +
  45 +/**
  46 + * Created by Mao Jiqing on 2016/9/28.
  47 + */
  48 +public class ChatListViewAdapter extends BaseAdapter {
  49 + private Context context;
  50 + private List<ChatMessageBean> userList = new ArrayList<ChatMessageBean>();
  51 + private ArrayList<String> imageList = new ArrayList<String>();
  52 + private HashMap<Integer,Integer> imagePosition = new HashMap<Integer,Integer>();
  53 + public static final int FROM_USER_MSG = 0;//接收消息类型
  54 + public static final int TO_USER_MSG = 1;//发送消息类型
  55 + public static final int FROM_USER_IMG = 2;//接收消息类型
  56 + public static final int TO_USER_IMG = 3;//发送消息类型
  57 + public static final int FROM_USER_VOICE = 4;//接收消息类型
  58 + public static final int TO_USER_VOICE = 5;//发送消息类型
  59 + private int mMinItemWith;// 设置对话框的最大宽度和最小宽度
  60 + private int mMaxItemWith;
  61 + public MyHandler handler;
  62 + private Animation an;
  63 + private SendErrorListener sendErrorListener;
  64 + private VoiceIsRead voiceIsRead;
  65 + public List<String> unReadPosition = new ArrayList<String>();
  66 + private int voicePlayPosition = -1;
  67 + private LayoutInflater mLayoutInflater;
  68 + private boolean isGif = true;
  69 + public boolean isPicRefresh = true;
  70 +
  71 + public interface SendErrorListener {
  72 + public void onClick(int position);
  73 + }
  74 +
  75 + public void setSendErrorListener(SendErrorListener sendErrorListener) {
  76 + this.sendErrorListener = sendErrorListener;
  77 + }
  78 +
  79 + public interface VoiceIsRead {
  80 + public void voiceOnClick(int position);
  81 + }
  82 +
  83 + public void setVoiceIsReadListener(VoiceIsRead voiceIsRead) {
  84 + this.voiceIsRead = voiceIsRead;
  85 + }
  86 +
  87 + public ChatListViewAdapter(Context context) {
  88 + this.context = context;
  89 + mLayoutInflater = LayoutInflater.from(context);
  90 + // 获取系统宽度
  91 + WindowManager wManager = (WindowManager) context
  92 + .getSystemService(Context.WINDOW_SERVICE);
  93 + DisplayMetrics outMetrics = new DisplayMetrics();
  94 + wManager.getDefaultDisplay().getMetrics(outMetrics);
  95 + mMaxItemWith = (int) (outMetrics.widthPixels * 0.5f);
  96 + mMinItemWith = (int) (outMetrics.widthPixels * 0.15f);
  97 + handler = new MyHandler(this);
  98 + }
  99 +
  100 + public static class MyHandler extends Handler {
  101 + private final WeakReference<ChatListViewAdapter> mTbAdapter;
  102 +
  103 + public MyHandler(ChatListViewAdapter tbAdapter) {
  104 + mTbAdapter = new WeakReference<ChatListViewAdapter>(tbAdapter);
  105 + }
  106 +
  107 + @Override
  108 + public void handleMessage(Message msg) {
  109 + ChatListViewAdapter tbAdapter = mTbAdapter.get();
  110 +
  111 + if (tbAdapter != null) {
  112 + }
  113 + }
  114 + }
  115 +
  116 + public void setIsGif(boolean isGif) {
  117 + this.isGif = isGif;
  118 + }
  119 +
  120 + public void setUserList(List<ChatMessageBean> userList) {
  121 + this.userList = userList;
  122 + }
  123 +
  124 + public void setImageList(ArrayList<String> imageList) {
  125 + this.imageList = imageList;
  126 + }
  127 + public void setImagePosition(HashMap<Integer,Integer> imagePosition) {
  128 + this.imagePosition = imagePosition;
  129 + }
  130 +
  131 + @Override
  132 + public int getCount() {
  133 + return userList.size();
  134 + }
  135 +
  136 + @Override
  137 + public Object getItem(int i) {
  138 + return userList.get(i);
  139 + }
  140 +
  141 + @Override
  142 + public long getItemId(int i) {
  143 + return i;
  144 + }
  145 +
  146 + @Override
  147 + public int getItemViewType(int position) {
  148 + // TODO Auto-generated method stub
  149 + return userList.get(position).getType();
  150 + }
  151 +
  152 + @Override
  153 + public int getViewTypeCount() {
  154 + // TODO Auto-generated method stub
  155 + return 6;
  156 + }
  157 +
  158 + @SuppressLint("InflateParams")
  159 + @Override
  160 + public View getView(int i, View view, ViewGroup viewGroup) {
  161 + ChatMessageBean tbub = userList.get(i);
  162 + switch (getItemViewType(i)) {
  163 + case FROM_USER_MSG:
  164 + FromUserMsgViewHolder holder;
  165 + if (view == null) {
  166 + holder = new FromUserMsgViewHolder();
  167 + view = mLayoutInflater.inflate(R.layout.layout_msgfrom_list_item, null);
  168 + holder.headicon = (ImageView) view
  169 + .findViewById(R.id.tb_other_user_icon);
  170 + holder.chat_time = (TextView) view.findViewById(R.id.chat_time);
  171 + holder.content = (GifTextView) view.findViewById(R.id.content);
  172 + view.setTag(holder);
  173 + } else {
  174 + holder = (FromUserMsgViewHolder) view.getTag();
  175 + }
  176 + fromMsgUserLayout((FromUserMsgViewHolder) holder, tbub, i);
  177 + break;
  178 + case FROM_USER_IMG:
  179 + FromUserImageViewHolder holder1;
  180 + if (view == null) {
  181 + holder1 = new FromUserImageViewHolder();
  182 + view = mLayoutInflater.inflate(R.layout.layout_imagefrom_list_item, null);
  183 + holder1.headicon = (ImageView) view
  184 + .findViewById(R.id.tb_other_user_icon);
  185 + holder1.chat_time = (TextView) view.findViewById(R.id.chat_time);
  186 + holder1.image_Msg = (BubbleImageView) view
  187 + .findViewById(R.id.image_message);
  188 + view.setTag(holder1);
  189 + } else {
  190 + holder1 = (FromUserImageViewHolder) view.getTag();
  191 + }
  192 + fromImgUserLayout((FromUserImageViewHolder) holder1, tbub, i);
  193 + break;
  194 + case FROM_USER_VOICE:
  195 + FromUserVoiceViewHolder holder2;
  196 + if (view == null) {
  197 + holder2 = new FromUserVoiceViewHolder();
  198 + view = mLayoutInflater.inflate(R.layout.layout_voicefrom_list_item, null);
  199 + holder2.headicon = (ImageView) view
  200 + .findViewById(R.id.tb_other_user_icon);
  201 + holder2.chat_time = (TextView) view.findViewById(R.id.chat_time);
  202 + holder2.voice_group = (LinearLayout) view
  203 + .findViewById(R.id.voice_group);
  204 + holder2.voice_time = (TextView) view
  205 + .findViewById(R.id.voice_time);
  206 + holder2.receiver_voice_unread = (View) view
  207 + .findViewById(R.id.receiver_voice_unread);
  208 + holder2.voice_image = (FrameLayout) view
  209 + .findViewById(R.id.voice_receiver_image);
  210 + holder2.voice_anim = (View) view
  211 + .findViewById(R.id.id_receiver_recorder_anim);
  212 + view.setTag(holder2);
  213 + } else {
  214 + holder2 = (FromUserVoiceViewHolder) view.getTag();
  215 + }
  216 + fromVoiceUserLayout((FromUserVoiceViewHolder) holder2, tbub, i);
  217 + break;
  218 + case TO_USER_MSG:
  219 + ToUserMsgViewHolder holder3;
  220 + if (view == null) {
  221 + holder3 = new ToUserMsgViewHolder();
  222 + view = mLayoutInflater.inflate(R.layout.layout_msgto_list_item, null);
  223 + holder3.headicon = (ImageView) view
  224 + .findViewById(R.id.tb_my_user_icon);
  225 + holder3.chat_time = (TextView) view
  226 + .findViewById(R.id.mychat_time);
  227 + holder3.content = (GifTextView) view
  228 + .findViewById(R.id.mycontent);
  229 + holder3.sendFailImg = (ImageView) view
  230 + .findViewById(R.id.mysend_fail_img);
  231 + view.setTag(holder3);
  232 + } else {
  233 + holder3 = (ToUserMsgViewHolder) view.getTag();
  234 + }
  235 + toMsgUserLayout((ToUserMsgViewHolder) holder3, tbub, i);
  236 + break;
  237 + case TO_USER_IMG:
  238 + ToUserImgViewHolder holder4;
  239 + if (view == null) {
  240 + holder4 = new ToUserImgViewHolder();
  241 + view = mLayoutInflater.inflate(R.layout.layout_imageto_list_item, null);
  242 + holder4.headicon = (ImageView) view
  243 + .findViewById(R.id.tb_my_user_icon);
  244 + holder4.chat_time = (TextView) view
  245 + .findViewById(R.id.mychat_time);
  246 + holder4.sendFailImg = (ImageView) view
  247 + .findViewById(R.id.mysend_fail_img);
  248 + holder4.image_group = (LinearLayout) view
  249 + .findViewById(R.id.image_group);
  250 + holder4.image_Msg = (BubbleImageView) view
  251 + .findViewById(R.id.image_message);
  252 + view.setTag(holder4);
  253 + } else {
  254 + holder4 = (ToUserImgViewHolder) view.getTag();
  255 + }
  256 + toImgUserLayout((ToUserImgViewHolder) holder4, tbub, i);
  257 + break;
  258 + case TO_USER_VOICE:
  259 + ToUserVoiceViewHolder holder5;
  260 + if (view == null) {
  261 + holder5 = new ToUserVoiceViewHolder();
  262 + view = mLayoutInflater.inflate(R.layout.layout_voiceto_list_item, null);
  263 + holder5.headicon = (ImageView) view
  264 + .findViewById(R.id.tb_my_user_icon);
  265 + holder5.chat_time = (TextView) view
  266 + .findViewById(R.id.mychat_time);
  267 + holder5.voice_group = (LinearLayout) view
  268 + .findViewById(R.id.voice_group);
  269 + holder5.voice_time = (TextView) view
  270 + .findViewById(R.id.voice_time);
  271 + holder5.voice_image = (FrameLayout) view
  272 + .findViewById(R.id.voice_image);
  273 + holder5.voice_anim = (View) view
  274 + .findViewById(R.id.id_recorder_anim);
  275 + holder5.sendFailImg = (ImageView) view
  276 + .findViewById(R.id.mysend_fail_img);
  277 + view.setTag(holder5);
  278 + } else {
  279 + holder5 = (ToUserVoiceViewHolder) view.getTag();
  280 + }
  281 + toVoiceUserLayout((ToUserVoiceViewHolder) holder5, tbub, i);
  282 + break;
  283 + }
  284 +
  285 + return view;
  286 + }
  287 +
  288 + public class FromUserMsgViewHolder {
  289 + public ImageView headicon;
  290 + public TextView chat_time;
  291 + public GifTextView content;
  292 + }
  293 +
  294 + public class FromUserImageViewHolder {
  295 + public ImageView headicon;
  296 + public TextView chat_time;
  297 + public BubbleImageView image_Msg;
  298 + }
  299 +
  300 + public class FromUserVoiceViewHolder {
  301 + public ImageView headicon;
  302 + public TextView chat_time;
  303 + public LinearLayout voice_group;
  304 + public TextView voice_time;
  305 + public FrameLayout voice_image;
  306 + public View receiver_voice_unread;
  307 + public View voice_anim;
  308 + }
  309 +
  310 + public class ToUserMsgViewHolder {
  311 + public ImageView headicon;
  312 + public TextView chat_time;
  313 + public GifTextView content;
  314 + public ImageView sendFailImg;
  315 + }
  316 +
  317 + public class ToUserImgViewHolder {
  318 + public ImageView headicon;
  319 + public TextView chat_time;
  320 + public LinearLayout image_group;
  321 + public BubbleImageView image_Msg;
  322 + public ImageView sendFailImg;
  323 + }
  324 +
  325 + public class ToUserVoiceViewHolder {
  326 + public ImageView headicon;
  327 + public TextView chat_time;
  328 + public LinearLayout voice_group;
  329 + public TextView voice_time;
  330 + public FrameLayout voice_image;
  331 + public View receiver_voice_unread;
  332 + public View voice_anim;
  333 + public ImageView sendFailImg;
  334 + }
  335 +
  336 + private void fromMsgUserLayout(final FromUserMsgViewHolder holder, final ChatMessageBean tbub, final int position) {
  337 + holder.headicon.setBackgroundResource(R.mipmap.tongbao_hiv);
  338 + /* time */
  339 + if (position != 0) {
  340 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  341 + .getTime());
  342 + if (showTime != null) {
  343 + holder.chat_time.setVisibility(View.VISIBLE);
  344 + holder.chat_time.setText(showTime);
  345 + } else {
  346 + holder.chat_time.setVisibility(View.GONE);
  347 + }
  348 + } else {
  349 + String showTime = getTime(tbub.getTime(), null);
  350 + holder.chat_time.setVisibility(View.VISIBLE);
  351 + holder.chat_time.setText(showTime);
  352 + }
  353 + holder.content.setVisibility(View.VISIBLE);
  354 + holder.content.setSpanText(handler, tbub.getUserContent(), isGif);
  355 + }
  356 +
  357 + private void fromImgUserLayout(final FromUserImageViewHolder holder, final ChatMessageBean tbub, final int position) {
  358 + holder.headicon.setBackgroundResource(R.mipmap.tongbao_hiv);
  359 + /* time */
  360 + if (position != 0) {
  361 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  362 + .getTime());
  363 + if (showTime != null) {
  364 + holder.chat_time.setVisibility(View.VISIBLE);
  365 + holder.chat_time.setText(showTime);
  366 + } else {
  367 + holder.chat_time.setVisibility(View.GONE);
  368 + }
  369 + } else {
  370 + String showTime = getTime(tbub.getTime(), null);
  371 + holder.chat_time.setVisibility(View.VISIBLE);
  372 + holder.chat_time.setText(showTime);
  373 + }
  374 + if (isPicRefresh) {
  375 +// holder.image_Msg.setImageBitmap(null);
  376 + final String imageSrc = tbub.getImageLocal() == null ? "" : tbub
  377 + .getImageLocal();
  378 + final String imageUrlSrc = tbub.getImageUrl() == null ? "" : tbub
  379 + .getImageUrl();
  380 + final String imageIconUrl = tbub.getImageIconUrl() == null ? ""
  381 + : tbub.getImageIconUrl();
  382 + File file = new File(imageSrc);
  383 + final boolean hasLocal = !imageSrc.equals("")
  384 + && FileSaveUtil.isFileExists(file);
  385 + int res;
  386 + res = R.drawable.chatfrom_bg_focused;
  387 + if (hasLocal) {
  388 + holder.image_Msg.setLocalImageBitmap(ImageCheckoutUtil.getLoacalBitmap(imageSrc),
  389 + res);
  390 + } else {
  391 + holder.image_Msg.load(imageIconUrl, res, R.mipmap.cygs_cs);
  392 + }
  393 + holder.image_Msg.setOnClickListener(new View.OnClickListener() {
  394 +
  395 + @Override
  396 + public void onClick(View view) {
  397 + // TODO Auto-generated method stub
  398 + stopPlayVoice();
  399 + Intent intent = new Intent(context, ImageViewActivity.class);
  400 + intent.putStringArrayListExtra("images", imageList);
  401 + intent.putExtra("clickedIndex", imagePosition.get(position));
  402 + context.startActivity(intent);
  403 + }
  404 +
  405 + });
  406 + }
  407 +
  408 + }
  409 +
  410 + private void fromVoiceUserLayout(final FromUserVoiceViewHolder holder, final ChatMessageBean tbub, final int position) {
  411 + holder.headicon.setBackgroundResource(R.mipmap.tongbao_hiv);
  412 + /* time */
  413 + if (position != 0) {
  414 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  415 + .getTime());
  416 + if (showTime != null) {
  417 + holder.chat_time.setVisibility(View.VISIBLE);
  418 + holder.chat_time.setText(showTime);
  419 + } else {
  420 + holder.chat_time.setVisibility(View.GONE);
  421 + }
  422 + } else {
  423 + String showTime = getTime(tbub.getTime(), null);
  424 + holder.chat_time.setVisibility(View.VISIBLE);
  425 + holder.chat_time.setText(showTime);
  426 + }
  427 +
  428 + holder.voice_group.setVisibility(View.VISIBLE);
  429 + if (holder.receiver_voice_unread != null)
  430 + holder.receiver_voice_unread.setVisibility(View.GONE);
  431 + if (holder.receiver_voice_unread != null && unReadPosition != null) {
  432 + for (String unRead : unReadPosition) {
  433 + if (unRead.equals(position + "")) {
  434 + holder.receiver_voice_unread
  435 + .setVisibility(View.VISIBLE);
  436 + break;
  437 + }
  438 + }
  439 + }
  440 + AnimationDrawable drawable;
  441 + holder.voice_anim.setId(position);
  442 + if (position == voicePlayPosition) {
  443 + holder.voice_anim
  444 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  445 + holder.voice_anim
  446 + .setBackgroundResource(R.drawable.voice_play_receiver);
  447 + drawable = (AnimationDrawable) holder.voice_anim
  448 + .getBackground();
  449 + drawable.start();
  450 + } else {
  451 + holder.voice_anim
  452 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  453 + }
  454 + holder.voice_group.setOnClickListener(new View.OnClickListener() {
  455 +
  456 + @Override
  457 + public void onClick(View v) {
  458 + // TODO Auto-generated method stub
  459 + if (holder.receiver_voice_unread != null)
  460 + holder.receiver_voice_unread.setVisibility(View.GONE);
  461 + holder.voice_anim
  462 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  463 + stopPlayVoice();
  464 + voicePlayPosition = holder.voice_anim.getId();
  465 + AnimationDrawable drawable;
  466 + holder.voice_anim
  467 + .setBackgroundResource(R.drawable.voice_play_receiver);
  468 + drawable = (AnimationDrawable) holder.voice_anim
  469 + .getBackground();
  470 + drawable.start();
  471 + String voicePath = tbub.getUserVoicePath() == null ? "" : tbub
  472 + .getUserVoicePath();
  473 + File file = new File(voicePath);
  474 + if (!(!voicePath.equals("") && FileSaveUtil
  475 + .isFileExists(file))) {
  476 + voicePath = tbub.getUserVoiceUrl() == null ? ""
  477 + : tbub.getUserVoiceUrl();
  478 + }
  479 + if (voiceIsRead != null) {
  480 + voiceIsRead.voiceOnClick(position);
  481 + }
  482 + MediaManager.playSound(voicePath,
  483 + new MediaPlayer.OnCompletionListener() {
  484 +
  485 + @Override
  486 + public void onCompletion(MediaPlayer mp) {
  487 + voicePlayPosition = -1;
  488 + holder.voice_anim
  489 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  490 + }
  491 + });
  492 + }
  493 +
  494 + });
  495 + float voiceTime = tbub.getUserVoiceTime();
  496 + BigDecimal b = new BigDecimal(voiceTime);
  497 + float f1 = b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
  498 + holder.voice_time.setText(f1 + "\"");
  499 + ViewGroup.LayoutParams lParams = holder.voice_image
  500 + .getLayoutParams();
  501 + lParams.width = (int) (mMinItemWith + mMaxItemWith / 60f
  502 + * tbub.getUserVoiceTime());
  503 + holder.voice_image.setLayoutParams(lParams);
  504 + }
  505 +
  506 + private void toMsgUserLayout(final ToUserMsgViewHolder holder, final ChatMessageBean tbub, final int position) {
  507 + holder.headicon.setBackgroundResource(R.mipmap.grzx_tx_s);
  508 + holder.headicon.setImageDrawable(context.getResources()
  509 + .getDrawable(R.mipmap.grzx_tx_s));
  510 + /* time */
  511 + if (position != 0) {
  512 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  513 + .getTime());
  514 + if (showTime != null) {
  515 + holder.chat_time.setVisibility(View.VISIBLE);
  516 + holder.chat_time.setText(showTime);
  517 + } else {
  518 + holder.chat_time.setVisibility(View.GONE);
  519 + }
  520 + } else {
  521 + String showTime = getTime(tbub.getTime(), null);
  522 + holder.chat_time.setVisibility(View.VISIBLE);
  523 + holder.chat_time.setText(showTime);
  524 + }
  525 +
  526 + holder.content.setVisibility(View.VISIBLE);
  527 + holder.content.setSpanText(handler, tbub.getUserContent(), isGif);
  528 + }
  529 +
  530 + private void toImgUserLayout(final ToUserImgViewHolder holder, final ChatMessageBean tbub, final int position) {
  531 + holder.headicon.setBackgroundResource(R.mipmap.grzx_tx_s);
  532 + switch (tbub.getSendState()) {
  533 + case ChatConst.SENDING:
  534 + an = AnimationUtils.loadAnimation(context,
  535 + R.anim.update_loading_progressbar_anim);
  536 + LinearInterpolator lin = new LinearInterpolator();
  537 + an.setInterpolator(lin);
  538 + an.setRepeatCount(-1);
  539 + holder.sendFailImg
  540 + .setBackgroundResource(R.mipmap.xsearch_loading);
  541 + holder.sendFailImg.startAnimation(an);
  542 + an.startNow();
  543 + holder.sendFailImg.setVisibility(View.VISIBLE);
  544 + break;
  545 +
  546 + case ChatConst.COMPLETED:
  547 + holder.sendFailImg.clearAnimation();
  548 + holder.sendFailImg.setVisibility(View.GONE);
  549 + break;
  550 +
  551 + case ChatConst.SENDERROR:
  552 + holder.sendFailImg.clearAnimation();
  553 + holder.sendFailImg
  554 + .setBackgroundResource(R.mipmap.msg_state_fail_resend_pressed);
  555 + holder.sendFailImg.setVisibility(View.VISIBLE);
  556 + holder.sendFailImg.setOnClickListener(new View.OnClickListener() {
  557 +
  558 + @Override
  559 + public void onClick(View view) {
  560 + // TODO Auto-generated method stub
  561 + if (sendErrorListener != null) {
  562 + sendErrorListener.onClick(position);
  563 + }
  564 + }
  565 +
  566 + });
  567 + break;
  568 + default:
  569 + break;
  570 + }
  571 + holder.headicon.setImageDrawable(context.getResources()
  572 + .getDrawable(R.mipmap.grzx_tx_s));
  573 +
  574 + /* time */
  575 + if (position != 0) {
  576 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  577 + .getTime());
  578 + if (showTime != null) {
  579 + holder.chat_time.setVisibility(View.VISIBLE);
  580 + holder.chat_time.setText(showTime);
  581 + } else {
  582 + holder.chat_time.setVisibility(View.GONE);
  583 + }
  584 + } else {
  585 + String showTime = getTime(tbub.getTime(), null);
  586 + holder.chat_time.setVisibility(View.VISIBLE);
  587 + holder.chat_time.setText(showTime);
  588 + }
  589 +
  590 + if (isPicRefresh) {
  591 +// holder.image_Msg.setImageBitmap(null);
  592 + holder.image_group.setVisibility(View.VISIBLE);
  593 + final String imageSrc = tbub.getImageLocal() == null ? "" : tbub
  594 + .getImageLocal();
  595 + final String imageUrlSrc = tbub.getImageUrl() == null ? "" : tbub
  596 + .getImageUrl();
  597 + final String imageIconUrl = tbub.getImageIconUrl() == null ? ""
  598 + : tbub.getImageIconUrl();
  599 + File file = new File(imageSrc);
  600 + final boolean hasLocal = !imageSrc.equals("")
  601 + && FileSaveUtil.isFileExists(file);
  602 + int res;
  603 + res = R.drawable.chatto_bg_focused;
  604 + if (hasLocal) {
  605 + holder.image_Msg.setLocalImageBitmap(ImageCheckoutUtil.getLoacalBitmap(imageSrc),
  606 + res);
  607 + } else {
  608 + holder.image_Msg.load(imageIconUrl, res, R.mipmap.cygs_cs);
  609 + }
  610 + holder.image_Msg.setOnClickListener(new View.OnClickListener() {
  611 +
  612 + @Override
  613 + public void onClick(View view) {
  614 + // TODO Auto-generated method stub
  615 + stopPlayVoice();
  616 + Intent intent = new Intent(context, ImageViewActivity.class);
  617 + intent.putStringArrayListExtra("images", imageList);
  618 + intent.putExtra("clickedIndex", imagePosition.get(position));
  619 + context.startActivity(intent);
  620 + }
  621 +
  622 + });
  623 + }
  624 + }
  625 +
  626 + private void toVoiceUserLayout(final ToUserVoiceViewHolder holder, final ChatMessageBean tbub, final int position) {
  627 + holder.headicon.setBackgroundResource(R.mipmap.grzx_tx_s);
  628 + switch (tbub.getSendState()) {
  629 + case ChatConst.SENDING:
  630 + an = AnimationUtils.loadAnimation(context,
  631 + R.anim.update_loading_progressbar_anim);
  632 + LinearInterpolator lin = new LinearInterpolator();
  633 + an.setInterpolator(lin);
  634 + an.setRepeatCount(-1);
  635 + holder.sendFailImg
  636 + .setBackgroundResource(R.mipmap.xsearch_loading);
  637 + holder.sendFailImg.startAnimation(an);
  638 + an.startNow();
  639 + holder.sendFailImg.setVisibility(View.VISIBLE);
  640 + break;
  641 +
  642 + case ChatConst.COMPLETED:
  643 + holder.sendFailImg.clearAnimation();
  644 + holder.sendFailImg.setVisibility(View.GONE);
  645 + break;
  646 +
  647 + case ChatConst.SENDERROR:
  648 + holder.sendFailImg.clearAnimation();
  649 + holder.sendFailImg
  650 + .setBackgroundResource(R.mipmap.msg_state_fail_resend_pressed);
  651 + holder.sendFailImg.setVisibility(View.VISIBLE);
  652 + holder.sendFailImg.setOnClickListener(new View.OnClickListener() {
  653 +
  654 + @Override
  655 + public void onClick(View view) {
  656 + // TODO Auto-generated method stub
  657 + if (sendErrorListener != null) {
  658 + sendErrorListener.onClick(position);
  659 + }
  660 + }
  661 +
  662 + });
  663 + break;
  664 + default:
  665 + break;
  666 + }
  667 + holder.headicon.setImageDrawable(context.getResources()
  668 + .getDrawable(R.mipmap.grzx_tx_s));
  669 +
  670 + /* time */
  671 + if (position != 0) {
  672 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  673 + .getTime());
  674 + if (showTime != null) {
  675 + holder.chat_time.setVisibility(View.VISIBLE);
  676 + holder.chat_time.setText(showTime);
  677 + } else {
  678 + holder.chat_time.setVisibility(View.GONE);
  679 + }
  680 + } else {
  681 + String showTime = getTime(tbub.getTime(), null);
  682 + holder.chat_time.setVisibility(View.VISIBLE);
  683 + holder.chat_time.setText(showTime);
  684 + }
  685 + holder.voice_group.setVisibility(View.VISIBLE);
  686 + if (holder.receiver_voice_unread != null)
  687 + holder.receiver_voice_unread.setVisibility(View.GONE);
  688 + if (holder.receiver_voice_unread != null && unReadPosition != null) {
  689 + for (String unRead : unReadPosition) {
  690 + if (unRead.equals(position + "")) {
  691 + holder.receiver_voice_unread
  692 + .setVisibility(View.VISIBLE);
  693 + break;
  694 + }
  695 + }
  696 + }
  697 + AnimationDrawable drawable;
  698 + holder.voice_anim.setId(position);
  699 + if (position == voicePlayPosition) {
  700 + holder.voice_anim.setBackgroundResource(R.mipmap.adj);
  701 + holder.voice_anim
  702 + .setBackgroundResource(R.drawable.voice_play_send);
  703 + drawable = (AnimationDrawable) holder.voice_anim
  704 + .getBackground();
  705 + drawable.start();
  706 + } else {
  707 + holder.voice_anim.setBackgroundResource(R.mipmap.adj);
  708 + }
  709 + holder.voice_group.setOnClickListener(new View.OnClickListener() {
  710 +
  711 + @Override
  712 + public void onClick(View v) {
  713 + // TODO Auto-generated method stub
  714 + if (holder.receiver_voice_unread != null)
  715 + holder.receiver_voice_unread.setVisibility(View.GONE);
  716 + holder.voice_anim.setBackgroundResource(R.mipmap.adj);
  717 + stopPlayVoice();
  718 + voicePlayPosition = holder.voice_anim.getId();
  719 + AnimationDrawable drawable;
  720 + holder.voice_anim
  721 + .setBackgroundResource(R.drawable.voice_play_send);
  722 + drawable = (AnimationDrawable) holder.voice_anim
  723 + .getBackground();
  724 + drawable.start();
  725 + String voicePath = tbub.getUserVoiceUrl() == null ? ""
  726 + : tbub.getUserVoiceUrl();
  727 + if (voiceIsRead != null) {
  728 + voiceIsRead.voiceOnClick(position);
  729 + }
  730 + MediaManager.playSound(voicePath,
  731 + new MediaPlayer.OnCompletionListener() {
  732 +
  733 + @Override
  734 + public void onCompletion(MediaPlayer mp) {
  735 + voicePlayPosition = -1;
  736 + holder.voice_anim
  737 + .setBackgroundResource(R.mipmap.adj);
  738 + }
  739 + });
  740 + }
  741 +
  742 + });
  743 + float voiceTime = tbub.getUserVoiceTime();
  744 + BigDecimal b = new BigDecimal(voiceTime);
  745 + float f1 = b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
  746 + holder.voice_time.setText(f1 + "\"");
  747 + ViewGroup.LayoutParams lParams = holder.voice_image
  748 + .getLayoutParams();
  749 + lParams.width = (int) (mMinItemWith + mMaxItemWith / 60f
  750 + * tbub.getUserVoiceTime());
  751 + holder.voice_image.setLayoutParams(lParams);
  752 + }
  753 +
  754 + @SuppressLint("SimpleDateFormat")
  755 + public String getTime(String time, String before) {
  756 + String show_time = null;
  757 + if (before != null) {
  758 + try {
  759 + DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  760 + java.util.Date now = df.parse(time);
  761 + java.util.Date date = df.parse(before);
  762 + long l = now.getTime() - date.getTime();
  763 + long day = l / (24 * 60 * 60 * 1000);
  764 + long hour = (l / (60 * 60 * 1000) - day * 24);
  765 + long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
  766 + if (min >= 1) {
  767 + show_time = time.substring(11);
  768 + }
  769 + } catch (Exception e) {
  770 + e.printStackTrace();
  771 + }
  772 + } else {
  773 + show_time = time.substring(11);
  774 + }
  775 + String getDay = getDay(time);
  776 + if (show_time != null && getDay != null)
  777 + show_time = getDay + " " + show_time;
  778 + return show_time;
  779 + }
  780 +
  781 + @SuppressLint("SimpleDateFormat")
  782 + public static String returnTime() {
  783 + SimpleDateFormat sDateFormat = new SimpleDateFormat(
  784 + "yyyy-MM-dd HH:mm:ss");
  785 + String date = sDateFormat.format(new java.util.Date());
  786 + return date;
  787 + }
  788 +
  789 + @SuppressLint("SimpleDateFormat")
  790 + public String getDay(String time) {
  791 + String showDay = null;
  792 + String nowTime = returnTime();
  793 + try {
  794 + DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  795 + java.util.Date now = df.parse(nowTime);
  796 + java.util.Date date = df.parse(time);
  797 + long l = now.getTime() - date.getTime();
  798 + long day = l / (24 * 60 * 60 * 1000);
  799 + if (day >= 365) {
  800 + showDay = time.substring(0, 10);
  801 + } else if (day >= 1 && day < 365) {
  802 + showDay = time.substring(5, 10);
  803 + }
  804 + } catch (Exception e) {
  805 + e.printStackTrace();
  806 + }
  807 + return showDay;
  808 + }
  809 +
  810 + public void stopPlayVoice() {
  811 + if (voicePlayPosition != -1) {
  812 + View voicePlay = (View) ((Activity) context)
  813 + .findViewById(voicePlayPosition);
  814 + if (voicePlay != null) {
  815 + if (getItemViewType(voicePlayPosition) == FROM_USER_VOICE) {
  816 + voicePlay
  817 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  818 + } else {
  819 + voicePlay.setBackgroundResource(R.mipmap.adj);
  820 + }
  821 + }
  822 + MediaManager.pause();
  823 + voicePlayPosition = -1;
  824 + }
  825 + }
  826 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/activity/chartroom/adapter/ChatRecyclerAdapter.java 0 → 100644
... ... @@ -0,0 +1,858 @@
  1 +package com.shunzhi.parent.ui.activity.chartroom.adapter;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.app.Activity;
  5 +import android.content.Context;
  6 +import android.content.Intent;
  7 +import android.graphics.Bitmap;
  8 +import android.graphics.BitmapFactory;
  9 +import android.graphics.drawable.AnimationDrawable;
  10 +import android.media.MediaPlayer;
  11 +import android.os.Handler;
  12 +import android.support.v7.widget.RecyclerView;
  13 +import android.text.TextUtils;
  14 +import android.util.DisplayMetrics;
  15 +import android.view.LayoutInflater;
  16 +import android.view.View;
  17 +import android.view.ViewGroup;
  18 +import android.view.WindowManager;
  19 +import android.view.animation.Animation;
  20 +import android.view.animation.AnimationUtils;
  21 +import android.view.animation.LinearInterpolator;
  22 +import android.widget.FrameLayout;
  23 +import android.widget.ImageView;
  24 +import android.widget.LinearLayout;
  25 +import android.widget.TextView;
  26 +
  27 +import com.bumptech.glide.Glide;
  28 +import com.shunzhi.mychartlibrary.db.ChatMessageBean;
  29 +import com.shunzhi.parent.AppConfig;
  30 +import com.shunzhi.parent.AppContext;
  31 +import com.shunzhi.parent.R;
  32 +import com.shunzhi.parent.ui.activity.chartroom.ImageViewActivity;
  33 +import com.shunzhi.mychartlibrary.common.ChatConst;
  34 +import com.shunzhi.mychartlibrary.utils.FileSaveUtil;
  35 +import com.shunzhi.mychartlibrary.widget.BubbleImageView;
  36 +import com.shunzhi.mychartlibrary.widget.CustomShapeTransformation;
  37 +import com.shunzhi.mychartlibrary.widget.GifTextView;
  38 +import com.shunzhi.mychartlibrary.widget.MediaManager;
  39 +import com.shunzhi.parent.util.GlideUtils;
  40 +
  41 +import java.io.BufferedInputStream;
  42 +import java.io.ByteArrayOutputStream;
  43 +import java.io.File;
  44 +import java.io.FileInputStream;
  45 +import java.io.FileNotFoundException;
  46 +import java.io.IOException;
  47 +import java.math.BigDecimal;
  48 +import java.text.DateFormat;
  49 +import java.text.SimpleDateFormat;
  50 +import java.util.ArrayList;
  51 +import java.util.HashMap;
  52 +import java.util.List;
  53 +
  54 +/**
  55 + * Created by Mao Jiqing on 2016/9/29.
  56 + */
  57 +public class ChatRecyclerAdapter extends
  58 + RecyclerView.Adapter<RecyclerView.ViewHolder> {
  59 + private Context context;
  60 + private List<ChatMessageBean> userList = new ArrayList<ChatMessageBean>();
  61 + private ArrayList<String> imageList = new ArrayList<String>();
  62 + private HashMap<Integer, Integer> imagePosition = new HashMap<Integer, Integer>();
  63 + public static final int FROM_USER_MSG = 0;//接收消息类型
  64 + public static final int TO_USER_MSG = 1;//发送消息类型
  65 + public static final int FROM_USER_IMG = 2;//接收消息类型
  66 + public static final int TO_USER_IMG = 3;//发送消息类型
  67 + public static final int FROM_USER_VOICE = 4;//接收消息类型
  68 + public static final int TO_USER_VOICE = 5;//发送消息类型
  69 + private int mMinItemWith;// 设置对话框的最大宽度和最小宽度
  70 + private int mMaxItemWith;
  71 + public Handler handler;
  72 + private Animation an;
  73 + private SendErrorListener sendErrorListener;
  74 + private VoiceIsRead voiceIsRead;
  75 + public List<String> unReadPosition = new ArrayList<String>();
  76 + private int voicePlayPosition = -1;
  77 + private LayoutInflater mLayoutInflater;
  78 + private boolean isGif = true;
  79 + public boolean isPicRefresh = true;
  80 + private String parentUrl = "",childPhoto;
  81 +
  82 + public interface SendErrorListener {
  83 + public void onClick(int position);
  84 + }
  85 +
  86 + public void setSendErrorListener(SendErrorListener sendErrorListener) {
  87 + this.sendErrorListener = sendErrorListener;
  88 + }
  89 +
  90 + public interface VoiceIsRead {
  91 + public void voiceOnClick(int position);
  92 + }
  93 +
  94 + public void setVoiceIsReadListener(VoiceIsRead voiceIsRead) {
  95 + this.voiceIsRead = voiceIsRead;
  96 + }
  97 +
  98 + public ChatRecyclerAdapter(Context context, List<ChatMessageBean> userList,String childPhoto) {
  99 + this.context = context;
  100 + this.userList = userList;
  101 + mLayoutInflater = LayoutInflater.from(context);
  102 + // 获取系统宽度
  103 + WindowManager wManager = (WindowManager) context
  104 + .getSystemService(Context.WINDOW_SERVICE);
  105 + DisplayMetrics outMetrics = new DisplayMetrics();
  106 + wManager.getDefaultDisplay().getMetrics(outMetrics);
  107 + mMaxItemWith = (int) (outMetrics.widthPixels * 0.5f);
  108 + mMinItemWith = (int) (outMetrics.widthPixels * 0.15f);
  109 + handler = new Handler();
  110 + parentUrl= AppConfig.getAppConfig(AppContext.getInstance()).get(AppConfig.USER_IMAGE);
  111 + this.childPhoto=childPhoto;
  112 + }
  113 +
  114 + public void setIsGif(boolean isGif) {
  115 + this.isGif = isGif;
  116 + }
  117 +
  118 + public void setImageList(ArrayList<String> imageList) {
  119 + this.imageList = imageList;
  120 + }
  121 +
  122 + public void setImagePosition(HashMap<Integer, Integer> imagePosition) {
  123 + this.imagePosition = imagePosition;
  124 + }
  125 +
  126 + /**
  127 + * @param parent
  128 + * @param viewType
  129 + * @return
  130 + */
  131 + @Override
  132 + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  133 + View view = null;
  134 + RecyclerView.ViewHolder holder = null;
  135 + switch (viewType) {
  136 + case FROM_USER_MSG:
  137 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_msgfrom_list_item, parent, false);
  138 + holder = new FromUserMsgViewHolder(view);
  139 + break;
  140 + case FROM_USER_IMG:
  141 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_imagefrom_list_item, parent, false);
  142 + holder = new FromUserImageViewHolder(view);
  143 + break;
  144 + case FROM_USER_VOICE:
  145 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_voicefrom_list_item, parent, false);
  146 + holder = new FromUserVoiceViewHolder(view);
  147 + break;
  148 + case TO_USER_MSG:
  149 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_msgto_list_item, parent, false);
  150 + holder = new ToUserMsgViewHolder(view);
  151 + break;
  152 + case TO_USER_IMG:
  153 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_imageto_list_item, parent, false);
  154 + holder = new ToUserImgViewHolder(view);
  155 + break;
  156 + case TO_USER_VOICE:
  157 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_voiceto_list_item, parent, false);
  158 + holder = new ToUserVoiceViewHolder(view);
  159 + break;
  160 + }
  161 + return holder;
  162 + }
  163 +
  164 + class FromUserMsgViewHolder extends RecyclerView.ViewHolder {
  165 + private ImageView headicon;
  166 + private TextView chat_time;
  167 + private GifTextView content;
  168 +
  169 + public FromUserMsgViewHolder(View view) {
  170 + super(view);
  171 + headicon = (ImageView) view
  172 + .findViewById(R.id.tb_other_user_icon);
  173 + chat_time = (TextView) view.findViewById(R.id.chat_time);
  174 + content = (GifTextView) view.findViewById(R.id.content);
  175 + }
  176 + }
  177 +
  178 + class FromUserImageViewHolder extends RecyclerView.ViewHolder {
  179 + private ImageView headicon;
  180 + private TextView chat_time;
  181 + private BubbleImageView image_Msg;
  182 +
  183 + public FromUserImageViewHolder(View view) {
  184 + super(view);
  185 + headicon = (ImageView) view
  186 + .findViewById(R.id.tb_other_user_icon);
  187 + chat_time = (TextView) view.findViewById(R.id.chat_time);
  188 + image_Msg = (BubbleImageView) view
  189 + .findViewById(R.id.image_message);
  190 + }
  191 + }
  192 +
  193 + class FromUserVoiceViewHolder extends RecyclerView.ViewHolder {
  194 + private ImageView headicon;
  195 + private TextView chat_time;
  196 + private LinearLayout voice_group;
  197 + private TextView voice_time;
  198 + private FrameLayout voice_image;
  199 + private View receiver_voice_unread;
  200 + private View voice_anim;
  201 +
  202 + public FromUserVoiceViewHolder(View view) {
  203 + super(view);
  204 + headicon = (ImageView) view
  205 + .findViewById(R.id.tb_other_user_icon);
  206 + chat_time = (TextView) view.findViewById(R.id.chat_time);
  207 + voice_group = (LinearLayout) view
  208 + .findViewById(R.id.voice_group);
  209 + voice_time = (TextView) view
  210 + .findViewById(R.id.voice_time);
  211 + receiver_voice_unread = (View) view
  212 + .findViewById(R.id.receiver_voice_unread);
  213 + voice_image = (FrameLayout) view
  214 + .findViewById(R.id.voice_receiver_image);
  215 + voice_anim = (View) view
  216 + .findViewById(R.id.id_receiver_recorder_anim);
  217 + }
  218 + }
  219 +
  220 + class ToUserMsgViewHolder extends RecyclerView.ViewHolder {
  221 + private ImageView headicon;
  222 + private TextView chat_time;
  223 + private GifTextView content;
  224 + private ImageView sendFailImg;
  225 +
  226 + public ToUserMsgViewHolder(View view) {
  227 + super(view);
  228 + headicon = (ImageView) view
  229 + .findViewById(R.id.tb_my_user_icon);
  230 + chat_time = (TextView) view
  231 + .findViewById(R.id.mychat_time);
  232 + content = (GifTextView) view
  233 + .findViewById(R.id.mycontent);
  234 + sendFailImg = (ImageView) view
  235 + .findViewById(R.id.mysend_fail_img);
  236 + }
  237 + }
  238 +
  239 + class ToUserImgViewHolder extends RecyclerView.ViewHolder {
  240 + private ImageView headicon;
  241 + private TextView chat_time;
  242 + private LinearLayout image_group;
  243 + private BubbleImageView image_Msg;
  244 + private ImageView sendFailImg;
  245 +
  246 + public ToUserImgViewHolder(View view) {
  247 + super(view);
  248 + headicon = (ImageView) view
  249 + .findViewById(R.id.tb_my_user_icon);
  250 + chat_time = (TextView) view
  251 + .findViewById(R.id.mychat_time);
  252 + sendFailImg = (ImageView) view
  253 + .findViewById(R.id.mysend_fail_img);
  254 + image_group = (LinearLayout) view
  255 + .findViewById(R.id.image_group);
  256 + image_Msg = (BubbleImageView) view
  257 + .findViewById(R.id.image_message);
  258 + }
  259 + }
  260 +
  261 + class ToUserVoiceViewHolder extends RecyclerView.ViewHolder {
  262 + private ImageView headicon;
  263 + private TextView chat_time;
  264 + private LinearLayout voice_group;
  265 + private TextView voice_time;
  266 + private FrameLayout voice_image;
  267 + private View receiver_voice_unread;
  268 + private View voice_anim;
  269 + private ImageView sendFailImg;
  270 +
  271 + public ToUserVoiceViewHolder(View view) {
  272 + super(view);
  273 + headicon = (ImageView) view
  274 + .findViewById(R.id.tb_my_user_icon);
  275 + chat_time = (TextView) view
  276 + .findViewById(R.id.mychat_time);
  277 + voice_group = (LinearLayout) view
  278 + .findViewById(R.id.voice_group);
  279 + voice_time = (TextView) view
  280 + .findViewById(R.id.voice_time);
  281 + voice_image = (FrameLayout) view
  282 + .findViewById(R.id.voice_image);
  283 + voice_anim = (View) view
  284 + .findViewById(R.id.id_recorder_anim);
  285 + sendFailImg = (ImageView) view
  286 + .findViewById(R.id.mysend_fail_img);
  287 + }
  288 + }
  289 +
  290 + /**
  291 + * @param holder
  292 + * @param position
  293 + */
  294 + @Override
  295 + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  296 + ChatMessageBean tbub = userList.get(position);
  297 + int itemViewType = getItemViewType(position);
  298 + switch (itemViewType) {
  299 + case FROM_USER_MSG:
  300 + fromMsgUserLayout((FromUserMsgViewHolder) holder, tbub, position);
  301 + break;
  302 + case FROM_USER_IMG:
  303 + fromImgUserLayout((FromUserImageViewHolder) holder, tbub, position);
  304 + break;
  305 + case FROM_USER_VOICE:
  306 + fromVoiceUserLayout((FromUserVoiceViewHolder) holder, tbub, position);
  307 + break;
  308 + case TO_USER_MSG:
  309 + toMsgUserLayout((ToUserMsgViewHolder) holder, tbub, position);
  310 + break;
  311 + case TO_USER_IMG:
  312 + toImgUserLayout((ToUserImgViewHolder) holder, tbub, position);
  313 + break;
  314 + case TO_USER_VOICE:
  315 + toVoiceUserLayout((ToUserVoiceViewHolder) holder, tbub, position);
  316 + break;
  317 + }
  318 + }
  319 +
  320 + @Override
  321 + public int getItemViewType(int position) {
  322 + return userList.get(position).getType();
  323 + }
  324 +
  325 + @Override
  326 + public int getItemCount() {
  327 + return userList.size();
  328 + }
  329 +
  330 + private void fromMsgUserLayout(final FromUserMsgViewHolder holder, final ChatMessageBean tbub, final int position) {
  331 +// holder.headicon.setBackgroundResource(R.mipmap.tongbao_hiv);
  332 + if (!TextUtils.isEmpty(childPhoto))
  333 + GlideUtils.showImg(context,holder.headicon,childPhoto);
  334 + else holder.headicon.setImageResource(R.drawable.header_icon);
  335 + /* time */
  336 + if (position != 0) {
  337 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  338 + .getTime());
  339 + if (showTime != null) {
  340 + holder.chat_time.setVisibility(View.VISIBLE);
  341 + holder.chat_time.setText(showTime);
  342 + } else {
  343 + holder.chat_time.setVisibility(View.GONE);
  344 + }
  345 + } else {
  346 + String showTime = getTime(tbub.getTime(), null);
  347 + holder.chat_time.setVisibility(View.VISIBLE);
  348 + holder.chat_time.setText(showTime);
  349 + }
  350 + holder.content.setVisibility(View.VISIBLE);
  351 + holder.content.setSpanText(handler, tbub.getUserContent(), isGif);
  352 + }
  353 +
  354 + private void fromImgUserLayout(final FromUserImageViewHolder holder, final ChatMessageBean tbub, final int position) {
  355 + if (!TextUtils.isEmpty(childPhoto))
  356 + GlideUtils.showImg(context,holder.headicon,childPhoto);
  357 + else holder.headicon.setImageResource(R.drawable.header_icon);
  358 + /* time */
  359 + if (position != 0) {
  360 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  361 + .getTime());
  362 + if (showTime != null) {
  363 + holder.chat_time.setVisibility(View.VISIBLE);
  364 + holder.chat_time.setText(showTime);
  365 + } else {
  366 + holder.chat_time.setVisibility(View.GONE);
  367 + }
  368 + } else {
  369 + String showTime = getTime(tbub.getTime(), null);
  370 + holder.chat_time.setVisibility(View.VISIBLE);
  371 + holder.chat_time.setText(showTime);
  372 + }
  373 +// if (isPicRefresh) {
  374 + final String imageSrc = tbub.getImageLocal() == null ? "" : tbub
  375 + .getImageLocal();
  376 + final String imageUrlSrc = tbub.getImageUrl() == null ? "" : tbub
  377 + .getImageUrl();
  378 + final String imageIconUrl = tbub.getImageIconUrl() == null ? ""
  379 + : tbub.getImageIconUrl();
  380 + File file = new File(imageSrc);
  381 + final boolean hasLocal = !imageSrc.equals("")
  382 + && FileSaveUtil.isFileExists(file);
  383 + int res;
  384 + res = R.drawable.chatfrom_bg_focused;
  385 +// Glide.with(context).load(imageSrc).transform(new CustomShapeTransformation(context, res)).into(holder.image_Msg);
  386 + Glide.with(context).load(imageSrc).placeholder(R.mipmap.cygs_cs).transform(new CustomShapeTransformation(context, res)).into(holder.image_Msg);
  387 +
  388 + holder.image_Msg.setOnClickListener(new View.OnClickListener() {
  389 +
  390 + @Override
  391 + public void onClick(View view) {
  392 + // TODO Auto-generated method stub
  393 + stopPlayVoice();
  394 + Intent intent = new Intent(context, ImageViewActivity.class);
  395 + intent.putStringArrayListExtra("images", imageList);
  396 + intent.putExtra("clickedIndex", imagePosition.get(position));
  397 + context.startActivity(intent);
  398 + }
  399 +
  400 + });
  401 +// }
  402 +
  403 + }
  404 +
  405 + private void fromVoiceUserLayout(final FromUserVoiceViewHolder holder, final ChatMessageBean tbub, final int position) {
  406 + if (!TextUtils.isEmpty(childPhoto))
  407 + GlideUtils.showImg(context,holder.headicon,childPhoto);
  408 + else holder.headicon.setImageResource(R.drawable.header_icon);
  409 + /* time */
  410 + if (position != 0) {
  411 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  412 + .getTime());
  413 + if (showTime != null) {
  414 + holder.chat_time.setVisibility(View.VISIBLE);
  415 + holder.chat_time.setText(showTime);
  416 + } else {
  417 + holder.chat_time.setVisibility(View.GONE);
  418 + }
  419 + } else {
  420 + String showTime = getTime(tbub.getTime(), null);
  421 + holder.chat_time.setVisibility(View.VISIBLE);
  422 + holder.chat_time.setText(showTime);
  423 + }
  424 +
  425 + holder.voice_group.setVisibility(View.VISIBLE);
  426 + if (holder.receiver_voice_unread != null)
  427 + holder.receiver_voice_unread.setVisibility(View.GONE);
  428 + if (holder.receiver_voice_unread != null && unReadPosition != null) {
  429 + for (String unRead : unReadPosition) {
  430 + if (unRead.equals(position + "")) {
  431 + holder.receiver_voice_unread
  432 + .setVisibility(View.VISIBLE);
  433 + break;
  434 + }
  435 + }
  436 + }
  437 + AnimationDrawable drawable;
  438 + holder.voice_anim.setId(position);
  439 + if (position == voicePlayPosition) {
  440 + holder.voice_anim
  441 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  442 + holder.voice_anim
  443 + .setBackgroundResource(R.drawable.voice_play_receiver);
  444 + drawable = (AnimationDrawable) holder.voice_anim
  445 + .getBackground();
  446 + drawable.start();
  447 + } else {
  448 + holder.voice_anim
  449 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  450 + }
  451 + holder.voice_group.setOnClickListener(new View.OnClickListener() {
  452 +
  453 + @Override
  454 + public void onClick(View v) {
  455 + // TODO Auto-generated method stub
  456 + if (holder.receiver_voice_unread != null)
  457 + holder.receiver_voice_unread.setVisibility(View.GONE);
  458 + holder.voice_anim
  459 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  460 + stopPlayVoice();
  461 + voicePlayPosition = holder.voice_anim.getId();
  462 + AnimationDrawable drawable;
  463 + holder.voice_anim
  464 + .setBackgroundResource(R.drawable.voice_play_receiver);
  465 + drawable = (AnimationDrawable) holder.voice_anim
  466 + .getBackground();
  467 + drawable.start();
  468 + String voicePath = tbub.getUserVoicePath() == null ? "" : tbub
  469 + .getUserVoicePath();
  470 + File file = new File(voicePath);
  471 + if (!(!voicePath.equals("") && FileSaveUtil
  472 + .isFileExists(file))) {
  473 + voicePath = tbub.getUserVoiceUrl() == null ? ""
  474 + : tbub.getUserVoiceUrl();
  475 + }
  476 + if (voiceIsRead != null) {
  477 + voiceIsRead.voiceOnClick(position);
  478 + }
  479 + MediaManager.playSound(voicePath,
  480 + new MediaPlayer.OnCompletionListener() {
  481 +
  482 + @Override
  483 + public void onCompletion(MediaPlayer mp) {
  484 + voicePlayPosition = -1;
  485 + holder.voice_anim
  486 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  487 + }
  488 + });
  489 + }
  490 +
  491 + });
  492 + float voiceTime = tbub.getUserVoiceTime();
  493 + BigDecimal b = new BigDecimal(voiceTime);
  494 + float f1 = b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
  495 + holder.voice_time.setText(f1 + "\"");
  496 + ViewGroup.LayoutParams lParams = holder.voice_image
  497 + .getLayoutParams();
  498 + lParams.width = (int) (mMinItemWith + mMaxItemWith / 60f
  499 + * tbub.getUserVoiceTime());
  500 + holder.voice_image.setLayoutParams(lParams);
  501 + }
  502 +
  503 + private void toMsgUserLayout(final ToUserMsgViewHolder holder, final ChatMessageBean tbub, final int position) {
  504 +// holder.headicon.setBackgroundResource(R.mipmap.grzx_tx_s);
  505 +// holder.headicon.setImageDrawable(context.getResources()
  506 +// .getDrawable(R.mipmap.grzx_tx_s));
  507 + if (!TextUtils.isEmpty(parentUrl))
  508 + GlideUtils.showImg(context,holder.headicon,parentUrl);
  509 + else holder.headicon.setImageResource(R.drawable.header_icon);
  510 + /* time */
  511 + if (position != 0) {
  512 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  513 + .getTime());
  514 + if (showTime != null) {
  515 + holder.chat_time.setVisibility(View.VISIBLE);
  516 + holder.chat_time.setText(showTime);
  517 + } else {
  518 + holder.chat_time.setVisibility(View.GONE);
  519 + }
  520 + } else {
  521 + String showTime = getTime(tbub.getTime(), null);
  522 + holder.chat_time.setVisibility(View.VISIBLE);
  523 + holder.chat_time.setText(showTime);
  524 + }
  525 +
  526 + holder.content.setVisibility(View.VISIBLE);
  527 + holder.content.setSpanText(handler, tbub.getUserContent(), isGif);
  528 + }
  529 +
  530 + private void toImgUserLayout(final ToUserImgViewHolder holder, final ChatMessageBean tbub, final int position) {
  531 + if (!TextUtils.isEmpty(parentUrl))
  532 + GlideUtils.showImg(context,holder.headicon,parentUrl);
  533 + else holder.headicon.setImageResource(R.drawable.header_icon);
  534 + switch (tbub.getSendState()) {
  535 + case ChatConst.SENDING:
  536 + an = AnimationUtils.loadAnimation(context,
  537 + R.anim.update_loading_progressbar_anim);
  538 + LinearInterpolator lin = new LinearInterpolator();
  539 + an.setInterpolator(lin);
  540 + an.setRepeatCount(-1);
  541 + holder.sendFailImg
  542 + .setBackgroundResource(R.mipmap.xsearch_loading);
  543 + holder.sendFailImg.startAnimation(an);
  544 + an.startNow();
  545 + holder.sendFailImg.setVisibility(View.VISIBLE);
  546 + break;
  547 +
  548 + case ChatConst.COMPLETED:
  549 + holder.sendFailImg.clearAnimation();
  550 + holder.sendFailImg.setVisibility(View.GONE);
  551 + break;
  552 +
  553 + case ChatConst.SENDERROR:
  554 + holder.sendFailImg.clearAnimation();
  555 + holder.sendFailImg
  556 + .setBackgroundResource(R.mipmap.msg_state_fail_resend_pressed);
  557 + holder.sendFailImg.setVisibility(View.VISIBLE);
  558 + holder.sendFailImg.setOnClickListener(new View.OnClickListener() {
  559 +
  560 + @Override
  561 + public void onClick(View view) {
  562 + // TODO Auto-generated method stub
  563 + if (sendErrorListener != null) {
  564 + sendErrorListener.onClick(position);
  565 + }
  566 + }
  567 +
  568 + });
  569 + break;
  570 + default:
  571 + break;
  572 + }
  573 +// holder.headicon.setImageDrawable(context.getResources()
  574 +// .getDrawable(R.mipmap.grzx_tx_s));
  575 +
  576 + /* time */
  577 + if (position != 0) {
  578 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  579 + .getTime());
  580 + if (showTime != null) {
  581 + holder.chat_time.setVisibility(View.VISIBLE);
  582 + holder.chat_time.setText(showTime);
  583 + } else {
  584 + holder.chat_time.setVisibility(View.GONE);
  585 + }
  586 + } else {
  587 + String showTime = getTime(tbub.getTime(), null);
  588 + holder.chat_time.setVisibility(View.VISIBLE);
  589 + holder.chat_time.setText(showTime);
  590 + }
  591 +
  592 +// if (isPicRefresh) {
  593 + holder.image_group.setVisibility(View.VISIBLE);
  594 + final String imageSrc = tbub.getImageLocal() == null ? "" : tbub
  595 + .getImageLocal();
  596 + final String imageUrlSrc = tbub.getImageUrl() == null ? "" : tbub
  597 + .getImageUrl();
  598 + final String imageIconUrl = tbub.getImageIconUrl() == null ? ""
  599 + : tbub.getImageIconUrl();
  600 + File file = new File(imageSrc);
  601 + final boolean hasLocal = !imageSrc.equals("")
  602 + && FileSaveUtil.isFileExists(file);
  603 + int res;
  604 + res = R.drawable.chatto_bg_focused;
  605 +// Glide.with(context).load(imageSrc).transform(new CustomShapeTransformation(context, res)).into(holder.image_Msg);
  606 + Glide.with(context).load(imageSrc).placeholder(R.mipmap.cygs_cs).transform(new CustomShapeTransformation(context, res)).into(holder.image_Msg);
  607 +
  608 + holder.image_Msg.setOnClickListener(new View.OnClickListener() {
  609 +
  610 + @Override
  611 + public void onClick(View view) {
  612 + // TODO Auto-generated method stub
  613 + stopPlayVoice();
  614 + Intent intent = new Intent(context, ImageViewActivity.class);
  615 + intent.putStringArrayListExtra("images", imageList);
  616 + intent.putExtra("clickedIndex", imagePosition.get(position));
  617 + context.startActivity(intent);
  618 + }
  619 +
  620 + });
  621 +// }
  622 + }
  623 +
  624 + private void toVoiceUserLayout(final ToUserVoiceViewHolder holder, final ChatMessageBean tbub, final int position) {
  625 + if (!TextUtils.isEmpty(parentUrl))
  626 + GlideUtils.showImg(context,holder.headicon,parentUrl);
  627 + else holder.headicon.setImageResource(R.drawable.header_icon);
  628 + switch (tbub.getSendState()) {
  629 + case ChatConst.SENDING:
  630 + an = AnimationUtils.loadAnimation(context,
  631 + R.anim.update_loading_progressbar_anim);
  632 + LinearInterpolator lin = new LinearInterpolator();
  633 + an.setInterpolator(lin);
  634 + an.setRepeatCount(-1);
  635 + holder.sendFailImg
  636 + .setBackgroundResource(R.mipmap.xsearch_loading);
  637 + holder.sendFailImg.startAnimation(an);
  638 + an.startNow();
  639 + holder.sendFailImg.setVisibility(View.VISIBLE);
  640 + break;
  641 +
  642 + case ChatConst.COMPLETED:
  643 + holder.sendFailImg.clearAnimation();
  644 + holder.sendFailImg.setVisibility(View.GONE);
  645 + break;
  646 +
  647 + case ChatConst.SENDERROR:
  648 + holder.sendFailImg.clearAnimation();
  649 + holder.sendFailImg
  650 + .setBackgroundResource(R.mipmap.msg_state_fail_resend_pressed);
  651 + holder.sendFailImg.setVisibility(View.VISIBLE);
  652 + holder.sendFailImg.setOnClickListener(new View.OnClickListener() {
  653 +
  654 + @Override
  655 + public void onClick(View view) {
  656 + // TODO Auto-generated method stub
  657 + if (sendErrorListener != null) {
  658 + sendErrorListener.onClick(position);
  659 + }
  660 + }
  661 +
  662 + });
  663 + break;
  664 + default:
  665 + break;
  666 + }
  667 +// holder.headicon.setImageDrawable(context.getResources()
  668 +// .getDrawable(R.mipmap.grzx_tx_s));
  669 +
  670 + /* time */
  671 + if (position != 0) {
  672 + String showTime = getTime(tbub.getTime(), userList.get(position - 1)
  673 + .getTime());
  674 + if (showTime != null) {
  675 + holder.chat_time.setVisibility(View.VISIBLE);
  676 + holder.chat_time.setText(showTime);
  677 + } else {
  678 + holder.chat_time.setVisibility(View.GONE);
  679 + }
  680 + } else {
  681 + String showTime = getTime(tbub.getTime(), null);
  682 + holder.chat_time.setVisibility(View.VISIBLE);
  683 + holder.chat_time.setText(showTime);
  684 + }
  685 + holder.voice_group.setVisibility(View.VISIBLE);
  686 + if (holder.receiver_voice_unread != null)
  687 + holder.receiver_voice_unread.setVisibility(View.GONE);
  688 + if (holder.receiver_voice_unread != null && unReadPosition != null) {
  689 + for (String unRead : unReadPosition) {
  690 + if (unRead.equals(position + "")) {
  691 + holder.receiver_voice_unread
  692 + .setVisibility(View.VISIBLE);
  693 + break;
  694 + }
  695 + }
  696 + }
  697 + AnimationDrawable drawable;
  698 + holder.voice_anim.setId(position);
  699 + if (position == voicePlayPosition) {
  700 + holder.voice_anim.setBackgroundResource(R.mipmap.adj);
  701 + holder.voice_anim
  702 + .setBackgroundResource(R.drawable.voice_play_send);
  703 + drawable = (AnimationDrawable) holder.voice_anim
  704 + .getBackground();
  705 + drawable.start();
  706 + } else {
  707 + holder.voice_anim.setBackgroundResource(R.mipmap.adj);
  708 + }
  709 + holder.voice_group.setOnClickListener(new View.OnClickListener() {
  710 +
  711 + @Override
  712 + public void onClick(View v) {
  713 + // TODO Auto-generated method stub
  714 + if (holder.receiver_voice_unread != null)
  715 + holder.receiver_voice_unread.setVisibility(View.GONE);
  716 + holder.voice_anim.setBackgroundResource(R.mipmap.adj);
  717 + stopPlayVoice();
  718 + voicePlayPosition = holder.voice_anim.getId();
  719 + AnimationDrawable drawable;
  720 + holder.voice_anim
  721 + .setBackgroundResource(R.drawable.voice_play_send);
  722 + drawable = (AnimationDrawable) holder.voice_anim
  723 + .getBackground();
  724 + drawable.start();
  725 + String voicePath = tbub.getUserVoiceUrl() == null ? ""
  726 + : tbub.getUserVoiceUrl();
  727 + if (voiceIsRead != null) {
  728 + voiceIsRead.voiceOnClick(position);
  729 + }
  730 + MediaManager.playSound(voicePath,
  731 + new MediaPlayer.OnCompletionListener() {
  732 +
  733 + @Override
  734 + public void onCompletion(MediaPlayer mp) {
  735 + voicePlayPosition = -1;
  736 + holder.voice_anim
  737 + .setBackgroundResource(R.mipmap.adj);
  738 + }
  739 + });
  740 + }
  741 +
  742 + });
  743 + float voiceTime = tbub.getUserVoiceTime();
  744 + BigDecimal b = new BigDecimal(voiceTime);
  745 + float f1 = b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
  746 + holder.voice_time.setText(f1 + "\"");
  747 + ViewGroup.LayoutParams lParams = holder.voice_image
  748 + .getLayoutParams();
  749 + lParams.width = (int) (mMinItemWith + mMaxItemWith / 60f
  750 + * tbub.getUserVoiceTime());
  751 + holder.voice_image.setLayoutParams(lParams);
  752 + }
  753 +
  754 + @SuppressLint("SimpleDateFormat")
  755 + public String getTime(String time, String before) {
  756 + String show_time = null;
  757 + if (before != null) {
  758 + try {
  759 + DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  760 + java.util.Date now = df.parse(time);
  761 + java.util.Date date = df.parse(before);
  762 + long l = now.getTime() - date.getTime();
  763 + long day = l / (24 * 60 * 60 * 1000);
  764 + long hour = (l / (60 * 60 * 1000) - day * 24);
  765 + long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
  766 + if (min >= 1) {
  767 + show_time = time.substring(11);
  768 + }
  769 + } catch (Exception e) {
  770 + e.printStackTrace();
  771 + }
  772 + } else {
  773 + show_time = time.substring(11);
  774 + }
  775 + String getDay = getDay(time);
  776 + if (show_time != null && getDay != null)
  777 + show_time = getDay + " " + show_time;
  778 + return show_time;
  779 + }
  780 +
  781 + @SuppressLint("SimpleDateFormat")
  782 + public static String returnTime() {
  783 + SimpleDateFormat sDateFormat = new SimpleDateFormat(
  784 + "yyyy-MM-dd HH:mm:ss");
  785 + String date = sDateFormat.format(new java.util.Date());
  786 + return date;
  787 + }
  788 +
  789 + @SuppressLint("SimpleDateFormat")
  790 + public String getDay(String time) {
  791 + String showDay = null;
  792 + String nowTime = returnTime();
  793 + try {
  794 + DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  795 + java.util.Date now = df.parse(nowTime);
  796 + java.util.Date date = df.parse(time);
  797 + long l = now.getTime() - date.getTime();
  798 + long day = l / (24 * 60 * 60 * 1000);
  799 + if (day >= 365) {
  800 + showDay = time.substring(0, 10);
  801 + } else if (day >= 1 && day < 365) {
  802 + showDay = time.substring(5, 10);
  803 + }
  804 + } catch (Exception e) {
  805 + e.printStackTrace();
  806 + }
  807 + return showDay;
  808 + }
  809 +
  810 + public static Bitmap getLoacalBitmap(String url) {
  811 + try {
  812 + ByteArrayOutputStream out;
  813 + FileInputStream fis = new FileInputStream(url);
  814 + BufferedInputStream bis = new BufferedInputStream(fis);
  815 + out = new ByteArrayOutputStream();
  816 + @SuppressWarnings("unused")
  817 + int hasRead = 0;
  818 + byte[] buffer = new byte[1024 * 2];
  819 + while ((hasRead = bis.read(buffer)) > 0) {
  820 + // 读出多少数据,向输出流中写入多少
  821 + out.write(buffer);
  822 + out.flush();
  823 + }
  824 + out.close();
  825 + fis.close();
  826 + bis.close();
  827 + byte[] data = out.toByteArray();
  828 + // 长宽减半
  829 + BitmapFactory.Options opts = new BitmapFactory.Options();
  830 + opts.inSampleSize = 3;
  831 + return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
  832 + } catch (FileNotFoundException e) {
  833 + e.printStackTrace();
  834 + return null;
  835 + } catch (IOException e) {
  836 + // TODO Auto-generated catch block
  837 + e.printStackTrace();
  838 + return null;
  839 + }
  840 + }
  841 +
  842 + public void stopPlayVoice() {
  843 + if (voicePlayPosition != -1) {
  844 + View voicePlay = (View) ((Activity) context)
  845 + .findViewById(voicePlayPosition);
  846 + if (voicePlay != null) {
  847 + if (getItemViewType(voicePlayPosition) == FROM_USER_VOICE) {
  848 + voicePlay
  849 + .setBackgroundResource(R.mipmap.receiver_voice_node_playing003);
  850 + } else {
  851 + voicePlay.setBackgroundResource(R.mipmap.adj);
  852 + }
  853 + }
  854 + MediaManager.pause();
  855 + voicePlayPosition = -1;
  856 + }
  857 + }
  858 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/activity/chartroom/fragment/ImageViewFragment.java 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +package com.shunzhi.parent.ui.activity.chartroom.fragment;
  2 +
  3 +import android.graphics.Bitmap;
  4 +import android.graphics.BitmapFactory;
  5 +import android.support.v4.app.Fragment;
  6 +import android.view.View;
  7 +import android.view.View.OnClickListener;
  8 +import android.widget.ProgressBar;
  9 +
  10 +import com.bumptech.glide.Glide;
  11 +import com.bumptech.glide.request.animation.GlideAnimation;
  12 +import com.bumptech.glide.request.target.SimpleTarget;
  13 +import com.polites.android.GestureImageView;
  14 +import com.shunzhi.parent.R;
  15 +
  16 +public class ImageViewFragment extends Fragment {
  17 + private String imageUrl;
  18 + private ProgressBar loadBar;
  19 + private GestureImageView imageGiv;
  20 +
  21 + public View onCreateView(android.view.LayoutInflater inflater,
  22 + android.view.ViewGroup container,
  23 + android.os.Bundle savedInstanceState) {
  24 + View view = inflater.inflate(R.layout.layout_images_view_item, container,
  25 + false);
  26 + init(view);
  27 + loadImage(imageUrl);
  28 + return view;
  29 + }
  30 +
  31 + private void init(View mView) {
  32 + loadBar = (ProgressBar) mView.findViewById(R.id.imageView_loading_pb);
  33 + imageGiv = (GestureImageView) mView
  34 + .findViewById(R.id.imageView_item_giv);
  35 + imageGiv.setOnClickListener(new OnClickListener() {
  36 +
  37 + @Override
  38 + public void onClick(View v) {
  39 + getActivity().finish();
  40 + }
  41 + });
  42 + }
  43 +
  44 + public void loadImage(String url) {
  45 + if (url.startsWith("http://")) {
  46 + Glide.with(this).load(url).asBitmap().into(new SimpleTarget<Bitmap>() {
  47 + @Override
  48 + public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
  49 + if (resource != null) {
  50 + imageGiv.setImageBitmap(resource);
  51 + loadBar.setVisibility(View.GONE);
  52 + imageGiv.setVisibility(View.VISIBLE);
  53 + }
  54 + }
  55 + });
  56 + } else {
  57 + imageGiv.setImageBitmap(BitmapFactory.decodeFile(url));
  58 + loadBar.setVisibility(View.GONE);
  59 + imageGiv.setVisibility(View.VISIBLE);
  60 + }
  61 + }
  62 +
  63 + public String getImageUrl() {
  64 + return imageUrl;
  65 + }
  66 +
  67 + public void setImageUrl(String imageUrl) {
  68 + this.imageUrl = imageUrl;
  69 + }
  70 +
  71 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/activity/message/LeaverMessagesActivity.java 0 → 100644
... ... @@ -0,0 +1,42 @@
  1 +package com.shunzhi.parent.ui.activity.message;
  2 +
  3 +import android.content.Intent;
  4 +import android.support.annotation.NonNull;
  5 +import android.support.v7.app.AppCompatActivity;
  6 +import android.os.Bundle;
  7 +
  8 +import com.share.mvpsdk.base.BasePresenter;
  9 +import com.share.mvpsdk.base.activity.BaseMVPCompatActivity;
  10 +import com.shunzhi.parent.R;
  11 +import com.shunzhi.parent.contract.leavermessage.LeaverMessage;
  12 +import com.shunzhi.parent.contract.leavermessage.LeaverMessageContract;
  13 +import com.shunzhi.parent.presenter.leavermessage.LeaverMessagePresenter;
  14 +import com.shunzhi.parent.ui.activity.chartroom.RecyclerViewChatActivity;
  15 +
  16 +import java.util.List;
  17 +
  18 +public class LeaverMessagesActivity extends BaseMVPCompatActivity<LeaverMessageContract.MyLeaverMessagePresenter,LeaverMessageContract.ILeaverMessageModel>
  19 +implements LeaverMessageContract.ILeverMessageView{
  20 +
  21 + @Override
  22 + protected void initView(Bundle savedInstanceState) {
  23 + Intent intent = new Intent(this, RecyclerViewChatActivity.class);
  24 + startActivity(intent);
  25 + }
  26 +
  27 + @Override
  28 + protected int getLayoutId() {
  29 + return R.layout.activity_leaver_messages;
  30 + }
  31 +
  32 + @NonNull
  33 + @Override
  34 + public BasePresenter initPresenter() {
  35 + return LeaverMessagePresenter.newInstance();
  36 + }
  37 +
  38 + @Override
  39 + public void ShowLeaverMessageList(List<LeaverMessage> leaverMessageList) {
  40 +
  41 + }
  42 +}
... ...
app/src/main/java/com/shunzhi/parent/ui/fragment/report/ChengZhangFragment.java
... ... @@ -40,6 +40,7 @@ import com.shunzhi.parent.ui.activity.BankActivity;
40 40 import com.shunzhi.parent.ui.activity.MyChildActivity;
41 41 import com.shunzhi.parent.ui.activity.apply.ApplyReplaceCardActivity;
42 42 import com.shunzhi.parent.ui.activity.apply.ApplySigninActivity;
  43 +import com.shunzhi.parent.ui.activity.chartroom.RecyclerViewChatActivity;
43 44 import com.shunzhi.parent.ui.activity.mywebview.WebViewActivity;
44 45  
45 46 import java.util.List;
... ... @@ -82,7 +83,7 @@ public class ChengZhangFragment extends BaseMVPCompatFragment&lt;ReportContract.Rep
82 83  
83 84 private String type = "", jsonStr = "";
84 85  
85   - LinearLayout layout_chengzhang, layout_report, layout_kaoqin, layout_buka, layout_qingjia;
  86 + LinearLayout layout_chengzhang, layout_report, layout_kaoqin, layout_buka, layout_qingjia,layout_liuyan;
86 87  
87 88 RelativeLayout rl_noData;
88 89  
... ... @@ -101,6 +102,7 @@ public class ChengZhangFragment extends BaseMVPCompatFragment&lt;ReportContract.Rep
101 102 layout_kaoqin = view.findViewById(R.id.layout_kaoqin);
102 103 layout_buka = view.findViewById(R.id.layout_buka);
103 104 layout_qingjia = view.findViewById(R.id.layout_qingjia);
  105 + layout_liuyan=view.findViewById(R.id.layout_liuyan);
104 106 tvNoData = view.findViewById(R.id.tvNoData);
105 107 calendarView_month_mode = view.findViewById(R.id.calendarView_month_mode);
106 108 monthWeekMaterialCalendarView = view.findViewById(R.id.slidelayout);
... ... @@ -108,6 +110,7 @@ public class ChengZhangFragment extends BaseMVPCompatFragment&lt;ReportContract.Rep
108 110 layout_kaoqin.setOnClickListener(this);
109 111 layout_buka.setOnClickListener(this);
110 112 layout_qingjia.setOnClickListener(this);
  113 + layout_liuyan.setOnClickListener(this);
111 114 type = getArguments().getString("type");
112 115 jsonStr = getArguments().getString("jsonStr");
113 116 show();
... ... @@ -200,6 +203,13 @@ public class ChengZhangFragment extends BaseMVPCompatFragment&lt;ReportContract.Rep
200 203 case R.id.layout_qingjia:
201 204 ToastUtils.showToast("正在努力开发中,敬请期待");
202 205 break;
  206 + case R.id.layout_liuyan://留言
  207 + Bundle bundle = new Bundle();
  208 + bundle.putString("childName",childBean.getStudentName());
  209 + bundle.putString("childPhoto",childBean.getPhoto());
  210 + startNewActivity(RecyclerViewChatActivity.class,bundle);
  211 +// startActivity(new Intent(getActivity(),RecyclerViewChatActivity.class));
  212 + break;
203 213 }
204 214 }
205 215  
... ...
app/src/main/res/anim/update_loading_progressbar_anim.xml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<rotate xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:drawable="@mipmap/xsearch_loading"
  4 + android:fromDegrees="0"
  5 + android:toDegrees="359"
  6 + android:pivotX="50%"
  7 + android:pivotY="50%"
  8 + android:duration="700"
  9 + />
0 10 \ No newline at end of file
... ...
app/src/main/res/drawable-xhdpi/chatfrom_bg_focused.9.png 0 → 100644

903 Bytes

app/src/main/res/drawable-xhdpi/chatto_bg_focused.9.png 0 → 100644

1 KB

app/src/main/res/drawable-xhdpi/xmxq_tc_bj.9.png 0 → 100644

135 Bytes

app/src/main/res/drawable/frame_bg.xml 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <solid android:color="@android:color/white" />
  4 +
  5 + <stroke
  6 + android:width="1dp"
  7 + android:color="@color/light_gray_2" />
  8 +
  9 + <padding
  10 + android:bottom="1dp"
  11 + android:left="1dp"
  12 + android:right="1dp"
  13 + android:top="1dp" />
  14 + <!--
  15 + <corners android:topLeftRadius="5dp" android:topRightRadius="5dp"
  16 + android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/> -->
  17 +</shape>
0 18 \ No newline at end of file
... ...
app/src/main/res/drawable/frame_blue_to_thin_bg.xml 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<selector xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:state_pressed="true"><shape android:shape="rectangle">
  5 + <solid android:color="@color/light_blue2" />
  6 +
  7 + <stroke android:width="1dp" android:color="@color/light_blue2" />
  8 +
  9 + <padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
  10 +
  11 + <corners android:radius="2dp" />
  12 + </shape></item>
  13 + <item android:state_focused="true"><shape android:shape="rectangle">
  14 + <solid android:color="@color/light_blue2" />
  15 +
  16 + <stroke android:width="1dp" android:color="@color/light_blue2" />
  17 +
  18 + <padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
  19 +
  20 + <corners android:radius="2dp" />
  21 + </shape></item>
  22 + <item><shape android:shape="rectangle">
  23 + <solid android:color="@color/light_blue1" />
  24 +
  25 + <stroke android:width="1dp" android:color="@color/light_blue1" />
  26 +
  27 + <padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
  28 +
  29 + <corners android:radius="2dp" />
  30 + </shape></item>
  31 +
  32 +</selector>
0 33 \ No newline at end of file
... ...
app/src/main/res/drawable/voice_play_receiver.xml 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
  3 +
  4 + <item
  5 + android:drawable="@mipmap/receiver_voice_node_playing000"
  6 + android:duration="300">
  7 + </item>
  8 +
  9 + <item
  10 + android:drawable="@mipmap/receiver_voice_node_playing001"
  11 + android:duration="300">
  12 + </item>
  13 +
  14 + <item
  15 + android:drawable="@mipmap/receiver_voice_node_playing002"
  16 + android:duration="300">
  17 + </item>
  18 +
  19 + <item
  20 + android:drawable="@mipmap/receiver_voice_node_playing003"
  21 + android:duration="300">
  22 + </item>
  23 +
  24 +</animation-list>
0 25 \ No newline at end of file
... ...
app/src/main/res/drawable/voice_play_send.xml 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
  3 +
  4 + <item
  5 + android:drawable="@mipmap/v_anim1"
  6 + android:duration="300">
  7 + </item>
  8 +
  9 + <item
  10 + android:drawable="@mipmap/v_anim2"
  11 + android:duration="300">
  12 + </item>
  13 +
  14 + <item
  15 + android:drawable="@mipmap/v_anim3"
  16 + android:duration="300">
  17 + </item>
  18 +
  19 +</animation-list>
0 20 \ No newline at end of file
... ...
app/src/main/res/layout/activity_images_view.xml 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical" >
  6 + <android.support.v4.view.ViewPager
  7 + android:id="@+id/images_vp"
  8 + android:layout_width="wrap_content"
  9 + android:layout_height="wrap_content">
  10 +
  11 + </android.support.v4.view.ViewPager>
  12 + <LinearLayout
  13 + android:id="@+id/imageView_title_ll"
  14 + android:layout_width="match_parent"
  15 + android:layout_height="wrap_content"
  16 + android:layout_alignParentTop="true"
  17 + android:orientation="horizontal"
  18 + android:background="@color/zz_half_transparent"
  19 + android:paddingTop="5dp"
  20 + android:paddingBottom="5dp"
  21 + android:gravity="center">
  22 + <TextView
  23 + android:id="@+id/imageView_current_tv"
  24 + android:layout_width="wrap_content"
  25 + android:layout_height="wrap_content"
  26 + android:text="1"
  27 + android:textSize="18sp"
  28 + android:textColor="@color/white"/>
  29 + <TextView
  30 + android:id="@+id/imageView_total_tv"
  31 + android:layout_width="wrap_content"
  32 + android:layout_height="wrap_content"
  33 + android:text="/8"
  34 + android:textSize="18sp"
  35 + android:textColor="@color/white"/>
  36 + </LinearLayout>
  37 +</RelativeLayout>
... ...
app/src/main/res/layout/activity_leaver_messages.xml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + tools:context=".ui.activity.message.LeaverMessagesActivity">
  8 +
  9 +</android.support.constraint.ConstraintLayout>
0 10 \ No newline at end of file
... ...
app/src/main/res/layout/layout_chengzhang.xml
... ... @@ -105,4 +105,43 @@
105 105  
106 106 </LinearLayout>
107 107  
  108 +
  109 + <TextView
  110 + android:layout_width="wrap_content"
  111 + android:layout_height="wrap_content"
  112 + android:layout_gravity="center_horizontal"
  113 + android:layout_marginTop="@dimen/size_dp_10"
  114 + android:text="云视窗"
  115 + android:textColor="@color/textColor"
  116 + android:textSize="@dimen/size_dp_16" />
  117 +
  118 + <LinearLayout
  119 + android:id="@+id/layout_liuyan"
  120 + android:layout_width="match_parent"
  121 + android:layout_height="?android:actionBarSize"
  122 + android:layout_marginLeft="@dimen/size_dp_10"
  123 + android:layout_marginRight="@dimen/size_dp_10"
  124 + android:layout_marginTop="@dimen/size_dp_10"
  125 + android:background="@drawable/shape_corner_bg"
  126 + android:orientation="horizontal">
  127 +
  128 + <ImageView
  129 + android:layout_width="wrap_content"
  130 + android:layout_height="wrap_content"
  131 + android:layout_gravity="center_vertical"
  132 + android:layout_margin="@dimen/size_dp_5"
  133 + android:scaleType="fitXY"
  134 + android:src="@drawable/kaoqin" />
  135 +
  136 + <TextView
  137 + android:layout_width="wrap_content"
  138 + android:layout_height="wrap_content"
  139 + android:layout_gravity="center_vertical"
  140 + android:layout_marginLeft="@dimen/size_dp_15"
  141 + android:text="留言板"
  142 + android:textColor="@color/textColor"
  143 + android:textSize="@dimen/size_dp_16" />
  144 +
  145 + </LinearLayout>
  146 +
108 147 </LinearLayout>
109 148 \ No newline at end of file
... ...
app/src/main/res/layout/layout_imagefrom_list_item.xml 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:padding="5dp">
  6 +
  7 + <TextView
  8 + android:id="@+id/chat_time"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:layout_centerHorizontal="true"
  13 + android:textColor="@color/light_gray_6"
  14 + android:textSize="10sp"
  15 + android:visibility="gone" />
  16 +
  17 + <ImageView
  18 + android:id="@+id/tb_other_user_icon"
  19 + android:layout_width="50dp"
  20 + android:layout_height="50dp"
  21 + android:layout_alignParentLeft="true"
  22 + android:layout_below="@id/chat_time" />
  23 +
  24 + <LinearLayout
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_below="@id/chat_time"
  28 + android:layout_margin="5dp"
  29 + android:layout_toRightOf="@+id/tb_other_user_icon"
  30 + android:orientation="horizontal">
  31 +
  32 + <com.shunzhi.mychartlibrary.widget.BubbleImageView
  33 + android:id="@+id/image_message"
  34 + android:layout_width="wrap_content"
  35 + android:layout_height="wrap_content"
  36 + android:scaleType="centerCrop" />
  37 + </LinearLayout>
  38 +
  39 +</RelativeLayout>
0 40 \ No newline at end of file
... ...
app/src/main/res/layout/layout_images_view_item.xml 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout
  3 + xmlns:android="http://schemas.android.com/apk/res/android"
  4 + xmlns:gesture-image="http://schemas.polites.com/android"
  5 + android:id="@+id/image_view_rl"
  6 + android:layout_width="fill_parent"
  7 + android:layout_height="fill_parent"
  8 + android:orientation="vertical"
  9 + android:background="@color/zz_half_transparent">
  10 +
  11 + <ProgressBar
  12 + android:id="@+id/imageView_loading_pb"
  13 + android:layout_width="wrap_content"
  14 + android:layout_height="wrap_content"
  15 + android:layout_centerInParent="true"
  16 + />
  17 +
  18 + <com.polites.android.GestureImageView
  19 + android:id="@+id/imageView_item_giv"
  20 + android:layout_width="fill_parent"
  21 + android:layout_height="fill_parent"
  22 + gesture-image:min-scale="0.75"
  23 + gesture-image:max-scale="10.0"
  24 + android:visibility="gone"/>
  25 +</RelativeLayout>
... ...
app/src/main/res/layout/layout_imageto_list_item.xml 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:padding="5dp">
  6 +
  7 + <TextView
  8 + android:id="@+id/mychat_time"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:layout_centerHorizontal="true"
  13 + android:textColor="@color/light_gray_6"
  14 + android:textSize="10sp"
  15 + android:visibility="gone" />
  16 +
  17 + <ImageView
  18 + android:id="@+id/tb_my_user_icon"
  19 + android:layout_width="50dp"
  20 + android:layout_height="50dp"
  21 + android:layout_alignParentRight="true"
  22 + android:layout_below="@id/mychat_time" />
  23 +
  24 + <LinearLayout
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_below="@id/mychat_time"
  28 + android:layout_toLeftOf="@+id/tb_my_user_icon"
  29 + android:orientation="horizontal">
  30 +
  31 + <ImageView
  32 + android:id="@+id/mysend_fail_img"
  33 + android:layout_width="25dp"
  34 + android:layout_height="25dp"
  35 + android:layout_gravity="center_vertical"
  36 + android:background="@mipmap/msg_state_fail_resend_pressed" />
  37 +
  38 + <LinearLayout
  39 + android:id="@+id/image_group"
  40 + android:layout_width="wrap_content"
  41 + android:layout_height="wrap_content"
  42 + android:layout_margin="5dp"
  43 + android:orientation="vertical"
  44 + android:visibility="gone">
  45 +
  46 + <com.shunzhi.mychartlibrary.widget.BubbleImageView
  47 + android:id="@+id/image_message"
  48 + android:layout_width="wrap_content"
  49 + android:layout_height="wrap_content"
  50 + android:scaleType="centerCrop" />
  51 + </LinearLayout>
  52 + </LinearLayout>
  53 +
  54 +</RelativeLayout>
0 55 \ No newline at end of file
... ...
app/src/main/res/layout/layout_msgfrom_list_item.xml 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:padding="5dp">
  6 +
  7 + <TextView
  8 + android:id="@+id/chat_time"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:layout_centerHorizontal="true"
  13 + android:textColor="@color/light_gray_6"
  14 + android:textSize="10sp"
  15 + android:visibility="gone" />
  16 +
  17 + <ImageView
  18 + android:id="@+id/tb_other_user_icon"
  19 + android:layout_width="50dp"
  20 + android:layout_height="50dp"
  21 + android:layout_alignParentLeft="true"
  22 + android:layout_below="@id/chat_time" />
  23 +
  24 + <LinearLayout
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_below="@id/chat_time"
  28 + android:layout_toRightOf="@+id/tb_other_user_icon"
  29 + android:orientation="horizontal">
  30 +
  31 + <com.shunzhi.mychartlibrary.widget.GifTextView
  32 + android:id="@+id/content"
  33 + android:layout_width="wrap_content"
  34 + android:layout_height="wrap_content"
  35 + android:layout_margin="5dp"
  36 + android:background="@drawable/chatfrom_bg_focused"
  37 + android:textSize="16sp" />
  38 + </LinearLayout>
  39 +
  40 +</RelativeLayout>
0 41 \ No newline at end of file
... ...
app/src/main/res/layout/layout_msgto_list_item.xml 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:padding="5dp">
  6 +
  7 + <TextView
  8 + android:id="@+id/mychat_time"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:layout_centerHorizontal="true"
  13 + android:textColor="@color/light_gray_6"
  14 + android:textSize="10sp"
  15 + android:visibility="gone" />
  16 +
  17 + <ImageView
  18 + android:id="@+id/tb_my_user_icon"
  19 + android:layout_width="50dp"
  20 + android:layout_height="50dp"
  21 + android:layout_alignParentRight="true"
  22 + android:layout_below="@id/mychat_time" />
  23 +
  24 + <LinearLayout
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_below="@id/mychat_time"
  28 + android:layout_toLeftOf="@+id/tb_my_user_icon"
  29 + android:orientation="horizontal">
  30 +
  31 + <com.shunzhi.mychartlibrary.widget.GifTextView
  32 + android:id="@+id/mycontent"
  33 + android:layout_width="wrap_content"
  34 + android:layout_height="wrap_content"
  35 + android:layout_margin="5dp"
  36 + android:background="@drawable/chatto_bg_focused"
  37 + android:textColor="@color/white"
  38 + android:textSize="16sp" />
  39 + </LinearLayout>
  40 +
  41 +</RelativeLayout>
0 42 \ No newline at end of file
... ...
app/src/main/res/layout/layout_pull_to_refresh.xml 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical" >
  6 + <TextView
  7 + android:id="@+id/pull_text"
  8 + android:layout_width="match_parent"
  9 + android:layout_height="wrap_content"
  10 + android:text="pull to refresh!"
  11 + />
  12 + <com.maxi.chatdemo.widget.pulltorefresh.PullToRefreshRecyclerView
  13 + android:id="@+id/pull_list"
  14 + android:layout_width="match_parent"
  15 + android:layout_height="match_parent"
  16 + android:background="#ffffff"
  17 + />
  18 +
  19 +</LinearLayout>
0 20 \ No newline at end of file
... ...
app/src/main/res/layout/layout_voicefrom_list_item.xml 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:padding="5dp">
  6 +
  7 + <TextView
  8 + android:id="@+id/chat_time"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:layout_centerHorizontal="true"
  13 + android:textColor="@color/light_gray_6"
  14 + android:textSize="10sp"
  15 + android:visibility="gone" />
  16 +
  17 + <ImageView
  18 + android:id="@+id/tb_other_user_icon"
  19 + android:layout_width="50dp"
  20 + android:layout_height="50dp"
  21 + android:layout_alignParentLeft="true"
  22 + android:layout_below="@id/chat_time" />
  23 +
  24 + <LinearLayout
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_below="@id/chat_time"
  28 + android:layout_toRightOf="@+id/tb_other_user_icon"
  29 + android:orientation="horizontal">
  30 +
  31 + <LinearLayout
  32 + android:id="@+id/voice_group"
  33 + android:layout_width="wrap_content"
  34 + android:layout_height="wrap_content"
  35 + android:layout_margin="5dp"
  36 + android:orientation="horizontal"
  37 + android:visibility="gone">
  38 +
  39 + <FrameLayout
  40 + android:id="@+id/voice_receiver_image"
  41 + android:layout_width="wrap_content"
  42 + android:layout_height="wrap_content"
  43 + android:layout_gravity="center"
  44 + android:background="@drawable/chatfrom_bg_focused">
  45 +
  46 + <View
  47 + android:id="@+id/id_receiver_recorder_anim"
  48 + android:layout_width="15dp"
  49 + android:layout_height="15dp"
  50 + android:layout_gravity="center_vertical|left"
  51 + android:background="@mipmap/receiver_voice_node_playing003" />
  52 +
  53 + <View
  54 + android:id="@+id/receiver_voice_unread"
  55 + android:layout_width="10dp"
  56 + android:layout_height="10dp"
  57 + android:layout_gravity="center_vertical|right"
  58 + android:background="@mipmap/msg_chat_voice_unread" />
  59 + </FrameLayout>
  60 +
  61 + <TextView
  62 + android:id="@+id/voice_time"
  63 + android:layout_width="wrap_content"
  64 + android:layout_height="wrap_content"
  65 + android:layout_gravity="center_vertical"
  66 + android:textColor="@color/middle_gray_1" />
  67 + </LinearLayout>
  68 +
  69 + </LinearLayout>
  70 +
  71 +</RelativeLayout>
0 72 \ No newline at end of file
... ...
app/src/main/res/layout/layout_voiceto_list_item.xml 0 → 100644
... ... @@ -0,0 +1,70 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:padding="5dp">
  6 +
  7 + <TextView
  8 + android:id="@+id/mychat_time"
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentTop="true"
  12 + android:layout_centerHorizontal="true"
  13 + android:textColor="@color/light_gray_6"
  14 + android:textSize="10sp"
  15 + android:visibility="gone" />
  16 +
  17 + <ImageView
  18 + android:id="@+id/tb_my_user_icon"
  19 + android:layout_width="50dp"
  20 + android:layout_height="50dp"
  21 + android:layout_alignParentRight="true"
  22 + android:layout_below="@id/mychat_time" />
  23 +
  24 + <LinearLayout
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_below="@id/mychat_time"
  28 + android:layout_toLeftOf="@+id/tb_my_user_icon"
  29 + android:orientation="horizontal">
  30 +
  31 + <ImageView
  32 + android:id="@+id/mysend_fail_img"
  33 + android:layout_width="25dp"
  34 + android:layout_height="25dp"
  35 + android:layout_gravity="center_vertical"
  36 + android:background="@mipmap/msg_state_fail_resend_pressed" />
  37 +
  38 + <LinearLayout
  39 + android:id="@+id/voice_group"
  40 + android:layout_width="wrap_content"
  41 + android:layout_height="wrap_content"
  42 + android:layout_margin="5dp"
  43 + android:orientation="horizontal"
  44 + android:visibility="gone">
  45 +
  46 + <TextView
  47 + android:id="@+id/voice_time"
  48 + android:layout_width="wrap_content"
  49 + android:layout_height="wrap_content"
  50 + android:layout_gravity="center_vertical"
  51 + android:textColor="@color/middle_gray_1" />
  52 +
  53 + <FrameLayout
  54 + android:id="@+id/voice_image"
  55 + android:layout_width="wrap_content"
  56 + android:layout_height="wrap_content"
  57 + android:layout_gravity="center"
  58 + android:background="@drawable/chatto_bg_focused">
  59 +
  60 + <View
  61 + android:id="@+id/id_recorder_anim"
  62 + android:layout_width="15dp"
  63 + android:layout_height="15dp"
  64 + android:layout_gravity="center_vertical|right"
  65 + android:background="@mipmap/adj" />
  66 + </FrameLayout>
  67 + </LinearLayout>
  68 + </LinearLayout>
  69 +
  70 +</RelativeLayout>
0 71 \ No newline at end of file
... ...
app/src/main/res/mipmap-hdpi/f1.gif 0 → 100644

4.06 KB

app/src/main/res/mipmap-hdpi/f10.gif 0 → 100644

3.79 KB

app/src/main/res/mipmap-hdpi/f11.gif 0 → 100644

7.89 KB

app/src/main/res/mipmap-hdpi/f12.gif 0 → 100644

2.24 KB

app/src/main/res/mipmap-hdpi/f13.gif 0 → 100644

1.74 KB

app/src/main/res/mipmap-hdpi/f14.gif 0 → 100644

1.81 KB

app/src/main/res/mipmap-hdpi/f15.gif 0 → 100644

1.57 KB

app/src/main/res/mipmap-hdpi/f16.gif 0 → 100644

1.42 KB

app/src/main/res/mipmap-hdpi/f17.gif 0 → 100644

7.99 KB

app/src/main/res/mipmap-hdpi/f18.gif 0 → 100644

7.99 KB

app/src/main/res/mipmap-hdpi/f19.gif 0 → 100644

1.81 KB

app/src/main/res/mipmap-hdpi/f2.gif 0 → 100644

1.59 KB

app/src/main/res/mipmap-hdpi/f20.gif 0 → 100644

1.87 KB

app/src/main/res/mipmap-hdpi/f21.gif 0 → 100644

3.02 KB

app/src/main/res/mipmap-hdpi/f22.gif 0 → 100644

1.95 KB

app/src/main/res/mipmap-hdpi/f23.gif 0 → 100644

2.25 KB

app/src/main/res/mipmap-hdpi/f24.gif 0 → 100644

2.43 KB

app/src/main/res/mipmap-hdpi/f25.gif 0 → 100644

3.96 KB

app/src/main/res/mipmap-hdpi/f26.gif 0 → 100644

2.64 KB

app/src/main/res/mipmap-hdpi/f27.gif 0 → 100644

3.34 KB

app/src/main/res/mipmap-hdpi/f28.gif 0 → 100644

4.84 KB

app/src/main/res/mipmap-hdpi/f29.gif 0 → 100644

1.78 KB

app/src/main/res/mipmap-hdpi/f3.gif 0 → 100644

1.81 KB

app/src/main/res/mipmap-hdpi/f30.gif 0 → 100644

7.24 KB

app/src/main/res/mipmap-hdpi/f31.gif 0 → 100644

4.39 KB

app/src/main/res/mipmap-hdpi/f32.gif 0 → 100644

2.13 KB

app/src/main/res/mipmap-hdpi/f33.gif 0 → 100644

1.43 KB

app/src/main/res/mipmap-hdpi/f34.gif 0 → 100644

1.21 KB

app/src/main/res/mipmap-hdpi/f35.gif 0 → 100644

1.68 KB

app/src/main/res/mipmap-hdpi/f36.gif 0 → 100644

1.8 KB

app/src/main/res/mipmap-hdpi/f37.gif 0 → 100644

1.14 KB

app/src/main/res/mipmap-hdpi/f38.gif 0 → 100644

2.54 KB

app/src/main/res/mipmap-hdpi/f39.gif 0 → 100644

1.39 KB

app/src/main/res/mipmap-hdpi/f4.gif 0 → 100644

1.85 KB

app/src/main/res/mipmap-hdpi/f40.gif 0 → 100644

1.28 KB

app/src/main/res/mipmap-hdpi/f5.gif 0 → 100644

1.98 KB

app/src/main/res/mipmap-hdpi/f6.gif 0 → 100644

3.19 KB

app/src/main/res/mipmap-hdpi/f7.gif 0 → 100644

3.9 KB

app/src/main/res/mipmap-hdpi/f8.gif 0 → 100644

4.92 KB

app/src/main/res/mipmap-hdpi/f9.gif 0 → 100644

3.37 KB

app/src/main/res/mipmap-hdpi/ic_launcher.png

2.98 KB | W: | H:

3.34 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
app/src/main/res/mipmap-hdpi/msg_state_fail_resend_pressed.png 0 → 100644

1.72 KB

app/src/main/res/mipmap-hdpi/xsearch_loading.png 0 → 100644

3.01 KB

app/src/main/res/mipmap-xhdpi/adj.png 0 → 100644

828 Bytes

app/src/main/res/mipmap-xhdpi/cygs_cs.png 0 → 100644

414 Bytes

app/src/main/res/mipmap-xhdpi/delete_expression.png 0 → 100644

3.01 KB

app/src/main/res/mipmap-xhdpi/emoji_icon.png 0 → 100644

2.06 KB

app/src/main/res/mipmap-xhdpi/grzx_tx_s.png 0 → 100644

142 KB

app/src/main/res/mipmap-xhdpi/ic_launcher.png

4.46 KB | W: | H:

4.73 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
app/src/main/res/mipmap-xhdpi/msg_chat_voice_unread.png 0 → 100644

1.18 KB

app/src/main/res/mipmap-xhdpi/receiver_voice_node_playing.png 0 → 100644

592 Bytes

app/src/main/res/mipmap-xhdpi/receiver_voice_node_playing000.png 0 → 100644

82 Bytes

app/src/main/res/mipmap-xhdpi/receiver_voice_node_playing001.png 0 → 100644

162 Bytes

app/src/main/res/mipmap-xhdpi/receiver_voice_node_playing002.png 0 → 100644

356 Bytes

app/src/main/res/mipmap-xhdpi/receiver_voice_node_playing003.png 0 → 100644

591 Bytes

app/src/main/res/mipmap-xhdpi/tb_dialog_loading_bg.png 0 → 100644

3.32 KB

app/src/main/res/mipmap-xhdpi/tb_voice1.png 0 → 100644

17.4 KB

app/src/main/res/mipmap-xhdpi/tb_voice2.png 0 → 100644

18.8 KB

app/src/main/res/mipmap-xhdpi/tb_voice3.png 0 → 100644

20.2 KB

app/src/main/res/mipmap-xhdpi/tongbao_hiv.png 0 → 100644

6.92 KB

app/src/main/res/mipmap-xhdpi/v_anim1.png 0 → 100644

14.3 KB

app/src/main/res/mipmap-xhdpi/v_anim2.png 0 → 100644

14.4 KB

app/src/main/res/mipmap-xhdpi/v_anim3.png 0 → 100644

828 Bytes

app/src/main/res/values/colors.xml
... ... @@ -3,7 +3,132 @@
3 3 <color name="colorPrimary">#3F51B5</color>
4 4 <color name="colorPrimaryDark">#303F9F</color>
5 5 <color name="colorAccent">#FF4081</color>
  6 + <color name="three_transparent">#30ffffff</color>
  7 + <color name="black">#000000</color>
  8 + <color name="white">#ffffff</color>
  9 + <color name="light_gray_1">#e5e5e5</color>
  10 + <color name="light_gray_2">#f0f2f6</color>
  11 + <color name="light_gray_3">#fafafa</color>
  12 + <color name="light_gray_4">#f5f5f5</color>
  13 + <color name="light_gray_5">#f3f3f3</color>
  14 + <color name="light_gray_6">#aaaaaa</color>
  15 + <color name="light_gray_7">#f0f0f0</color>
  16 + <color name="light_gray_8">#666666</color>
  17 + <color name="light_gray_9">#f4f5f7</color>
  18 + <color name="light_gray_10">#bfbfbf</color>
  19 + <color name="light_gray_11">#f1f2f6</color>
  20 + <color name="light_gray_12">#333333</color>
  21 + <color name="middle_gray_1">#999999</color>
  22 + <color name="middle_gray_2">#818181</color>
  23 + <color name="dark_gray_1">#051b28</color>
  24 + <color name="dark_gray_2">#848689</color>
  25 + <color name="dark_gray_3">#252525</color>
  26 + <color name="dark_gray_4">#232326</color>
  27 + <color name="dark_gray_5">#f2f4f5</color>
6 28  
  29 + <color name="blue2">#0a85ff</color>
  30 + <color name="blue3">#356cb0</color>
  31 + <color name="blue4">#5795f3</color>
  32 + <color name="blue5">#2297fe</color>
  33 +
  34 + <color name="yellow">#edbb74</color>
  35 + <color name="yellow_1">#ffb802</color>
  36 + <color name="yellow_2">#fff5e5</color>
  37 + <color name="yellow_3">#fd9c00</color>
  38 + <color name="red">#ffdd2727</color> <!-- 酱红色 -->
  39 + <color name="red1">#c82300</color> <!-- 深红色 -->
  40 + <color name="red2">#e64a4b</color>
  41 + <color name="red3">#ff4719</color>
  42 + <color name="red4">#f2426c</color>
  43 + <color name="red5">#ff7870</color>
  44 + <color name="red6">#dd2727</color>
  45 + <color name="red7">#ff4258</color>
  46 + <color name="red8">#e72701</color>
  47 +
  48 + <color name="mjq_red">#ff5757</color>
  49 + <color name="mjq_albumback">#E1E0DE</color>
  50 + <color name="mjq_none_color">#00000000</color>
  51 + <color name="click_bg">#d9d9d9</color>
  52 + <color name="edit_frame_bg">#e9eaec</color>
  53 + <color name="light_blue1">#3097e6</color>
  54 + <color name="light_blue2">#503097e6</color>
  55 + <color name="light_blue3">#dcf4ff</color>
  56 + <color name="light_blue4">#84d4f9</color>
  57 + <color name="light_blue5">#45b1e3</color>
  58 + <color name="light_blue6">#3299e8</color>
  59 + <color name="light_blue7">#1597f2</color>
  60 +
  61 + <color name="zhu_light_blue">#346cb0</color>
  62 +
  63 + <color name="zz_light_blue">#278ff3</color>
  64 + <color name="zz_divider">#e6e6e6</color>
  65 + <color name="zz_divider1">#dedede</color>
  66 + <color name="zz_invest_light_gray">#808080</color>
  67 + <color name="zz_half_transparent">#7f000000</color>
  68 + <color name="black_30_transparent">#48000000</color>
  69 + <color name="black_50_transparent">#50000000</color>
  70 + <color name="zz_seven_transparent">#70ffffff</color>
  71 + <color name="zz_light_gray_6">#ebebeb</color>
  72 + <color name="zz_4_11_16">#bbbbbb</color>
  73 + <color name="zz_gray_22">#222222</color>
  74 + <color name="text_color_gray1">#626262</color>
  75 + <color name="lines_view">#cccccc</color>
  76 + <color name="navpage">#FFE1E8EB</color>
  77 + <color name="dark_yellow_1">#ffb84c</color>
  78 + <color name="dark_white_1">#feeedc</color>
  79 + <color name="hint_red_1">#fadcdc</color>
  80 + <color name="black1">#2f2f2f</color>
  81 + <color name="black2">#656565</color>
  82 + <color name="black3">#595959</color>
  83 + <color name="black4">#343434</color>
  84 + <color name="light_blue_1">#4ca4fe</color>
  85 + <color name="light_blue_2">#14ccca</color>
  86 + <color name="light_red_1">#f26464</color>
  87 + <color name="light_blue">#1597f2</color>
  88 +
  89 + <color name="light_gray_13">#dddddd</color>
  90 + <color name="light_gray_14">#838383</color>
  91 + <color name="light_gray_15">#999999</color>
  92 + <color name="light_gray_16">#f2f5f5</color>
  93 + <color name="light_gray_17">#f8f8f8</color>
  94 + <color name="light_gray_18">#c9c7c3</color>
  95 + <color name="light_gray_19">#b2b2b2</color>
  96 + <color name="light_gray_21">#a3a8ad</color>
  97 + <color name="light_gray_20">#d2d2d2</color>
  98 + <color name="light_gray_22">#b3b3b3</color>
  99 + <color name="light_gray_24">#a5a5a5</color>
  100 + <color name="light_gray_23">#929292</color>
  101 + <color name="light_gray_25">#e0e0e0</color>
  102 + <color name="red_dark">#634444</color>
  103 +
  104 + <item name="subscribe_item_text_color_normal" type="color">@color/default_text</item>
  105 +
  106 + <color name="subscribe_item_text_color_pressed">#ffb9b9b9</color>
  107 + <color name="default_text">#ff454545</color>
  108 + <color name="subscribe_item_text_color_pressed_night">#ff303030</color>
  109 + <color name="subscribe_item_focused_stroke">#ffd9d9d9</color>
  110 + <color name="subscribe_item_drag_stroke">#ffd2d2d2</color>
  111 + <color name="subscribe_item_drag_bg">#fff5f5f5</color>
  112 + <color name="subscribe_item_drag_stroke_night">#ff464646</color>
  113 + <color name="subscribe_item_drag_bg_night">#ff252525</color>
  114 + <color name="subscribe_item_selected_bg">#ffffffff</color>
  115 + <color name="subscribe_item_selected_stroke">#ffcc3131</color>
  116 + <color name="subscribe_item_disabled_bg">#ffefefef</color>
  117 + <color name="subscribe_item_disabled_stroke">#ffd9d9d9</color>
  118 + <color name="subscribe_item_pressed_bg">#fff9f9f9</color>
  119 + <color name="subscribe_item_pressed_stroke">#ffcdcdcd</color>
  120 + <color name="subscribe_item_normal_bg">#fff5f5f5</color>
  121 + <color name="subscribe_item_normal_stroke">#ffcdcdcd</color>
  122 + <color name="subscribe_item_focused_bg_night">#ff252525</color>
  123 + <color name="subscribe_item_focused_stroke_night">#ff464646</color>
  124 + <color name="subscribe_item_selected_bg_night">#ff252525</color>
  125 + <color name="subscribe_item_selected_stroke_night">#ffbc494d</color>
  126 + <color name="subscribe_item_disabled_bg_night">#ff2b2b2b</color>
  127 + <color name="project_detail_red">#ffcd2323</color>
  128 + <color name="project_detail_purple">#ff573535</color>
  129 + <color name="transparentWhite">#30ffffff</color>
  130 + <color name="transparentWhit2">#efffffff</color>
  131 + <color name="transparentGray">#e6e0e0e0</color>
7 132  
8 133 <color name="hintTextColor">#494947</color>
9 134 <color name="bottomline">#B8B8B9</color>
... ...
app/src/main/res/values/strings.xml
... ... @@ -7,4 +7,11 @@
7 7 <string name="ceping">慧测慧练</string>
8 8 <string name="consult_huati">热门资讯</string>
9 9 <string name="order_detail">订单详情</string>
  10 + <!-- 录音 -->
  11 + <string name="normal">按住 说话</string>
  12 + <string name="recording">松开 结束</string>
  13 + <string name="want_to_cancle">松开手指,取消发送</string>
  14 + <string name="shouzhishanghua">手指上滑,取消发送</string>
  15 + <string name="tooshort">录音时间过短</string>
  16 + <string name="toolong">录音时间过长</string>
10 17 </resources>
... ...
app/src/main/res/values/styles.xml
... ... @@ -82,4 +82,16 @@
82 82 <!--<item name="colorAccent">@color/colorAccent</item>-->
83 83 </style>
84 84  
  85 + <style name="AppBarTheme" parent="android:Theme.Holo.Light">
  86 + <item name="android:windowFullscreen">false</item>
  87 + <item name="android:windowIsTranslucent">true</item>
  88 + </style>
  89 +
  90 + <style name="Theme_audioDialog" parent="@android:style/Theme.Dialog">
  91 + <item name="android:windowBackground">@mipmap/tb_dialog_loading_bg</item>
  92 + <item name="android:windowFrame">@null</item>
  93 + <item name="android:windowIsFloating">true</item>
  94 + <item name="android:windowIsTranslucent">true</item>
  95 + <item name="android:backgroundDimEnabled">false</item>
  96 + </style>
85 97 </resources>
... ...
mvpsdk/build.gradle
... ... @@ -38,7 +38,6 @@ android {
38 38 dependencies {
39 39 implementation fileTree(dir: 'libs', include: ['*.jar'])
40 40  
41   - implementation 'com.android.support:appcompat-v7:26.1.0'
42 41 implementation 'com.android.support.constraint:constraint-layout:1.0.2'
43 42 testImplementation 'junit:junit:4.12'
44 43 androidTestImplementation 'com.android.support.test:runner:1.0.1'
... ...
mychartlibrary/.gitignore 0 → 100644
... ... @@ -0,0 +1 @@
  1 +/build
... ...
mychartlibrary/build.gradle 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +apply plugin: 'com.android.library'
  2 +
  3 +android {
  4 + compileSdkVersion 27
  5 +
  6 +
  7 +
  8 + defaultConfig {
  9 + minSdkVersion 16
  10 + targetSdkVersion 27
  11 + versionCode 1
  12 + versionName "1.0"
  13 +
  14 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  15 +
  16 + }
  17 +
  18 + buildTypes {
  19 + release {
  20 + minifyEnabled false
  21 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  22 + }
  23 + }
  24 +
  25 +}
  26 +
  27 +dependencies {
  28 + implementation fileTree(dir: 'libs', include: ['*.jar'])
  29 +
  30 + implementation 'com.android.support:appcompat-v7:27.1.1'
  31 + testImplementation 'junit:junit:4.12'
  32 + androidTestImplementation 'com.android.support.test:runner:1.0.2'
  33 + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
  34 + implementation 'org.greenrobot:greendao:3.2.2'
  35 + compile "com.android.support:recyclerview-v7:27.1.1"
  36 + // Glide
  37 + compile "com.github.bumptech.glide:glide:$rootProject.glideVersion"
  38 + compile "com.github.bumptech.glide:okhttp-integration:$rootProject.glideokhttpVersion"
  39 + compile "jp.wasabeef:glide-transformations:$rootProject.glideTransformationVersion"
  40 +}
... ...
mychartlibrary/proguard-rules.pro 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +# Add project specific ProGuard rules here.
  2 +# You can control the set of applied configuration files using the
  3 +# proguardFiles setting in build.gradle.
  4 +#
  5 +# For more details, see
  6 +# http://developer.android.com/guide/developing/tools/proguard.html
  7 +
  8 +# If your project uses WebView with JS, uncomment the following
  9 +# and specify the fully qualified class name to the JavaScript interface
  10 +# class:
  11 +#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  12 +# public *;
  13 +#}
  14 +
  15 +# Uncomment this to preserve the line number information for
  16 +# debugging stack traces.
  17 +#-keepattributes SourceFile,LineNumberTable
  18 +
  19 +# If you keep the line number information, uncomment this to
  20 +# hide the original source file name.
  21 +#-renamesourcefileattribute SourceFile
... ...
mychartlibrary/src/androidTest/java/com/shunzhi/mychartlibrary/ExampleInstrumentedTest.java 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +package com.shunzhi.mychartlibrary;
  2 +
  3 +import android.content.Context;
  4 +import android.support.test.InstrumentationRegistry;
  5 +import android.support.test.runner.AndroidJUnit4;
  6 +
  7 +import org.junit.Test;
  8 +import org.junit.runner.RunWith;
  9 +
  10 +import static org.junit.Assert.*;
  11 +
  12 +/**
  13 + * Instrumented test, which will execute on an Android device.
  14 + *
  15 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  16 + */
  17 +@RunWith(AndroidJUnit4.class)
  18 +public class ExampleInstrumentedTest {
  19 + @Test
  20 + public void useAppContext() {
  21 + // Context of the app under test.
  22 + Context appContext = InstrumentationRegistry.getTargetContext();
  23 +
  24 + assertEquals("com.shunzhi.mychartlibrary.test", appContext.getPackageName());
  25 + }
  26 +}
... ...
mychartlibrary/src/main/AndroidManifest.xml 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2 + package="com.shunzhi.mychartlibrary" />
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/BaseActivity.java 0 → 100644
... ... @@ -0,0 +1,791 @@
  1 +package com.shunzhi.mychartlibrary;
  2 +
  3 +import android.Manifest;
  4 +import android.annotation.SuppressLint;
  5 +import android.annotation.TargetApi;
  6 +import android.app.ActionBar;
  7 +import android.app.Activity;
  8 +import android.content.Intent;
  9 +import android.content.pm.PackageManager;
  10 +import android.graphics.Bitmap;
  11 +import android.net.Uri;
  12 +import android.os.Build;
  13 +import android.os.Bundle;
  14 +import android.os.Environment;
  15 +import android.provider.MediaStore;
  16 +import android.support.v4.view.ViewPager;
  17 +import android.text.Spannable;
  18 +import android.text.TextUtils;
  19 +import android.view.KeyEvent;
  20 +import android.view.View;
  21 +import android.widget.AdapterView;
  22 +import android.widget.EditText;
  23 +import android.widget.ImageView;
  24 +import android.widget.LinearLayout;
  25 +import android.widget.ListView;
  26 +import android.widget.TextView;
  27 +import android.widget.Toast;
  28 +
  29 +
  30 +import com.shunzhi.mychartlibrary.adapter.DataAdapter;
  31 +import com.shunzhi.mychartlibrary.adapter.ExpressionAdapter;
  32 +import com.shunzhi.mychartlibrary.adapter.ExpressionPagerAdapter;
  33 +import com.shunzhi.mychartlibrary.db.ChatDbManager;
  34 +import com.shunzhi.mychartlibrary.db.ChatMessageBean;
  35 +import com.shunzhi.mychartlibrary.utils.StatusBarUtils;
  36 +import com.shunzhi.mychartlibrary.common.ChatConst;
  37 +import com.shunzhi.mychartlibrary.utils.FileSaveUtil;
  38 +import com.shunzhi.mychartlibrary.utils.ImageCheckoutUtil;
  39 +import com.shunzhi.mychartlibrary.utils.KeyBoardUtils;
  40 +import com.shunzhi.mychartlibrary.utils.PictureUtil;
  41 +import com.shunzhi.mychartlibrary.utils.ScreenUtil;
  42 +import com.shunzhi.mychartlibrary.utils.SmileUtils;
  43 +import com.shunzhi.mychartlibrary.widget.AudioRecordButton;
  44 +import com.shunzhi.mychartlibrary.widget.ChatBottomView;
  45 +import com.shunzhi.mychartlibrary.widget.ExpandGridView;
  46 +import com.shunzhi.mychartlibrary.widget.HeadIconSelectorView;
  47 +import com.shunzhi.mychartlibrary.widget.MediaManager;
  48 +import com.shunzhi.mychartlibrary.widget.pulltorefresh.PullToRefreshLayout;
  49 +
  50 +import java.io.File;
  51 +import java.io.FileInputStream;
  52 +import java.io.FileNotFoundException;
  53 +import java.io.IOException;
  54 +import java.lang.reflect.Field;
  55 +import java.text.SimpleDateFormat;
  56 +import java.util.ArrayList;
  57 +import java.util.HashMap;
  58 +import java.util.List;
  59 +import java.util.Map;
  60 +
  61 +/**
  62 + * Created by Mao Jiqing on 2016/10/20.
  63 + */
  64 +public abstract class BaseActivity extends Activity {
  65 + public PullToRefreshLayout pullList;
  66 + public boolean isDown = false;
  67 + private boolean CAN_WRITE_EXTERNAL_STORAGE = true;
  68 + private boolean CAN_RECORD_AUDIO = true;
  69 + public int position; //加载滚动刷新位置
  70 + public int bottomStatusHeight = 0;
  71 + public int listSlideHeight = 0;//滑动距离
  72 + public TextView send_emoji_icon;
  73 + public ImageView emoji;
  74 + public ImageView mess_iv;
  75 + public ImageView voiceIv;
  76 + public ListView mess_lv;
  77 + public ChatBottomView tbbv;
  78 + private DataAdapter adapter;
  79 + public AudioRecordButton voiceBtn;
  80 + public EditText mEditTextContent;
  81 + public ViewPager expressionViewpager;
  82 + public LinearLayout emoji_group;
  83 + private File mCurrentPhotoFile;
  84 + public View activityRootView;
  85 + private Toast mToast;
  86 + public String userName = "test";//聊天对象昵称
  87 + private String permissionInfo;
  88 + private String camPicPath;
  89 + public String item[] = {"你好!", "我正忙着呢,等等", "有啥事吗?", "有时间聊聊吗", "再见!"};
  90 + public List<ChatMessageBean> tblist = new ArrayList<ChatMessageBean>();
  91 + private List<String> reslist;
  92 + public ChatDbManager mChatDbManager;
  93 + public int page = 0;
  94 + public int number = 10;
  95 + public List<ChatMessageBean> pagelist = new ArrayList<ChatMessageBean>();
  96 + public ArrayList<String> imageList = new ArrayList<String>();//adapter图片数据
  97 + public HashMap<Integer, Integer> imagePosition = new HashMap<Integer, Integer>();//图片下标位置
  98 + private static final int SDK_PERMISSION_REQUEST = 127;
  99 + private static final int IMAGE_SIZE = 100 * 1024;// 300kb
  100 + public static final int SEND_OK = 0x1110;
  101 + public static final int REFRESH = 0x0011;
  102 + public static final int RECERIVE_OK = 0x1111;
  103 + public static final int PULL_TO_REFRESH_DOWN = 0x0111;
  104 +
  105 + /**
  106 + * 发送文本消息
  107 + */
  108 + protected abstract void sendMessage();
  109 +
  110 + /**
  111 + * 发送图片文件
  112 + *
  113 + * @param filePath
  114 + */
  115 + protected abstract void sendImage(String filePath);
  116 +
  117 + /**
  118 + * 发送语音消息
  119 + *
  120 + * @param seconds
  121 + * @param filePath
  122 + */
  123 + protected abstract void sendVoice(float seconds, String filePath);
  124 +
  125 + protected abstract void loadRecords();
  126 +
  127 + @Override
  128 + protected void onCreate(Bundle savedInstanceState) {
  129 + super.onCreate(savedInstanceState);
  130 + setContentView(R.layout.activity_chat);
  131 + StatusBarUtils.setBarColor(this,getResources().getColor(R.color.titleColor));
  132 + findView();
  133 + initpop();
  134 + init();
  135 + // after andrioid m,must request Permiision on runtime
  136 + getPersimmions();
  137 + }
  138 +
  139 + @Override
  140 + protected void onDestroy() {
  141 + MediaManager.pause();
  142 + MediaManager.release();
  143 + cancelToast();
  144 + super.onDestroy();
  145 + }
  146 +
  147 + protected void findView() {
  148 + pullList = (PullToRefreshLayout) findViewById(R.id.content_lv);
  149 + activityRootView = findViewById(R.id.layout_tongbao_rl);
  150 + mEditTextContent = (EditText) findViewById(R.id.mess_et);
  151 + mess_iv = (ImageView) findViewById(R.id.mess_iv);
  152 + emoji = (ImageView) findViewById(R.id.emoji);
  153 + voiceIv = (ImageView) findViewById(R.id.voice_iv);
  154 + expressionViewpager = (ViewPager) findViewById(R.id.vPager);
  155 + voiceBtn = (AudioRecordButton) findViewById(R.id.voice_btn);
  156 + emoji_group = (LinearLayout) findViewById(R.id.emoji_group);
  157 + send_emoji_icon = (TextView) findViewById(R.id.send_emoji_icon);
  158 + tbbv = (ChatBottomView) findViewById(R.id.other_lv);
  159 + initActionBar();
  160 + }
  161 +
  162 + protected void init() {
  163 + mEditTextContent.setOnKeyListener(onKeyListener);
  164 + mChatDbManager = new ChatDbManager();
  165 + PullToRefreshLayout.pulltorefreshNotifier pullNotifier = new PullToRefreshLayout.pulltorefreshNotifier() {
  166 + @Override
  167 + public void onPull() {
  168 + // TODO Auto-generated method stub
  169 + downLoad();
  170 + }
  171 + };
  172 + pullList.setpulltorefreshNotifier(pullNotifier);
  173 + voiceIv.setOnClickListener(new View.OnClickListener() {
  174 +
  175 + @Override
  176 + public void onClick(View arg0) {
  177 + // TODO Auto-generated method stub
  178 + if (voiceBtn.getVisibility() == View.GONE) {
  179 + emoji.setBackgroundResource(R.mipmap.emoji);
  180 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  181 + mEditTextContent.setVisibility(View.GONE);
  182 + emoji_group.setVisibility(View.GONE);
  183 + tbbv.setVisibility(View.GONE);
  184 + mess_lv.setVisibility(View.GONE);
  185 + voiceBtn.setVisibility(View.VISIBLE);
  186 + KeyBoardUtils.hideKeyBoard(BaseActivity.this,
  187 + mEditTextContent);
  188 + voiceIv.setBackgroundResource(R.mipmap.chatting_setmode_keyboard_btn_normal);
  189 + } else {
  190 + mEditTextContent.setVisibility(View.VISIBLE);
  191 + voiceBtn.setVisibility(View.GONE);
  192 + voiceIv.setBackgroundResource(R.mipmap.voice_btn_normal);
  193 + KeyBoardUtils.showKeyBoard(BaseActivity.this, mEditTextContent);
  194 + }
  195 + }
  196 +
  197 + });
  198 + mess_iv.setOnClickListener(new View.OnClickListener() {
  199 +
  200 + @SuppressLint("NewApi")
  201 + @Override
  202 + public void onClick(View v) {
  203 + // TODO Auto-generated method stub
  204 + emoji_group.setVisibility(View.GONE);
  205 + if (tbbv.getVisibility() == View.GONE
  206 + && mess_lv.getVisibility() == View.GONE) {
  207 + mEditTextContent.setVisibility(View.VISIBLE);
  208 + mess_iv.setFocusable(true);
  209 + voiceBtn.setVisibility(View.GONE);
  210 + emoji.setBackgroundResource(R.mipmap.emoji);
  211 + voiceIv.setBackgroundResource(R.mipmap.voice_btn_normal);
  212 + tbbv.setVisibility(View.VISIBLE);
  213 + KeyBoardUtils.hideKeyBoard(BaseActivity.this,
  214 + mEditTextContent);
  215 + mess_iv.setBackgroundResource(R.mipmap.chatting_setmode_keyboard_btn_normal);
  216 + } else {
  217 + tbbv.setVisibility(View.GONE);
  218 + KeyBoardUtils.showKeyBoard(BaseActivity.this, mEditTextContent);
  219 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  220 + if (mess_lv.getVisibility() != View.GONE) {
  221 + mess_lv.setVisibility(View.GONE);
  222 + KeyBoardUtils.showKeyBoard(BaseActivity.this, mEditTextContent);
  223 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  224 + }
  225 + }
  226 + }
  227 + });
  228 + send_emoji_icon.setOnClickListener(new View.OnClickListener() {
  229 +
  230 + @Override
  231 + public void onClick(View arg0) {
  232 + // TODO Auto-generated method stub
  233 + sendMessage();
  234 + }
  235 +
  236 + });
  237 + tbbv.setOnHeadIconClickListener(new HeadIconSelectorView.OnHeadIconClickListener() {
  238 +
  239 + @SuppressLint("InlinedApi")
  240 + @Override
  241 + public void onClick(int from) {
  242 + switch (from) {
  243 + case ChatBottomView.FROM_CAMERA:
  244 + if (!CAN_WRITE_EXTERNAL_STORAGE) {
  245 + Toast.makeText(BaseActivity.this, "权限未开通\n请到设置中开通相册权限", Toast.LENGTH_SHORT).show();
  246 + } else {
  247 + final String state = Environment.getExternalStorageState();
  248 + if (Environment.MEDIA_MOUNTED.equals(state)) {
  249 + camPicPath = getSavePicPath();
  250 + Intent openCameraIntent = new Intent(
  251 + MediaStore.ACTION_IMAGE_CAPTURE);
  252 + Uri uri = Uri.fromFile(new File(camPicPath));
  253 + openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
  254 + startActivityForResult(openCameraIntent,
  255 + ChatBottomView.FROM_CAMERA);
  256 + } else {
  257 + showToast("请检查内存卡");
  258 + }
  259 + }
  260 + break;
  261 + case ChatBottomView.FROM_GALLERY:
  262 + if (!CAN_WRITE_EXTERNAL_STORAGE) {
  263 + Toast.makeText(BaseActivity.this, "权限未开通\n请到设置中开通相册权限", Toast.LENGTH_SHORT).show();
  264 + } else {
  265 + String status = Environment.getExternalStorageState();
  266 + if (status.equals(Environment.MEDIA_MOUNTED)) {// 判断是否有SD卡
  267 + Intent intent = new Intent();
  268 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  269 + intent.setAction(Intent.ACTION_GET_CONTENT);
  270 + } else {
  271 + intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
  272 + intent.addCategory(Intent.CATEGORY_OPENABLE);
  273 + intent.putExtra("crop", "true");
  274 + intent.putExtra("scale", "true");
  275 + intent.putExtra("scaleUpIfNeeded", true);
  276 + }
  277 + intent.setType("image/*");
  278 + startActivityForResult(intent,
  279 + ChatBottomView.FROM_GALLERY);
  280 + } else {
  281 + showToast("没有SD卡");
  282 + }
  283 + }
  284 + break;
  285 +
  286 + case ChatBottomView.FROM_PHRASE:
  287 + if (mess_lv.getVisibility() == View.GONE) {
  288 + tbbv.setVisibility(View.GONE);
  289 + emoji.setBackgroundResource(R.mipmap.emoji);
  290 + voiceIv.setBackgroundResource(R.mipmap.voice_btn_normal);
  291 + mess_lv.setVisibility(View.VISIBLE);
  292 + KeyBoardUtils.hideKeyBoard(BaseActivity.this,
  293 + mEditTextContent);
  294 + mess_iv.setBackgroundResource(R.mipmap.chatting_setmode_keyboard_btn_normal);
  295 + }
  296 + }
  297 + }
  298 +
  299 + });
  300 + emoji.setOnClickListener(new View.OnClickListener() {
  301 +
  302 + @Override
  303 + public void onClick(View v) {
  304 + // TODO Auto-generated method stub
  305 + mess_lv.setVisibility(View.GONE);
  306 + tbbv.setVisibility(View.GONE);
  307 + if (emoji_group.getVisibility() == View.GONE) {
  308 + mEditTextContent.setVisibility(View.VISIBLE);
  309 + voiceBtn.setVisibility(View.GONE);
  310 + voiceIv.setBackgroundResource(R.mipmap.voice_btn_normal);
  311 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  312 + emoji_group.setVisibility(View.VISIBLE);
  313 + emoji.setBackgroundResource(R.mipmap.chatting_setmode_keyboard_btn_normal);
  314 + KeyBoardUtils.hideKeyBoard(BaseActivity.this,
  315 + mEditTextContent);
  316 + } else {
  317 + emoji_group.setVisibility(View.GONE);
  318 + emoji.setBackgroundResource(R.mipmap.emoji);
  319 + KeyBoardUtils.showKeyBoard(BaseActivity.this, mEditTextContent);
  320 + }
  321 + }
  322 + });
  323 + // 表情list
  324 + reslist = getExpressionRes(40);
  325 + // 初始化表情viewpager
  326 + List<View> views = new ArrayList<View>();
  327 + View gv1 = getGridChildView(1);
  328 + View gv2 = getGridChildView(2);
  329 + views.add(gv1);
  330 + views.add(gv2);
  331 + expressionViewpager.setAdapter(new ExpressionPagerAdapter(views));
  332 +
  333 + mEditTextContent.setOnClickListener(new View.OnClickListener() {
  334 +
  335 + @Override
  336 + public void onClick(View v) {
  337 + // TODO Auto-generated method stub
  338 + emoji_group.setVisibility(View.GONE);
  339 + tbbv.setVisibility(View.GONE);
  340 + mess_lv.setVisibility(View.GONE);
  341 + emoji.setBackgroundResource(R.mipmap.emoji);
  342 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  343 + voiceIv.setBackgroundResource(R.mipmap.voice_btn_normal);
  344 + }
  345 +
  346 + });
  347 +
  348 + mess_lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  349 +
  350 + @Override
  351 + public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
  352 + long arg3) {
  353 + // TODO Auto-generated method stub
  354 + mEditTextContent.setText(item[arg2]);
  355 + sendMessage();
  356 + }
  357 +
  358 + });
  359 +// controlKeyboardLayout(activityRootView, pullList);
  360 + bottomStatusHeight = ScreenUtil.getNavigationBarHeight(this);
  361 + //加载本地聊天记录
  362 + page = (int) mChatDbManager.getPages(number);
  363 + loadRecords();
  364 + }
  365 +
  366 + private void initActionBar() {
  367 + if (getActionBar() == null) {
  368 + return;
  369 + }
  370 +// getActionBar().setBackgroundDrawable(getResources().getDrawable(R.drawable.ab_bg));//ActionBar的背景图片
  371 + getActionBar().setCustomView(R.layout.layout_action_bar);//ActionBar的自定义布局文件
  372 + getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
  373 + View.OnClickListener listener = new View.OnClickListener() {
  374 + @Override
  375 + public void onClick(View v) {
  376 + if(v.getId()==R.id.ivLeft){
  377 + doLeft();
  378 + }else if (v.getId()==R.id.ivRight){
  379 + doRight();
  380 + }else if (v.getId()==R.id.llRight){
  381 + doRight();
  382 + }
  383 + }
  384 + };
  385 + getActionBar().getCustomView().findViewById(R.id.ivLeft).setOnClickListener(listener);
  386 + getActionBar().getCustomView().findViewById(R.id.ivRight).setOnClickListener(listener);
  387 + getActionBar().getCustomView().findViewById(R.id.llRight).setOnClickListener(listener);
  388 + ((TextView) getActionBar().getCustomView().findViewById(R.id.tvTitle)).setText(getTitle().toString());
  389 + }
  390 +
  391 + @TargetApi(23)
  392 + protected void getPersimmions() {
  393 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  394 + ArrayList<String> permissions = new ArrayList<String>();
  395 + // 读写权限
  396 + if (addPermission(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
  397 + permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny \n";
  398 + }
  399 + // 麦克风权限
  400 + if (addPermission(permissions, Manifest.permission.RECORD_AUDIO)) {
  401 + permissionInfo += "Manifest.permission.WRITE_EXTERNAL_STORAGE Deny \n";
  402 + }
  403 + if (permissions.size() > 0) {
  404 + requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
  405 + }
  406 + }
  407 + }
  408 +
  409 + @TargetApi(23)
  410 + private boolean addPermission(ArrayList<String> permissionsList, String permission) {
  411 + if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { // 如果应用没有获得对应权限,则添加到列表中,准备批量申请
  412 + if (shouldShowRequestPermissionRationale(permission)) {
  413 + return true;
  414 + } else {
  415 + permissionsList.add(permission);
  416 + return false;
  417 + }
  418 +
  419 + } else {
  420 + return true;
  421 + }
  422 + }
  423 +
  424 + @TargetApi(23)
  425 + @Override
  426 + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
  427 + // TODO Auto-generated method stub
  428 + super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  429 + switch (requestCode) {
  430 + case SDK_PERMISSION_REQUEST:
  431 + Map<String, Integer> perms = new HashMap<String, Integer>();
  432 + // Initial
  433 + perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
  434 + perms.put(Manifest.permission.RECORD_AUDIO, PackageManager.PERMISSION_GRANTED);
  435 + // Fill with results
  436 + for (int i = 0; i < permissions.length; i++)
  437 + perms.put(permissions[i], grantResults[i]);
  438 + // Check for ACCESS_FINE_LOCATION
  439 + if (perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  440 + // Permission Denied
  441 + CAN_WRITE_EXTERNAL_STORAGE = false;
  442 + Toast.makeText(this, "禁用图片权限将导致发送图片功能无法使用!", Toast.LENGTH_SHORT)
  443 + .show();
  444 + }
  445 + if (perms.get(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
  446 + CAN_RECORD_AUDIO = false;
  447 + Toast.makeText(this, "禁用录制音频权限将导致语音功能无法使用!", Toast.LENGTH_SHORT)
  448 + .show();
  449 + }
  450 + break;
  451 + default:
  452 + super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  453 + }
  454 + }
  455 +
  456 + public void setTitle(CharSequence title) {
  457 + ((TextView) getActionBar().getCustomView().findViewById(R.id.tvTitle)).setText(title);
  458 + }
  459 +
  460 + protected void showLeft(boolean flag) {
  461 + if (getActionBar() == null) {
  462 + return;
  463 + }
  464 + getActionBar().getCustomView().findViewById(R.id.ivLeft).setVisibility(flag ? View.VISIBLE : View.GONE);
  465 + }
  466 +
  467 + protected void showRight(boolean flag) {
  468 + if (getActionBar() == null) {
  469 + return;
  470 + }
  471 + getActionBar().getCustomView().findViewById(R.id.llRight).setVisibility(flag ? View.VISIBLE : View.GONE);
  472 + }
  473 +
  474 + protected void doLeft() {
  475 + finish();
  476 + }
  477 +
  478 + protected void doRight() {
  479 +
  480 + }
  481 +
  482 + protected void setRight(int drawRes) {
  483 + if (getActionBar() == null) {
  484 + return;
  485 + }
  486 + ((ImageView) getActionBar().getCustomView().findViewById(R.id.ivRight)).setImageResource(drawRes);
  487 + getActionBar().getCustomView().findViewById(R.id.ivRight).setVisibility(View.VISIBLE);
  488 + }
  489 +
  490 + protected void setRightText(String text){
  491 + if(getActionBar()==null){
  492 + return;
  493 + }
  494 + ((TextView)getActionBar().getCustomView().findViewById(R.id.tvRight)).setText(text);
  495 + getActionBar().getCustomView().findViewById(R.id.tvRight).setVisibility(View.VISIBLE);
  496 + }
  497 +
  498 + /**
  499 + * 常用语列表初始化
  500 + */
  501 + @SuppressLint({"NewApi", "InflateParams"})
  502 + private void initpop() {
  503 + mess_lv = (ListView) findViewById(R.id.mess_lv);
  504 + adapter = new DataAdapter(this, item);
  505 + mess_lv.setAdapter(adapter);
  506 + }
  507 +
  508 + private void downLoad() {
  509 + if (!isDown) {
  510 + new Thread(new Runnable() {
  511 +
  512 + @Override
  513 + public void run() {
  514 + // TODO Auto-generated method stub
  515 + loadRecords();
  516 + }
  517 + }).start();
  518 + }
  519 + }
  520 +
  521 +
  522 + @Override
  523 + protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  524 + super.onActivityResult(requestCode, resultCode, data);
  525 + if (resultCode == RESULT_OK) {
  526 + tbbv.setVisibility(View.GONE);
  527 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  528 + switch (requestCode) {
  529 + case ChatBottomView.FROM_CAMERA:
  530 + FileInputStream is = null;
  531 + try {
  532 + is = new FileInputStream(camPicPath);
  533 + File camFile = new File(camPicPath); // 图片文件路径
  534 + if (camFile.exists()) {
  535 + int size = ImageCheckoutUtil
  536 + .getImageSize(ImageCheckoutUtil
  537 + .getLoacalBitmap(camPicPath));
  538 + if (size > IMAGE_SIZE) {
  539 + showDialog(camPicPath);
  540 + } else {
  541 + sendImage(camPicPath);
  542 + }
  543 + } else {
  544 + showToast("该文件不存在!");
  545 + }
  546 + } catch (FileNotFoundException e) {
  547 + // TODO Auto-generated catch block
  548 + e.printStackTrace();
  549 + } finally {
  550 + // 关闭流
  551 + try {
  552 + is.close();
  553 + } catch (IOException e) {
  554 + // TODO Auto-generated catch block
  555 + e.printStackTrace();
  556 + }
  557 + }
  558 + break;
  559 + case ChatBottomView.FROM_GALLERY:
  560 + Uri uri = data.getData();
  561 + String path = FileSaveUtil.getPath(getApplicationContext(), uri);
  562 + mCurrentPhotoFile = new File(path); // 图片文件路径
  563 + if (mCurrentPhotoFile.exists()) {
  564 + int size = ImageCheckoutUtil.getImageSize(ImageCheckoutUtil.getLoacalBitmap(path));
  565 + if (size > IMAGE_SIZE) {
  566 + showDialog(path);
  567 + } else {
  568 + sendImage(path);
  569 + }
  570 + } else {
  571 + showToast("该文件不存在!");
  572 + }
  573 +
  574 + break;
  575 + }
  576 + } else if (resultCode == RESULT_CANCELED) {
  577 + // Toast.makeText(this, "操作取消", Toast.LENGTH_SHORT).show();
  578 + }
  579 + }
  580 +
  581 + @Override
  582 + public boolean onKeyDown(int keyCode, KeyEvent event) {
  583 + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
  584 + finish();
  585 + return true;
  586 + }
  587 + return super.onKeyDown(keyCode, event);
  588 + }
  589 +
  590 + /**
  591 + * 界面复位
  592 + */
  593 + protected void reset() {
  594 + emoji_group.setVisibility(View.GONE);
  595 + tbbv.setVisibility(View.GONE);
  596 + mess_lv.setVisibility(View.GONE);
  597 + emoji.setBackgroundResource(R.mipmap.emoji);
  598 + mess_iv.setBackgroundResource(R.mipmap.tb_more);
  599 + voiceIv.setBackgroundResource(R.mipmap.voice_btn_normal);
  600 + }
  601 +
  602 + public void showToast(String text) {
  603 + if (mToast == null) {
  604 + mToast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
  605 + } else {
  606 + mToast.setText(text);
  607 + mToast.setDuration(Toast.LENGTH_SHORT);
  608 + }
  609 + mToast.show();
  610 + }
  611 +
  612 + public void cancelToast() {
  613 + if (mToast != null) {
  614 + mToast.cancel();
  615 + }
  616 + }
  617 +
  618 +
  619 + /**
  620 + * 获取表情的gridview的子view
  621 + *
  622 + * @param i
  623 + * @return
  624 + */
  625 + private View getGridChildView(int i) {
  626 + View view = View.inflate(this, R.layout.layout_expression_gridview, null);
  627 + ExpandGridView gv = (ExpandGridView) view.findViewById(R.id.gridview);
  628 + List<String> list = new ArrayList<String>();
  629 + if (i == 1) {
  630 + List<String> list1 = reslist.subList(0, 20);
  631 + list.addAll(list1);
  632 + } else if (i == 2) {
  633 + list.addAll(reslist.subList(20, reslist.size()));
  634 + }
  635 + list.add("delete_expression");
  636 + final ExpressionAdapter expressionAdapter = new ExpressionAdapter(this,
  637 + 1, list);
  638 + gv.setAdapter(expressionAdapter);
  639 + gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  640 +
  641 + @Override
  642 + public void onItemClick(AdapterView<?> parent, View view,
  643 + int position, long id) {
  644 + String filename = expressionAdapter.getItem(position);
  645 + try {
  646 + // 文字输入框可见时,才可输入表情
  647 + // 按住说话可见,不让输入表情
  648 + if (filename != "delete_expression") { // 不是删除键,显示表情
  649 + // 这里用的反射,所以混淆的时候不要混淆SmileUtils这个类
  650 + @SuppressWarnings("rawtypes")
  651 + Class clz = Class
  652 + .forName("com.maxi.chatdemo.utils.SmileUtils");
  653 + Field field = clz.getField(filename);
  654 + String oriContent = mEditTextContent.getText()
  655 + .toString();
  656 + int index = Math.max(
  657 + mEditTextContent.getSelectionStart(), 0);
  658 + StringBuilder sBuilder = new StringBuilder(oriContent);
  659 + Spannable insertEmotion = SmileUtils.getSmiledText(
  660 + BaseActivity.this,
  661 + (String) field.get(null));
  662 + sBuilder.insert(index, insertEmotion);
  663 + mEditTextContent.setText(sBuilder.toString());
  664 + mEditTextContent.setSelection(index
  665 + + insertEmotion.length());
  666 + } else { // 删除文字或者表情
  667 + if (!TextUtils.isEmpty(mEditTextContent.getText())) {
  668 +
  669 + int selectionStart = mEditTextContent
  670 + .getSelectionStart();// 获取光标的位置
  671 + if (selectionStart > 0) {
  672 + String body = mEditTextContent.getText()
  673 + .toString();
  674 + String tempStr = body.substring(0,
  675 + selectionStart);
  676 + int i = tempStr.lastIndexOf("[");// 获取最后一个表情的位置
  677 + if (i != -1) {
  678 + CharSequence cs = tempStr.substring(i,
  679 + selectionStart);
  680 + if (SmileUtils.containsKey(cs.toString()))
  681 + mEditTextContent.getEditableText()
  682 + .delete(i, selectionStart);
  683 + else
  684 + mEditTextContent.getEditableText()
  685 + .delete(selectionStart - 1,
  686 + selectionStart);
  687 + } else {
  688 + mEditTextContent.getEditableText().delete(
  689 + selectionStart - 1, selectionStart);
  690 + }
  691 + }
  692 + }
  693 +
  694 + }
  695 + } catch (Exception e) {
  696 + }
  697 +
  698 + }
  699 + });
  700 + return view;
  701 + }
  702 +
  703 + public List<String> getExpressionRes(int getSum) {
  704 + List<String> reslist = new ArrayList<String>();
  705 + for (int x = 1; x <= getSum; x++) {
  706 + String filename = "f" + x;
  707 + reslist.add(filename);
  708 + }
  709 + return reslist;
  710 +
  711 + }
  712 +
  713 + private void showDialog(final String path) {
  714 + new Thread(new Runnable() {
  715 +
  716 + @Override
  717 + public void run() {
  718 + // // TODO Auto-generated method stub
  719 + try {
  720 + String GalPicPath = getSavePicPath();
  721 + Bitmap bitmap = PictureUtil.compressSizeImage(path);
  722 + boolean isSave = FileSaveUtil.saveBitmap(
  723 + PictureUtil.reviewPicRotate(bitmap, GalPicPath),
  724 + GalPicPath);
  725 + File file = new File(GalPicPath);
  726 + if (file.exists() && isSave) {
  727 + sendImage(GalPicPath);
  728 + }
  729 + } catch (Exception e) {
  730 + e.printStackTrace();
  731 + }
  732 + }
  733 + }).start();
  734 + }
  735 +
  736 +
  737 + private String getSavePicPath() {
  738 + final String dir = FileSaveUtil.SD_CARD_PATH + "image_data/";
  739 + try {
  740 + FileSaveUtil.createSDDirectory(dir);
  741 + } catch (IOException e) {
  742 + // TODO Auto-generated catch block
  743 + e.printStackTrace();
  744 + }
  745 + String fileName = String.valueOf(System.currentTimeMillis() + ".png");
  746 + return dir + fileName;
  747 + }
  748 +
  749 + public ChatMessageBean getTbub(String username, int type,
  750 + String Content, String imageIconUrl, String imageUrl,
  751 + String imageLocal, String userVoicePath, String userVoiceUrl,
  752 + Float userVoiceTime, @ChatConst.SendState int sendState) {
  753 + ChatMessageBean tbub = new ChatMessageBean();
  754 + tbub.setUserName(username);
  755 + String time = returnTime();
  756 + tbub.setTime(time);
  757 + tbub.setType(type);
  758 + tbub.setUserContent(Content);
  759 + tbub.setImageIconUrl(imageIconUrl);
  760 + tbub.setImageUrl(imageUrl);
  761 + tbub.setUserVoicePath(userVoicePath);
  762 + tbub.setUserVoiceUrl(userVoiceUrl);
  763 + tbub.setUserVoiceTime(userVoiceTime);
  764 + tbub.setSendState(sendState);
  765 + tbub.setImageLocal(imageLocal);
  766 + mChatDbManager.insert(tbub);
  767 +
  768 + return tbub;
  769 + }
  770 +
  771 + private View.OnKeyListener onKeyListener = new View.OnKeyListener() {
  772 +
  773 + @Override
  774 + public boolean onKey(View v, int keyCode, KeyEvent event) {
  775 + if (keyCode == KeyEvent.KEYCODE_ENTER
  776 + && event.getAction() == KeyEvent.ACTION_DOWN) {
  777 + sendMessage();
  778 + return true;
  779 + }
  780 + return false;
  781 + }
  782 + };
  783 +
  784 + @SuppressLint("SimpleDateFormat")
  785 + public static String returnTime() {
  786 + SimpleDateFormat sDateFormat = new SimpleDateFormat(
  787 + "yyyy-MM-dd HH:mm:ss");
  788 + String date = sDateFormat.format(new java.util.Date());
  789 + return date;
  790 + }
  791 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/adapter/DataAdapter.java 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +package com.shunzhi.mychartlibrary.adapter;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.view.LayoutInflater;
  6 +import android.view.View;
  7 +import android.view.ViewGroup;
  8 +import android.widget.BaseAdapter;
  9 +import android.widget.TextView;
  10 +
  11 +import com.shunzhi.mychartlibrary.R;
  12 +
  13 +
  14 +public class DataAdapter extends BaseAdapter {
  15 +
  16 + private String[] title;
  17 + private Context context;
  18 + public DataAdapter(Context context,String[] title) {
  19 + super();
  20 + this.context = context;
  21 + this.title = title;
  22 + }
  23 +
  24 + @Override
  25 + public int getCount() {
  26 + return title.length;
  27 + }
  28 +
  29 + @Override
  30 + public Object getItem(int position) {
  31 + return title[position];
  32 + }
  33 +
  34 + @Override
  35 + public long getItemId(int position) {
  36 + return position;
  37 + }
  38 +
  39 + @SuppressLint("InflateParams")
  40 + @Override
  41 + public View getView(final int position, View convertView,
  42 + ViewGroup parent) {
  43 + ViewHolder holder;
  44 + if (convertView == null) {
  45 + holder = new ViewHolder();
  46 + convertView = LayoutInflater.from(context)
  47 + .inflate(R.layout.layout_mess_iv_listitem, null);
  48 + holder.money_Tv = (TextView) convertView
  49 + .findViewById(R.id.title);
  50 + convertView.setTag(holder);
  51 + } else {
  52 + holder = (ViewHolder) convertView.getTag();
  53 + }
  54 +
  55 + holder.money_Tv.setText(title[position]);
  56 + return convertView;
  57 + }
  58 +
  59 + class ViewHolder {
  60 +
  61 + TextView money_Tv;
  62 + }
  63 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/adapter/ExpressionAdapter.java 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +/**
  2 + * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + * http://www.apache.org/licenses/LICENSE-2.0
  8 + * Unless required by applicable law or agreed to in writing, software
  9 + * distributed under the License is distributed on an "AS IS" BASIS,
  10 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11 + * See the License for the specific language governing permissions and
  12 + * limitations under the License.
  13 + */
  14 +package com.shunzhi.mychartlibrary.adapter;
  15 +
  16 +import android.content.Context;
  17 +import android.view.View;
  18 +import android.view.ViewGroup;
  19 +import android.widget.ArrayAdapter;
  20 +import android.widget.ImageView;
  21 +
  22 +
  23 +import com.shunzhi.mychartlibrary.R;
  24 +
  25 +import java.util.List;
  26 +
  27 +public class ExpressionAdapter extends ArrayAdapter<String>{
  28 +
  29 + public ExpressionAdapter(Context context, int textViewResourceId, List<String> objects) {
  30 + super(context, textViewResourceId, objects);
  31 + }
  32 +
  33 +
  34 + @Override
  35 + public View getView(int position, View convertView, ViewGroup parent) {
  36 + if(convertView == null){
  37 + convertView = View.inflate(getContext(), R.layout.layout_row_expression, null);
  38 + }
  39 +
  40 + ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_expression);
  41 +
  42 + String filename = getItem(position);
  43 + int resId = getContext().getResources().getIdentifier(filename, "mipmap", getContext().getPackageName());
  44 + imageView.setImageResource(resId);
  45 +
  46 + return convertView;
  47 + }
  48 +
  49 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/adapter/ExpressionPagerAdapter.java 0 → 100644
... ... @@ -0,0 +1,52 @@
  1 +/**
  2 + * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + * http://www.apache.org/licenses/LICENSE-2.0
  8 + * Unless required by applicable law or agreed to in writing, software
  9 + * distributed under the License is distributed on an "AS IS" BASIS,
  10 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11 + * See the License for the specific language governing permissions and
  12 + * limitations under the License.
  13 + */
  14 +package com.shunzhi.mychartlibrary.adapter;
  15 +
  16 +import android.support.v4.view.PagerAdapter;
  17 +import android.support.v4.view.ViewPager;
  18 +import android.view.View;
  19 +
  20 +import java.util.List;
  21 +
  22 +public class ExpressionPagerAdapter extends PagerAdapter {
  23 +
  24 + private List<View> views;
  25 +
  26 + public ExpressionPagerAdapter(List<View> views) {
  27 + this.views = views;
  28 + }
  29 +
  30 + @Override
  31 + public int getCount() {
  32 + return views.size();
  33 + }
  34 +
  35 + @Override
  36 + public boolean isViewFromObject(View arg0, Object arg1) {
  37 + return arg0 == arg1;
  38 + }
  39 +
  40 + @Override
  41 + public Object instantiateItem(View arg0, int arg1) {
  42 + ((ViewPager) arg0).addView(views.get(arg1));
  43 + return views.get(arg1);
  44 + }
  45 +
  46 + @Override
  47 + public void destroyItem(View arg0, int arg1, Object arg2) {
  48 + ((ViewPager) arg0).removeView(views.get(arg1));
  49 +
  50 + }
  51 +
  52 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/animator/BaseItemAnimator.java 0 → 100644
... ... @@ -0,0 +1,607 @@
  1 +package com.shunzhi.mychartlibrary.animator;
  2 +
  3 +import android.support.v4.view.ViewCompat;
  4 +import android.support.v4.view.ViewPropertyAnimatorCompat;
  5 +import android.support.v4.view.ViewPropertyAnimatorListener;
  6 +import android.support.v7.widget.RecyclerView;
  7 +import android.support.v7.widget.SimpleItemAnimator;
  8 +import android.view.View;
  9 +
  10 +import java.util.ArrayList;
  11 +import java.util.List;
  12 +
  13 +
  14 +/**
  15 + * Created by Mao Jiqing on 2016/9/30.
  16 + */
  17 +public abstract class BaseItemAnimator extends SimpleItemAnimator {
  18 +
  19 + /**
  20 + * RecyclerView
  21 + */
  22 + protected RecyclerView mRecyclerView;
  23 +
  24 + //------------------------------------------------------------
  25 + // Constructor
  26 + //------------------------------------------------------------
  27 +
  28 + public BaseItemAnimator(RecyclerView recyclerView){
  29 + mRecyclerView = recyclerView;
  30 + }
  31 +
  32 + //------------------------------------------------------------
  33 + // Default Item Animator
  34 + //------------------------------------------------------------
  35 + private static final boolean DEBUG = false;
  36 +
  37 + private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
  38 + private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
  39 + private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
  40 + private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
  41 +
  42 + private ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
  43 + private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
  44 + private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
  45 +
  46 + protected ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
  47 + protected ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList<>();
  48 + protected ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
  49 + protected ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();
  50 +
  51 + private static class MoveInfo {
  52 + public RecyclerView.ViewHolder holder;
  53 + public int fromX, fromY, toX, toY;
  54 +
  55 + private MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
  56 + this.holder = holder;
  57 + this.fromX = fromX;
  58 + this.fromY = fromY;
  59 + this.toX = toX;
  60 + this.toY = toY;
  61 + }
  62 + }
  63 +
  64 + private static class ChangeInfo {
  65 + public RecyclerView.ViewHolder oldHolder, newHolder;
  66 + public int fromX, fromY, toX, toY;
  67 + private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
  68 + this.oldHolder = oldHolder;
  69 + this.newHolder = newHolder;
  70 + }
  71 +
  72 + private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
  73 + int fromX, int fromY, int toX, int toY) {
  74 + this(oldHolder, newHolder);
  75 + this.fromX = fromX;
  76 + this.fromY = fromY;
  77 + this.toX = toX;
  78 + this.toY = toY;
  79 + }
  80 +
  81 + @Override
  82 + public String toString() {
  83 + return "ChangeInfo{" +
  84 + "oldHolder=" + oldHolder +
  85 + ", newHolder=" + newHolder +
  86 + ", fromX=" + fromX +
  87 + ", fromY=" + fromY +
  88 + ", toX=" + toX +
  89 + ", toY=" + toY +
  90 + '}';
  91 + }
  92 + }
  93 +
  94 +
  95 + @Override
  96 + public void runPendingAnimations() {
  97 + boolean removalsPending = !mPendingRemovals.isEmpty();
  98 + boolean movesPending = !mPendingMoves.isEmpty();
  99 + boolean changesPending = !mPendingChanges.isEmpty();
  100 + boolean additionsPending = !mPendingAdditions.isEmpty();
  101 + if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
  102 + // nothing to animate
  103 + return;
  104 + }
  105 + // First, remove stuff
  106 + for (RecyclerView.ViewHolder holder : mPendingRemovals) {
  107 + animateRemoveImpl(holder);
  108 + }
  109 + mPendingRemovals.clear();
  110 + // Next, move stuff
  111 + if (movesPending) {
  112 + final ArrayList<MoveInfo> moves = new ArrayList<>();
  113 + moves.addAll(mPendingMoves);
  114 + mMovesList.add(moves);
  115 + mPendingMoves.clear();
  116 + Runnable mover = new Runnable() {
  117 + @Override
  118 + public void run() {
  119 + for (MoveInfo moveInfo : moves) {
  120 + animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
  121 + moveInfo.toX, moveInfo.toY);
  122 + }
  123 + moves.clear();
  124 + mMovesList.remove(moves);
  125 + }
  126 + };
  127 + if (removalsPending) {
  128 + View view = moves.get(0).holder.itemView;
  129 + ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
  130 + } else {
  131 + mover.run();
  132 + }
  133 + }
  134 + // Next, change stuff, to run in parallel with move animations
  135 + if (changesPending) {
  136 + final ArrayList<ChangeInfo> changes = new ArrayList<>();
  137 + changes.addAll(mPendingChanges);
  138 + mChangesList.add(changes);
  139 + mPendingChanges.clear();
  140 + Runnable changer = new Runnable() {
  141 + @Override
  142 + public void run() {
  143 + for (ChangeInfo change : changes) {
  144 + animateChangeImpl(change);
  145 + }
  146 + changes.clear();
  147 + mChangesList.remove(changes);
  148 + }
  149 + };
  150 + if (removalsPending) {
  151 + RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
  152 + ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
  153 + } else {
  154 + changer.run();
  155 + }
  156 + }
  157 + // Next, add stuff
  158 + if (additionsPending) {
  159 + final ArrayList<RecyclerView.ViewHolder> additions = new ArrayList<>();
  160 + additions.addAll(mPendingAdditions);
  161 + mAdditionsList.add(additions);
  162 + mPendingAdditions.clear();
  163 + Runnable adder = new Runnable() {
  164 + public void run() {
  165 + for (RecyclerView.ViewHolder holder : additions) {
  166 + animateAddImpl(holder);
  167 + }
  168 + additions.clear();
  169 + mAdditionsList.remove(additions);
  170 + }
  171 + };
  172 + if (removalsPending || movesPending || changesPending) {
  173 + long removeDuration = removalsPending ? getRemoveDuration() : 0;
  174 + long moveDuration = movesPending ? getMoveDuration() : 0;
  175 + long changeDuration = changesPending ? getChangeDuration() : 0;
  176 + long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
  177 + View view = additions.get(0).itemView;
  178 + ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
  179 + } else {
  180 + adder.run();
  181 + }
  182 + }
  183 + }
  184 +
  185 + @Override
  186 + public boolean animateAdd(final RecyclerView.ViewHolder holder) {
  187 + resetAnimation(holder);
  188 + prepareAnimateAdd(holder);
  189 + ViewCompat.setAlpha(holder.itemView, 0);
  190 + mPendingAdditions.add(holder);
  191 + return true;
  192 + }
  193 +
  194 + protected abstract void prepareAnimateAdd(final RecyclerView.ViewHolder holder);
  195 +
  196 + protected abstract void animateAddImpl(final RecyclerView.ViewHolder holder);
  197 +
  198 + @Override
  199 + public boolean animateRemove(final RecyclerView.ViewHolder holder) {
  200 + resetAnimation(holder);
  201 + mPendingRemovals.add(holder);
  202 + return true;
  203 + }
  204 +
  205 + protected abstract void animateRemoveImpl(final RecyclerView.ViewHolder holder);
  206 +
  207 + @Override
  208 + public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
  209 + int toX, int toY) {
  210 + final View view = holder.itemView;
  211 + fromX += ViewCompat.getTranslationX(holder.itemView);
  212 + fromY += ViewCompat.getTranslationY(holder.itemView);
  213 + resetAnimation(holder);
  214 + int deltaX = toX - fromX;
  215 + int deltaY = toY - fromY;
  216 + if (deltaX == 0 && deltaY == 0) {
  217 + dispatchMoveFinished(holder);
  218 + return false;
  219 + }
  220 + if (deltaX != 0) {
  221 + ViewCompat.setTranslationX(view, -deltaX);
  222 + }
  223 + if (deltaY != 0) {
  224 + ViewCompat.setTranslationY(view, -deltaY);
  225 + }
  226 + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
  227 + return true;
  228 + }
  229 +
  230 +
  231 + private void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
  232 + final View view = holder.itemView;
  233 + final int deltaX = toX - fromX;
  234 + final int deltaY = toY - fromY;
  235 + if (deltaX != 0) {
  236 + ViewCompat.animate(view).translationX(0);
  237 + }
  238 + if (deltaY != 0) {
  239 + ViewCompat.animate(view).translationY(0);
  240 + }
  241 + // TODO: make EndActions end listeners instead, since end actions aren't called when
  242 + // vpas are canceled (and can't end them. why?)
  243 + // need listener functionality in VPACompat for this. Ick.
  244 + final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
  245 + mMoveAnimations.add(holder);
  246 + animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() {
  247 + @Override
  248 + public void onAnimationStart(View view) {
  249 + dispatchMoveStarting(holder);
  250 + }
  251 + @Override
  252 + public void onAnimationCancel(View view) {
  253 + if (deltaX != 0) {
  254 + ViewCompat.setTranslationX(view, 0);
  255 + }
  256 + if (deltaY != 0) {
  257 + ViewCompat.setTranslationY(view, 0);
  258 + }
  259 + }
  260 + @Override
  261 + public void onAnimationEnd(View view) {
  262 + animation.setListener(null);
  263 + dispatchMoveFinished(holder);
  264 + mMoveAnimations.remove(holder);
  265 + dispatchFinishedWhenDone();
  266 + }
  267 + }).start();
  268 + }
  269 +
  270 + @Override
  271 + public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
  272 + int fromX, int fromY, int toX, int toY) {
  273 + if (oldHolder == newHolder) {
  274 + // Don't know how to run change animations when the same view holder is re-used.
  275 + // run a move animation to handle position changes.
  276 + return animateMove(oldHolder, fromX, fromY, toX, toY);
  277 + }
  278 + final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView);
  279 + final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);
  280 + final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
  281 + resetAnimation(oldHolder);
  282 + int deltaX = (int) (toX - fromX - prevTranslationX);
  283 + int deltaY = (int) (toY - fromY - prevTranslationY);
  284 + // recover prev translation state after ending animation
  285 + ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);
  286 + ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);
  287 + ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
  288 + if (newHolder != null) {
  289 + // carry over translation values
  290 + resetAnimation(newHolder);
  291 + ViewCompat.setTranslationX(newHolder.itemView, -deltaX);
  292 + ViewCompat.setTranslationY(newHolder.itemView, -deltaY);
  293 + ViewCompat.setAlpha(newHolder.itemView, 0);
  294 + }
  295 + mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
  296 + return true;
  297 + }
  298 +
  299 + private void animateChangeImpl(final ChangeInfo changeInfo) {
  300 + final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
  301 + final View view = holder == null ? null : holder.itemView;
  302 + final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
  303 + final View newView = newHolder != null ? newHolder.itemView : null;
  304 + if (view != null) {
  305 + final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration(
  306 + getChangeDuration());
  307 + mChangeAnimations.add(changeInfo.oldHolder);
  308 + oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
  309 + oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
  310 + oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {
  311 + @Override
  312 + public void onAnimationStart(View view) {
  313 + dispatchChangeStarting(changeInfo.oldHolder, true);
  314 + }
  315 +
  316 + @Override
  317 + public void onAnimationEnd(View view) {
  318 + oldViewAnim.setListener(null);
  319 + ViewCompat.setAlpha(view, 1);
  320 + ViewCompat.setTranslationX(view, 0);
  321 + ViewCompat.setTranslationY(view, 0);
  322 + dispatchChangeFinished(changeInfo.oldHolder, true);
  323 + mChangeAnimations.remove(changeInfo.oldHolder);
  324 + dispatchFinishedWhenDone();
  325 + }
  326 + }).start();
  327 + }
  328 + if (newView != null) {
  329 + final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView);
  330 + mChangeAnimations.add(changeInfo.newHolder);
  331 + newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
  332 + alpha(1).setListener(new VpaListenerAdapter() {
  333 + @Override
  334 + public void onAnimationStart(View view) {
  335 + dispatchChangeStarting(changeInfo.newHolder, false);
  336 + }
  337 + @Override
  338 + public void onAnimationEnd(View view) {
  339 + newViewAnimation.setListener(null);
  340 + ViewCompat.setAlpha(newView, 1);
  341 + ViewCompat.setTranslationX(newView, 0);
  342 + ViewCompat.setTranslationY(newView, 0);
  343 + dispatchChangeFinished(changeInfo.newHolder, false);
  344 + mChangeAnimations.remove(changeInfo.newHolder);
  345 + dispatchFinishedWhenDone();
  346 + }
  347 + }).start();
  348 + }
  349 + }
  350 +
  351 + private void endChangeAnimation(List<ChangeInfo> infoList, RecyclerView.ViewHolder item) {
  352 + for (int i = infoList.size() - 1; i >= 0; i--) {
  353 + ChangeInfo changeInfo = infoList.get(i);
  354 + if (endChangeAnimationIfNecessary(changeInfo, item)) {
  355 + if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
  356 + infoList.remove(changeInfo);
  357 + }
  358 + }
  359 + }
  360 + }
  361 +
  362 + private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
  363 + if (changeInfo.oldHolder != null) {
  364 + endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
  365 + }
  366 + if (changeInfo.newHolder != null) {
  367 + endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
  368 + }
  369 + }
  370 + private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) {
  371 + boolean oldItem = false;
  372 + if (changeInfo.newHolder == item) {
  373 + changeInfo.newHolder = null;
  374 + } else if (changeInfo.oldHolder == item) {
  375 + changeInfo.oldHolder = null;
  376 + oldItem = true;
  377 + } else {
  378 + return false;
  379 + }
  380 + ViewCompat.setAlpha(item.itemView, 1);
  381 + ViewCompat.setTranslationX(item.itemView, 0);
  382 + ViewCompat.setTranslationY(item.itemView, 0);
  383 + dispatchChangeFinished(item, oldItem);
  384 + return true;
  385 + }
  386 +
  387 + @Override
  388 + public void endAnimation(RecyclerView.ViewHolder item) {
  389 + final View view = item.itemView;
  390 + // this will trigger end callback which should set properties to their target values.
  391 + ViewCompat.animate(view).cancel();
  392 + // TODO if some other animations are chained to end, how do we cancel them as well?
  393 + for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
  394 + MoveInfo moveInfo = mPendingMoves.get(i);
  395 + if (moveInfo.holder == item) {
  396 + ViewCompat.setTranslationY(view, 0);
  397 + ViewCompat.setTranslationX(view, 0);
  398 + dispatchMoveFinished(item);
  399 + mPendingMoves.remove(i);
  400 + }
  401 + }
  402 + endChangeAnimation(mPendingChanges, item);
  403 + if (mPendingRemovals.remove(item)) {
  404 + ViewCompat.setAlpha(view, 1);
  405 + dispatchRemoveFinished(item);
  406 + }
  407 + if (mPendingAdditions.remove(item)) {
  408 + ViewCompat.setAlpha(view, 1);
  409 + dispatchAddFinished(item);
  410 + }
  411 +
  412 + for (int i = mChangesList.size() - 1; i >= 0; i--) {
  413 + ArrayList<ChangeInfo> changes = mChangesList.get(i);
  414 + endChangeAnimation(changes, item);
  415 + if (changes.isEmpty()) {
  416 + mChangesList.remove(i);
  417 + }
  418 + }
  419 + for (int i = mMovesList.size() - 1; i >= 0; i--) {
  420 + ArrayList<MoveInfo> moves = mMovesList.get(i);
  421 + for (int j = moves.size() - 1; j >= 0; j--) {
  422 + MoveInfo moveInfo = moves.get(j);
  423 + if (moveInfo.holder == item) {
  424 + ViewCompat.setTranslationY(view, 0);
  425 + ViewCompat.setTranslationX(view, 0);
  426 + dispatchMoveFinished(item);
  427 + moves.remove(j);
  428 + if (moves.isEmpty()) {
  429 + mMovesList.remove(i);
  430 + }
  431 + break;
  432 + }
  433 + }
  434 + }
  435 + for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
  436 + ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
  437 + if (additions.remove(item)) {
  438 + ViewCompat.setAlpha(view, 1);
  439 + dispatchAddFinished(item);
  440 + if (additions.isEmpty()) {
  441 + mAdditionsList.remove(i);
  442 + }
  443 + }
  444 + }
  445 +
  446 + // animations should be ended by the cancel above.
  447 + //noinspection PointlessBooleanExpression,ConstantConditions
  448 + if (mRemoveAnimations.remove(item) && DEBUG) {
  449 + throw new IllegalStateException("after animation is cancelled, item should not be in "
  450 + + "mRemoveAnimations list");
  451 + }
  452 +
  453 + //noinspection PointlessBooleanExpression,ConstantConditions
  454 + if (mAddAnimations.remove(item) && DEBUG) {
  455 + throw new IllegalStateException("after animation is cancelled, item should not be in "
  456 + + "mAddAnimations list");
  457 + }
  458 +
  459 + //noinspection PointlessBooleanExpression,ConstantConditions
  460 + if (mChangeAnimations.remove(item) && DEBUG) {
  461 + throw new IllegalStateException("after animation is cancelled, item should not be in "
  462 + + "mChangeAnimations list");
  463 + }
  464 +
  465 + //noinspection PointlessBooleanExpression,ConstantConditions
  466 + if (mMoveAnimations.remove(item) && DEBUG) {
  467 + throw new IllegalStateException("after animation is cancelled, item should not be in "
  468 + + "mMoveAnimations list");
  469 + }
  470 + dispatchFinishedWhenDone();
  471 + }
  472 +
  473 + private void resetAnimation(RecyclerView.ViewHolder holder) {
  474 +// AnimatorCompatHelper.clearInterpolator(holder.itemView);
  475 + endAnimation(holder);
  476 + }
  477 +
  478 + @Override
  479 + public boolean isRunning() {
  480 + return (!mPendingAdditions.isEmpty() ||
  481 + !mPendingChanges.isEmpty() ||
  482 + !mPendingMoves.isEmpty() ||
  483 + !mPendingRemovals.isEmpty() ||
  484 + !mMoveAnimations.isEmpty() ||
  485 + !mRemoveAnimations.isEmpty() ||
  486 + !mAddAnimations.isEmpty() ||
  487 + !mChangeAnimations.isEmpty() ||
  488 + !mMovesList.isEmpty() ||
  489 + !mAdditionsList.isEmpty() ||
  490 + !mChangesList.isEmpty());
  491 + }
  492 +
  493 + /**
  494 + * Check the state of currently pending and running animations. If there are none
  495 + * pending/running, call {@link #dispatchAnimationsFinished()} to notify any
  496 + * listeners.
  497 + */
  498 + protected void dispatchFinishedWhenDone() {
  499 + if (!isRunning()) {
  500 + dispatchAnimationsFinished();
  501 + }
  502 + }
  503 +
  504 + @Override
  505 + public void endAnimations() {
  506 + int count = mPendingMoves.size();
  507 + for (int i = count - 1; i >= 0; i--) {
  508 + MoveInfo item = mPendingMoves.get(i);
  509 + View view = item.holder.itemView;
  510 + ViewCompat.setTranslationY(view, 0);
  511 + ViewCompat.setTranslationX(view, 0);
  512 + dispatchMoveFinished(item.holder);
  513 + mPendingMoves.remove(i);
  514 + }
  515 + count = mPendingRemovals.size();
  516 + for (int i = count - 1; i >= 0; i--) {
  517 + RecyclerView.ViewHolder item = mPendingRemovals.get(i);
  518 + dispatchRemoveFinished(item);
  519 + mPendingRemovals.remove(i);
  520 + }
  521 + count = mPendingAdditions.size();
  522 + for (int i = count - 1; i >= 0; i--) {
  523 + RecyclerView.ViewHolder item = mPendingAdditions.get(i);
  524 + View view = item.itemView;
  525 + ViewCompat.setAlpha(view, 1);
  526 + dispatchAddFinished(item);
  527 + mPendingAdditions.remove(i);
  528 + }
  529 + count = mPendingChanges.size();
  530 + for (int i = count - 1; i >= 0; i--) {
  531 + endChangeAnimationIfNecessary(mPendingChanges.get(i));
  532 + }
  533 + mPendingChanges.clear();
  534 + if (!isRunning()) {
  535 + return;
  536 + }
  537 +
  538 + int listCount = mMovesList.size();
  539 + for (int i = listCount - 1; i >= 0; i--) {
  540 + ArrayList<MoveInfo> moves = mMovesList.get(i);
  541 + count = moves.size();
  542 + for (int j = count - 1; j >= 0; j--) {
  543 + MoveInfo moveInfo = moves.get(j);
  544 + RecyclerView.ViewHolder item = moveInfo.holder;
  545 + View view = item.itemView;
  546 + ViewCompat.setTranslationY(view, 0);
  547 + ViewCompat.setTranslationX(view, 0);
  548 + dispatchMoveFinished(moveInfo.holder);
  549 + moves.remove(j);
  550 + if (moves.isEmpty()) {
  551 + mMovesList.remove(moves);
  552 + }
  553 + }
  554 + }
  555 + listCount = mAdditionsList.size();
  556 + for (int i = listCount - 1; i >= 0; i--) {
  557 + ArrayList<RecyclerView.ViewHolder> additions = mAdditionsList.get(i);
  558 + count = additions.size();
  559 + for (int j = count - 1; j >= 0; j--) {
  560 + RecyclerView.ViewHolder item = additions.get(j);
  561 + View view = item.itemView;
  562 + ViewCompat.setAlpha(view, 1);
  563 + dispatchAddFinished(item);
  564 + additions.remove(j);
  565 + if (additions.isEmpty()) {
  566 + mAdditionsList.remove(additions);
  567 + }
  568 + }
  569 + }
  570 + listCount = mChangesList.size();
  571 + for (int i = listCount - 1; i >= 0; i--) {
  572 + ArrayList<ChangeInfo> changes = mChangesList.get(i);
  573 + count = changes.size();
  574 + for (int j = count - 1; j >= 0; j--) {
  575 + endChangeAnimationIfNecessary(changes.get(j));
  576 + if (changes.isEmpty()) {
  577 + mChangesList.remove(changes);
  578 + }
  579 + }
  580 + }
  581 +
  582 + cancelAll(mRemoveAnimations);
  583 + cancelAll(mMoveAnimations);
  584 + cancelAll(mAddAnimations);
  585 + cancelAll(mChangeAnimations);
  586 +
  587 + dispatchAnimationsFinished();
  588 + }
  589 +
  590 + void cancelAll(List<RecyclerView.ViewHolder> viewHolders) {
  591 + for (int i = viewHolders.size() - 1; i >= 0; i--) {
  592 + ViewCompat.animate(viewHolders.get(i).itemView).cancel();
  593 + }
  594 + }
  595 +
  596 +
  597 + protected static class VpaListenerAdapter implements ViewPropertyAnimatorListener {
  598 + @Override
  599 + public void onAnimationStart(View view) {}
  600 +
  601 + @Override
  602 + public void onAnimationEnd(View view) {}
  603 +
  604 + @Override
  605 + public void onAnimationCancel(View view) {}
  606 + };
  607 +}
0 608 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/animator/SlideInOutBottomItemAnimator.java 0 → 100644
... ... @@ -0,0 +1,91 @@
  1 +package com.shunzhi.mychartlibrary.animator;
  2 +
  3 +import android.support.v4.view.ViewCompat;
  4 +import android.support.v4.view.ViewPropertyAnimatorCompat;
  5 +import android.support.v7.widget.RecyclerView;
  6 +import android.view.View;
  7 +
  8 +/**
  9 + * Created by Mao Jiqing on 2016/9/30.
  10 + */
  11 +public class SlideInOutBottomItemAnimator extends BaseItemAnimator {
  12 +
  13 + private float mOriginalY;
  14 + private float mDeltaY;
  15 +
  16 + public SlideInOutBottomItemAnimator(RecyclerView recyclerView) {
  17 + super(recyclerView);
  18 + }
  19 +
  20 + protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
  21 + final View view = holder.itemView;
  22 +
  23 + final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
  24 + mRemoveAnimations.add(holder);
  25 + animation.setDuration(getRemoveDuration())
  26 + .alpha(0)
  27 + .translationY(+mDeltaY)
  28 + .setListener(new VpaListenerAdapter() {
  29 + @Override
  30 + public void onAnimationStart(View view) {
  31 + dispatchRemoveStarting(holder);
  32 + }
  33 +
  34 + @Override
  35 + public void onAnimationEnd(View view) {
  36 + animation.setListener(null);
  37 + ViewCompat.setAlpha(view, 1);
  38 + ViewCompat.setTranslationY(view, +mDeltaY);
  39 + dispatchRemoveFinished(holder);
  40 + mRemoveAnimations.remove(holder);
  41 + dispatchFinishedWhenDone();
  42 + }
  43 + }).start();
  44 + }
  45 +
  46 + @Override
  47 + protected void prepareAnimateAdd(RecyclerView.ViewHolder holder) {
  48 + retrieveItemPosition(holder);
  49 + ViewCompat.setTranslationY(holder.itemView, +mDeltaY);
  50 + }
  51 +
  52 + protected void animateAddImpl(final RecyclerView.ViewHolder holder) {
  53 + final View view = holder.itemView;
  54 +
  55 + final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
  56 + mAddAnimations.add(holder);
  57 + animation.translationY(0)
  58 + .alpha(1)
  59 + .setDuration(getAddDuration())
  60 + .setListener(new VpaListenerAdapter() {
  61 + @Override
  62 + public void onAnimationStart(View view) {
  63 + dispatchAddStarting(holder);
  64 + }
  65 +
  66 + @Override
  67 + public void onAnimationCancel(View view) {
  68 + ViewCompat.setAlpha(view, 1);
  69 + ViewCompat.setTranslationY(view, 0);
  70 + }
  71 +
  72 + @Override
  73 + public void onAnimationEnd(View view) {
  74 + animation.setListener(null);
  75 + ViewCompat.setAlpha(view, 1);
  76 + ViewCompat.setTranslationY(view, 0);
  77 + dispatchAddFinished(holder);
  78 + mAddAnimations.remove(holder);
  79 + dispatchFinishedWhenDone();
  80 + }
  81 + }).start();
  82 + }
  83 +
  84 +
  85 + private void retrieveItemPosition(final RecyclerView.ViewHolder holder) {
  86 + mOriginalY = mRecyclerView.getLayoutManager().getDecoratedTop(holder.itemView);
  87 + mDeltaY = mRecyclerView.getHeight() - mOriginalY;
  88 + }
  89 +
  90 +
  91 +}
0 92 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/common/ChatConst.java 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +package com.shunzhi.mychartlibrary.common;
  2 +
  3 +import android.support.annotation.IntDef;
  4 +
  5 +import java.lang.annotation.Retention;
  6 +import java.lang.annotation.RetentionPolicy;
  7 +
  8 +/**
  9 + * Created by Mao Jiqing on 2016/10/15.
  10 + */
  11 +
  12 +public class ChatConst {
  13 + public static final String LISTVIEW_DATABASE_NAME = "listview.db";
  14 + public static final String RECYCLER_DATABASE_NAME = "recycler.db";
  15 + public static final int SENDING = 0;
  16 + public static final int COMPLETED = 1;
  17 + public static final int SENDERROR = 2;
  18 +
  19 + @IntDef({SENDING, COMPLETED, SENDERROR})
  20 + @Retention(RetentionPolicy.SOURCE)
  21 + public @interface SendState {
  22 + }
  23 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/BaseManager.java 0 → 100644
... ... @@ -0,0 +1,355 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +import android.content.Context;
  4 +import android.database.sqlite.SQLiteDatabase;
  5 +import android.database.sqlite.SQLiteException;
  6 +import android.support.annotation.NonNull;
  7 +import android.support.annotation.Nullable;
  8 +
  9 +
  10 +
  11 +import org.greenrobot.greendao.AbstractDao;
  12 +import org.greenrobot.greendao.query.Query;
  13 +import org.greenrobot.greendao.query.QueryBuilder;
  14 +
  15 +import java.util.Collection;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * Created by Mao Jiqing on 2016/10/15.
  20 + */
  21 +
  22 +public abstract class BaseManager<M, K> implements IDatabase<M, K> {
  23 + private static final String DEFAULT_DATABASE_NAME = "maxi.db";
  24 + private static DaoMaster.DevOpenHelper mHelper;
  25 + protected static DaoSession daoSession;
  26 +
  27 + /**
  28 + * 初始化OpenHelper
  29 + *
  30 + * @param context
  31 + */
  32 + public static void initOpenHelper(@NonNull Context context) {
  33 + mHelper = getOpenHelper(context, DEFAULT_DATABASE_NAME);
  34 + openWritableDb();
  35 + }
  36 +
  37 + /**
  38 + * 初始化OpenHelper
  39 + *
  40 + * @param context
  41 + * @param dataBaseName
  42 + */
  43 + public static void initOpenHelper(@NonNull Context context, @NonNull String dataBaseName) {
  44 + mHelper = getOpenHelper(context, dataBaseName);
  45 + openWritableDb();
  46 + }
  47 +
  48 + /**
  49 + * Query for readable DB
  50 + */
  51 + protected static void openReadableDb() throws SQLiteException {
  52 + daoSession = new DaoMaster(getReadableDatabase()).newSession();
  53 + }
  54 +
  55 + /**
  56 + * Query for writable DB
  57 + */
  58 + protected static void openWritableDb() throws SQLiteException {
  59 + daoSession = new DaoMaster(getWritableDatabase()).newSession();
  60 + }
  61 +
  62 + private static SQLiteDatabase getWritableDatabase() {
  63 + return mHelper.getWritableDatabase();
  64 + }
  65 +
  66 + private static SQLiteDatabase getReadableDatabase() {
  67 + return mHelper.getReadableDatabase();
  68 + }
  69 +
  70 + /**
  71 + * 在applicaiton中初始化DatabaseHelper
  72 + */
  73 + private static DaoMaster.DevOpenHelper getOpenHelper(@NonNull Context context, @Nullable String dataBaseName) {
  74 + closeDbConnections();
  75 + return new DaoMaster.DevOpenHelper(context, dataBaseName, null);
  76 + }
  77 +
  78 + /**
  79 + * 只关闭helper就好,看源码就知道helper关闭的时候会关闭数据库
  80 + */
  81 + public static void closeDbConnections() {
  82 + if (mHelper != null) {
  83 + mHelper.close();
  84 + mHelper = null;
  85 + }
  86 + if (daoSession != null) {
  87 + daoSession.clear();
  88 + daoSession = null;
  89 + }
  90 + }
  91 +
  92 + @Override
  93 + public void clearDaoSession() {
  94 + if (daoSession != null) {
  95 + daoSession.clear();
  96 + daoSession = null;
  97 + }
  98 + }
  99 +
  100 + @Override
  101 + public boolean dropDatabase() {
  102 + try {
  103 + openWritableDb();
  104 + } catch (Exception e) {
  105 + return false;
  106 + }
  107 + return true;
  108 + }
  109 +
  110 + @Override
  111 + public boolean insert(@NonNull M m) {
  112 + try {
  113 + if (m == null)
  114 + return false;
  115 + openWritableDb();
  116 + getAbstractDao().insert(m);
  117 + } catch (SQLiteException e) {
  118 + return false;
  119 + }
  120 + return true;
  121 + }
  122 +
  123 + @Override
  124 + public boolean insertOrReplace(@NonNull M m) {
  125 + try {
  126 + if (m == null)
  127 + return false;
  128 + openWritableDb();
  129 + getAbstractDao().insertOrReplace(m);
  130 + } catch (SQLiteException e) {
  131 + return false;
  132 + }
  133 + return true;
  134 + }
  135 +
  136 + @Override
  137 + public boolean delete(@NonNull M m) {
  138 + try {
  139 + if (m == null)
  140 + return false;
  141 + openWritableDb();
  142 + getAbstractDao().delete(m);
  143 + } catch (SQLiteException e) {
  144 + return false;
  145 + }
  146 + return true;
  147 + }
  148 +
  149 + @Override
  150 + public boolean deleteByKey(K key) {
  151 + try {
  152 + if (key.toString().isEmpty())
  153 + return false;
  154 + openWritableDb();
  155 + getAbstractDao().deleteByKey(key);
  156 + } catch (SQLiteException e) {
  157 + return false;
  158 + }
  159 + return true;
  160 + }
  161 +
  162 + @Override
  163 + public boolean deleteByKeyInTx(K... key) {
  164 + try {
  165 + openWritableDb();
  166 + getAbstractDao().deleteByKeyInTx(key);
  167 + } catch (SQLiteException e) {
  168 + return false;
  169 + }
  170 + return true;
  171 + }
  172 +
  173 + @Override
  174 + public boolean deleteList(List<M> mList) {
  175 + try {
  176 + if (mList == null || mList.size() == 0)
  177 + return false;
  178 + openWritableDb();
  179 + getAbstractDao().deleteInTx(mList);
  180 + } catch (SQLiteException e) {
  181 + return false;
  182 + }
  183 + return true;
  184 + }
  185 +
  186 + @Override
  187 + public boolean deleteAll() {
  188 + try {
  189 + openWritableDb();
  190 + getAbstractDao().deleteAll();
  191 + } catch (SQLiteException e) {
  192 + return false;
  193 + }
  194 + return true;
  195 + }
  196 +
  197 + @Override
  198 + public boolean update(@NonNull M m) {
  199 + try {
  200 + if (m == null)
  201 + return false;
  202 + openWritableDb();
  203 + getAbstractDao().update(m);
  204 + } catch (SQLiteException e) {
  205 + return false;
  206 + }
  207 + return true;
  208 + }
  209 +
  210 + @Override
  211 + public boolean updateInTx(M... m) {
  212 + try {
  213 + if (m == null)
  214 + return false;
  215 + openWritableDb();
  216 + getAbstractDao().updateInTx(m);
  217 + } catch (SQLiteException e) {
  218 + return false;
  219 + }
  220 + return true;
  221 + }
  222 +
  223 + @Override
  224 + public boolean updateList(List<M> mList) {
  225 + try {
  226 + if (mList == null || mList.size() == 0)
  227 + return false;
  228 + openWritableDb();
  229 + getAbstractDao().updateInTx(mList);
  230 + } catch (SQLiteException e) {
  231 + return false;
  232 + }
  233 + return true;
  234 + }
  235 +
  236 + @Override
  237 + public M selectByPrimaryKey(@NonNull K key) {
  238 + try {
  239 + openReadableDb();
  240 + return getAbstractDao().load(key);
  241 + } catch (SQLiteException e) {
  242 + return null;
  243 + }
  244 + }
  245 +
  246 + @Override
  247 + public List<M> loadAll() {
  248 + openReadableDb();
  249 + return getAbstractDao().loadAll();
  250 + }
  251 +
  252 + @Override
  253 + public List<M> loadPages(int page, int number) {
  254 + openReadableDb();
  255 + return getAbstractDao().queryBuilder()
  256 + .offset(page * number).limit(number).list();
  257 + }
  258 +
  259 + @Override
  260 + public long getPages(int number) {
  261 + long count = getAbstractDao().queryBuilder().count();
  262 + long page = count / number;
  263 + if (page > 0 && count % number == 0) {
  264 + return page - 1;
  265 + }
  266 + return page;
  267 + }
  268 +
  269 + @Override
  270 + public boolean refresh(@NonNull M m) {
  271 + try {
  272 + if (m == null)
  273 + return false;
  274 + openWritableDb();
  275 + getAbstractDao().refresh(m);
  276 + } catch (SQLiteException e) {
  277 + return false;
  278 + }
  279 + return true;
  280 + }
  281 +
  282 + @Override
  283 + public void runInTx(Runnable runnable) {
  284 + try {
  285 + openWritableDb();
  286 + daoSession.runInTx(runnable);
  287 + } catch (SQLiteException e) {
  288 + }
  289 + }
  290 +
  291 + @Override
  292 + public boolean insertList(@NonNull List<M> list) {
  293 + try {
  294 + if (list == null || list.size() == 0)
  295 + return false;
  296 + openWritableDb();
  297 + getAbstractDao().insertInTx(list);
  298 + } catch (SQLiteException e) {
  299 + return false;
  300 + }
  301 + return true;
  302 + }
  303 +
  304 + /**
  305 + * @param list
  306 + * @return
  307 + */
  308 + @Override
  309 + public boolean insertOrReplaceList(@NonNull List<M> list) {
  310 + try {
  311 + if (list == null || list.size() == 0)
  312 + return false;
  313 + openWritableDb();
  314 + getAbstractDao().insertOrReplaceInTx(list);
  315 + } catch (SQLiteException e) {
  316 + return false;
  317 + }
  318 + return true;
  319 + }
  320 +
  321 + @Override
  322 + public QueryBuilder<M> getQueryBuilder() {
  323 + openReadableDb();
  324 + return getAbstractDao().queryBuilder();
  325 + }
  326 +
  327 + /**
  328 + * @param where
  329 + * @param selectionArg
  330 + * @return
  331 + */
  332 + @Override
  333 + public List<M> queryRaw(String where, String... selectionArg) {
  334 + openReadableDb();
  335 + return getAbstractDao().queryRaw(where, selectionArg);
  336 + }
  337 +
  338 + public Query<M> queryRawCreate(String where, Object... selectionArg) {
  339 + openReadableDb();
  340 + return getAbstractDao().queryRawCreate(where, selectionArg);
  341 + }
  342 +
  343 + public Query<M> queryRawCreateListArgs(String where, Collection<Object> selectionArg) {
  344 + openReadableDb();
  345 + return getAbstractDao().queryRawCreateListArgs(where, selectionArg);
  346 + }
  347 +
  348 + /**
  349 + * 获取Dao
  350 + *
  351 + * @return
  352 + */
  353 + public abstract AbstractDao<M, K> getAbstractDao();
  354 +
  355 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/ChatDbManager.java 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +
  4 +
  5 +import org.greenrobot.greendao.AbstractDao;
  6 +
  7 +/**
  8 + * Created by Mao Jiqing on 2016/10/15.
  9 + */
  10 +
  11 +public class ChatDbManager extends BaseManager<ChatMessageBean,Long> {
  12 + @Override
  13 + public AbstractDao<ChatMessageBean, Long> getAbstractDao() {
  14 + return BaseManager.daoSession.getChatMessageBeanDao();
  15 + }
  16 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/ChatMessageBean.java 0 → 100644
... ... @@ -0,0 +1,194 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +/**
  4 + * Created by Mao Jiqing on 2016/10/15.
  5 + */
  6 +
  7 +
  8 +import com.shunzhi.mychartlibrary.common.ChatConst;
  9 +
  10 +import org.greenrobot.greendao.annotation.Entity;
  11 +import org.greenrobot.greendao.annotation.Generated;
  12 +import org.greenrobot.greendao.annotation.Id;
  13 +import org.greenrobot.greendao.annotation.Property;
  14 +
  15 +@Entity
  16 +public class ChatMessageBean {
  17 + @Id
  18 + private Long id;
  19 + @Property(nameInDb = "UserId")
  20 + private String UserId;
  21 + @Property(nameInDb = "UserName")
  22 + private String UserName;
  23 + @Property(nameInDb = "UserHeadIcon")
  24 + private String UserHeadIcon;
  25 + @Property(nameInDb = "UserContent")
  26 + private String UserContent;
  27 + @Property(nameInDb = "time")
  28 + private String time;
  29 + @Property(nameInDb = "type")
  30 + private int type;
  31 + @Property(nameInDb = "messagetype")
  32 + private int messagetype;
  33 + @Property(nameInDb = "UserVoiceTime")
  34 + private float UserVoiceTime;
  35 + @Property(nameInDb = "UserVoicePath")
  36 + private String UserVoicePath;
  37 + @Property(nameInDb = "UserVoiceUrl")
  38 + private String UserVoiceUrl;
  39 + @Property(nameInDb = "sendState")
  40 + private @ChatConst.SendState int sendState;
  41 + @Property(nameInDb = "imageUrl")
  42 + private String imageUrl;
  43 + @Property(nameInDb = "imageIconUrl")
  44 + private String imageIconUrl;
  45 + @Property(nameInDb = "imageLocal")
  46 + private String imageLocal;
  47 +
  48 + @Generated(hash = 1463432601)
  49 + public ChatMessageBean(Long id, String UserId, String UserName,
  50 + String UserHeadIcon, String UserContent, String time, int type,
  51 + int messagetype, float UserVoiceTime, String UserVoicePath,
  52 + String UserVoiceUrl, int sendState, String imageUrl,
  53 + String imageIconUrl, String imageLocal) {
  54 + this.id = id;
  55 + this.UserId = UserId;
  56 + this.UserName = UserName;
  57 + this.UserHeadIcon = UserHeadIcon;
  58 + this.UserContent = UserContent;
  59 + this.time = time;
  60 + this.type = type;
  61 + this.messagetype = messagetype;
  62 + this.UserVoiceTime = UserVoiceTime;
  63 + this.UserVoicePath = UserVoicePath;
  64 + this.UserVoiceUrl = UserVoiceUrl;
  65 + this.sendState = sendState;
  66 + this.imageUrl = imageUrl;
  67 + this.imageIconUrl = imageIconUrl;
  68 + this.imageLocal = imageLocal;
  69 + }
  70 +
  71 + @Generated(hash = 1557449535)
  72 + public ChatMessageBean() {
  73 + }
  74 +
  75 + public Long getId() {
  76 + return this.id;
  77 + }
  78 +
  79 + public void setId(Long id) {
  80 + this.id = id;
  81 + }
  82 +
  83 + public String getUserId() {
  84 + return this.UserId;
  85 + }
  86 +
  87 + public void setUserId(String UserId) {
  88 + this.UserId = UserId;
  89 + }
  90 +
  91 + public String getUserName() {
  92 + return this.UserName;
  93 + }
  94 +
  95 + public void setUserName(String UserName) {
  96 + this.UserName = UserName;
  97 + }
  98 +
  99 + public String getUserHeadIcon() {
  100 + return this.UserHeadIcon;
  101 + }
  102 +
  103 + public void setUserHeadIcon(String UserHeadIcon) {
  104 + this.UserHeadIcon = UserHeadIcon;
  105 + }
  106 +
  107 + public String getUserContent() {
  108 + return this.UserContent;
  109 + }
  110 +
  111 + public void setUserContent(String UserContent) {
  112 + this.UserContent = UserContent;
  113 + }
  114 +
  115 + public String getTime() {
  116 + return this.time;
  117 + }
  118 +
  119 + public void setTime(String time) {
  120 + this.time = time;
  121 + }
  122 +
  123 + public int getType() {
  124 + return this.type;
  125 + }
  126 +
  127 + public void setType(int type) {
  128 + this.type = type;
  129 + }
  130 +
  131 + public int getMessagetype() {
  132 + return this.messagetype;
  133 + }
  134 +
  135 + public void setMessagetype(int messagetype) {
  136 + this.messagetype = messagetype;
  137 + }
  138 +
  139 + public float getUserVoiceTime() {
  140 + return this.UserVoiceTime;
  141 + }
  142 +
  143 + public void setUserVoiceTime(float UserVoiceTime) {
  144 + this.UserVoiceTime = UserVoiceTime;
  145 + }
  146 +
  147 + public String getUserVoicePath() {
  148 + return this.UserVoicePath;
  149 + }
  150 +
  151 + public void setUserVoicePath(String UserVoicePath) {
  152 + this.UserVoicePath = UserVoicePath;
  153 + }
  154 +
  155 + public String getUserVoiceUrl() {
  156 + return this.UserVoiceUrl;
  157 + }
  158 +
  159 + public void setUserVoiceUrl(String UserVoiceUrl) {
  160 + this.UserVoiceUrl = UserVoiceUrl;
  161 + }
  162 +
  163 + public int getSendState() {
  164 + return this.sendState;
  165 + }
  166 +
  167 + public void setSendState(int sendState) {
  168 + this.sendState = sendState;
  169 + }
  170 +
  171 + public String getImageUrl() {
  172 + return this.imageUrl;
  173 + }
  174 +
  175 + public void setImageUrl(String imageUrl) {
  176 + this.imageUrl = imageUrl;
  177 + }
  178 +
  179 + public String getImageIconUrl() {
  180 + return this.imageIconUrl;
  181 + }
  182 +
  183 + public void setImageIconUrl(String imageIconUrl) {
  184 + this.imageIconUrl = imageIconUrl;
  185 + }
  186 +
  187 + public String getImageLocal() {
  188 + return this.imageLocal;
  189 + }
  190 +
  191 + public void setImageLocal(String imageLocal) {
  192 + this.imageLocal = imageLocal;
  193 + }
  194 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/ChatMessageBeanDao1.java 0 → 100644
... ... @@ -0,0 +1,277 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +import android.database.Cursor;
  4 +import android.database.sqlite.SQLiteStatement;
  5 +
  6 +import org.greenrobot.greendao.AbstractDao;
  7 +import org.greenrobot.greendao.Property;
  8 +import org.greenrobot.greendao.internal.DaoConfig;
  9 +import org.greenrobot.greendao.database.Database;
  10 +import org.greenrobot.greendao.database.DatabaseStatement;
  11 +
  12 +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
  13 +/**
  14 + * DAO for table "CHAT_MESSAGE_BEAN".
  15 +*/
  16 +public class ChatMessageBeanDao1 extends AbstractDao<ChatMessageBean, Long> {
  17 +
  18 + public static final String TABLENAME = "CHAT_MESSAGE_BEAN";
  19 +
  20 + /**
  21 + * Properties of entity ChatMessageBean.<br/>
  22 + * Can be used for QueryBuilder and for referencing column names.
  23 + */
  24 + public static class Properties {
  25 + public final static Property Id = new Property(0, Long.class, "id", true, "_id");
  26 + public final static Property UserId = new Property(1, String.class, "UserId", false, "UserId");
  27 + public final static Property UserName = new Property(2, String.class, "UserName", false, "UserName");
  28 + public final static Property UserHeadIcon = new Property(3, String.class, "UserHeadIcon", false, "UserHeadIcon");
  29 + public final static Property UserContent = new Property(4, String.class, "UserContent", false, "UserContent");
  30 + public final static Property Time = new Property(5, String.class, "time", false, "time");
  31 + public final static Property Type = new Property(6, int.class, "type", false, "type");
  32 + public final static Property Messagetype = new Property(7, int.class, "messagetype", false, "messagetype");
  33 + public final static Property UserVoiceTime = new Property(8, float.class, "UserVoiceTime", false, "UserVoiceTime");
  34 + public final static Property UserVoicePath = new Property(9, String.class, "UserVoicePath", false, "UserVoicePath");
  35 + public final static Property UserVoiceUrl = new Property(10, String.class, "UserVoiceUrl", false, "UserVoiceUrl");
  36 + public final static Property SendState = new Property(11, int.class, "sendState", false, "sendState");
  37 + public final static Property ImageUrl = new Property(12, String.class, "imageUrl", false, "imageUrl");
  38 + public final static Property ImageIconUrl = new Property(13, String.class, "imageIconUrl", false, "imageIconUrl");
  39 + public final static Property ImageLocal = new Property(14, String.class, "imageLocal", false, "imageLocal");
  40 + }
  41 +
  42 +
  43 + public ChatMessageBeanDao1(DaoConfig config) {
  44 + super(config);
  45 + }
  46 +
  47 + public ChatMessageBeanDao1(DaoConfig config, DaoSession daoSession) {
  48 + super(config, daoSession);
  49 + }
  50 +
  51 + /** Creates the underlying database table. */
  52 + public static void createTable(Database db, boolean ifNotExists) {
  53 + String constraint = ifNotExists? "IF NOT EXISTS ": "";
  54 + db.execSQL("CREATE TABLE " + constraint + "\"CHAT_MESSAGE_BEAN\" (" + //
  55 + "\"_id\" INTEGER PRIMARY KEY ," + // 0: id
  56 + "\"UserId\" TEXT," + // 1: UserId
  57 + "\"UserName\" TEXT," + // 2: UserName
  58 + "\"UserHeadIcon\" TEXT," + // 3: UserHeadIcon
  59 + "\"UserContent\" TEXT," + // 4: UserContent
  60 + "\"time\" TEXT," + // 5: time
  61 + "\"type\" INTEGER NOT NULL ," + // 6: type
  62 + "\"messagetype\" INTEGER NOT NULL ," + // 7: messagetype
  63 + "\"UserVoiceTime\" REAL NOT NULL ," + // 8: UserVoiceTime
  64 + "\"UserVoicePath\" TEXT," + // 9: UserVoicePath
  65 + "\"UserVoiceUrl\" TEXT," + // 10: UserVoiceUrl
  66 + "\"sendState\" INTEGER NOT NULL ," + // 11: sendState
  67 + "\"imageUrl\" TEXT," + // 12: imageUrl
  68 + "\"imageIconUrl\" TEXT," + // 13: imageIconUrl
  69 + "\"imageLocal\" TEXT);"); // 14: imageLocal
  70 + }
  71 +
  72 + /** Drops the underlying database table. */
  73 + public static void dropTable(Database db, boolean ifExists) {
  74 + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"CHAT_MESSAGE_BEAN\"";
  75 + db.execSQL(sql);
  76 + }
  77 +
  78 + @Override
  79 + protected final void bindValues(DatabaseStatement stmt, ChatMessageBean entity) {
  80 + stmt.clearBindings();
  81 +
  82 + Long id = entity.getId();
  83 + if (id != null) {
  84 + stmt.bindLong(1, id);
  85 + }
  86 +
  87 + String UserId = entity.getUserId();
  88 + if (UserId != null) {
  89 + stmt.bindString(2, UserId);
  90 + }
  91 +
  92 + String UserName = entity.getUserName();
  93 + if (UserName != null) {
  94 + stmt.bindString(3, UserName);
  95 + }
  96 +
  97 + String UserHeadIcon = entity.getUserHeadIcon();
  98 + if (UserHeadIcon != null) {
  99 + stmt.bindString(4, UserHeadIcon);
  100 + }
  101 +
  102 + String UserContent = entity.getUserContent();
  103 + if (UserContent != null) {
  104 + stmt.bindString(5, UserContent);
  105 + }
  106 +
  107 + String time = entity.getTime();
  108 + if (time != null) {
  109 + stmt.bindString(6, time);
  110 + }
  111 + stmt.bindLong(7, entity.getType());
  112 + stmt.bindLong(8, entity.getMessagetype());
  113 + stmt.bindDouble(9, entity.getUserVoiceTime());
  114 +
  115 + String UserVoicePath = entity.getUserVoicePath();
  116 + if (UserVoicePath != null) {
  117 + stmt.bindString(10, UserVoicePath);
  118 + }
  119 +
  120 + String UserVoiceUrl = entity.getUserVoiceUrl();
  121 + if (UserVoiceUrl != null) {
  122 + stmt.bindString(11, UserVoiceUrl);
  123 + }
  124 + stmt.bindLong(12, entity.getSendState());
  125 +
  126 + String imageUrl = entity.getImageUrl();
  127 + if (imageUrl != null) {
  128 + stmt.bindString(13, imageUrl);
  129 + }
  130 +
  131 + String imageIconUrl = entity.getImageIconUrl();
  132 + if (imageIconUrl != null) {
  133 + stmt.bindString(14, imageIconUrl);
  134 + }
  135 +
  136 + String imageLocal = entity.getImageLocal();
  137 + if (imageLocal != null) {
  138 + stmt.bindString(15, imageLocal);
  139 + }
  140 + }
  141 +
  142 + @Override
  143 + protected final void bindValues(SQLiteStatement stmt, ChatMessageBean entity) {
  144 + stmt.clearBindings();
  145 +
  146 + Long id = entity.getId();
  147 + if (id != null) {
  148 + stmt.bindLong(1, id);
  149 + }
  150 +
  151 + String UserId = entity.getUserId();
  152 + if (UserId != null) {
  153 + stmt.bindString(2, UserId);
  154 + }
  155 +
  156 + String UserName = entity.getUserName();
  157 + if (UserName != null) {
  158 + stmt.bindString(3, UserName);
  159 + }
  160 +
  161 + String UserHeadIcon = entity.getUserHeadIcon();
  162 + if (UserHeadIcon != null) {
  163 + stmt.bindString(4, UserHeadIcon);
  164 + }
  165 +
  166 + String UserContent = entity.getUserContent();
  167 + if (UserContent != null) {
  168 + stmt.bindString(5, UserContent);
  169 + }
  170 +
  171 + String time = entity.getTime();
  172 + if (time != null) {
  173 + stmt.bindString(6, time);
  174 + }
  175 + stmt.bindLong(7, entity.getType());
  176 + stmt.bindLong(8, entity.getMessagetype());
  177 + stmt.bindDouble(9, entity.getUserVoiceTime());
  178 +
  179 + String UserVoicePath = entity.getUserVoicePath();
  180 + if (UserVoicePath != null) {
  181 + stmt.bindString(10, UserVoicePath);
  182 + }
  183 +
  184 + String UserVoiceUrl = entity.getUserVoiceUrl();
  185 + if (UserVoiceUrl != null) {
  186 + stmt.bindString(11, UserVoiceUrl);
  187 + }
  188 + stmt.bindLong(12, entity.getSendState());
  189 +
  190 + String imageUrl = entity.getImageUrl();
  191 + if (imageUrl != null) {
  192 + stmt.bindString(13, imageUrl);
  193 + }
  194 +
  195 + String imageIconUrl = entity.getImageIconUrl();
  196 + if (imageIconUrl != null) {
  197 + stmt.bindString(14, imageIconUrl);
  198 + }
  199 +
  200 + String imageLocal = entity.getImageLocal();
  201 + if (imageLocal != null) {
  202 + stmt.bindString(15, imageLocal);
  203 + }
  204 + }
  205 +
  206 + @Override
  207 + public Long readKey(Cursor cursor, int offset) {
  208 + return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
  209 + }
  210 +
  211 + @Override
  212 + public ChatMessageBean readEntity(Cursor cursor, int offset) {
  213 + ChatMessageBean entity = new ChatMessageBean( //
  214 + cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
  215 + cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // UserId
  216 + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // UserName
  217 + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // UserHeadIcon
  218 + cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // UserContent
  219 + cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // time
  220 + cursor.getInt(offset + 6), // type
  221 + cursor.getInt(offset + 7), // messagetype
  222 + cursor.getFloat(offset + 8), // UserVoiceTime
  223 + cursor.isNull(offset + 9) ? null : cursor.getString(offset + 9), // UserVoicePath
  224 + cursor.isNull(offset + 10) ? null : cursor.getString(offset + 10), // UserVoiceUrl
  225 + cursor.getInt(offset + 11), // sendState
  226 + cursor.isNull(offset + 12) ? null : cursor.getString(offset + 12), // imageUrl
  227 + cursor.isNull(offset + 13) ? null : cursor.getString(offset + 13), // imageIconUrl
  228 + cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14) // imageLocal
  229 + );
  230 + return entity;
  231 + }
  232 +
  233 + @Override
  234 + public void readEntity(Cursor cursor, ChatMessageBean entity, int offset) {
  235 + entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
  236 + entity.setUserId(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
  237 + entity.setUserName(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
  238 + entity.setUserHeadIcon(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
  239 + entity.setUserContent(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
  240 + entity.setTime(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));
  241 + entity.setType(cursor.getInt(offset + 6));
  242 + entity.setMessagetype(cursor.getInt(offset + 7));
  243 + entity.setUserVoiceTime(cursor.getFloat(offset + 8));
  244 + entity.setUserVoicePath(cursor.isNull(offset + 9) ? null : cursor.getString(offset + 9));
  245 + entity.setUserVoiceUrl(cursor.isNull(offset + 10) ? null : cursor.getString(offset + 10));
  246 + entity.setSendState(cursor.getInt(offset + 11));
  247 + entity.setImageUrl(cursor.isNull(offset + 12) ? null : cursor.getString(offset + 12));
  248 + entity.setImageIconUrl(cursor.isNull(offset + 13) ? null : cursor.getString(offset + 13));
  249 + entity.setImageLocal(cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14));
  250 + }
  251 +
  252 + @Override
  253 + protected final Long updateKeyAfterInsert(ChatMessageBean entity, long rowId) {
  254 + entity.setId(rowId);
  255 + return rowId;
  256 + }
  257 +
  258 + @Override
  259 + public Long getKey(ChatMessageBean entity) {
  260 + if(entity != null) {
  261 + return entity.getId();
  262 + } else {
  263 + return null;
  264 + }
  265 + }
  266 +
  267 + @Override
  268 + public boolean hasKey(ChatMessageBean entity) {
  269 + return entity.getId() != null;
  270 + }
  271 +
  272 + @Override
  273 + protected final boolean isEntityUpdateable() {
  274 + return true;
  275 + }
  276 +
  277 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/DaoMaster.java 0 → 100644
... ... @@ -0,0 +1,96 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +import android.content.Context;
  4 +import android.database.sqlite.SQLiteDatabase;
  5 +import android.database.sqlite.SQLiteDatabase.CursorFactory;
  6 +import android.util.Log;
  7 +
  8 +import org.greenrobot.greendao.AbstractDaoMaster;
  9 +import org.greenrobot.greendao.database.StandardDatabase;
  10 +import org.greenrobot.greendao.database.Database;
  11 +import org.greenrobot.greendao.database.DatabaseOpenHelper;
  12 +import org.greenrobot.greendao.identityscope.IdentityScopeType;
  13 +
  14 +
  15 +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
  16 +/**
  17 + * Master of DAO (schema version 1): knows all DAOs.
  18 + */
  19 +public class DaoMaster extends AbstractDaoMaster {
  20 + public static final int SCHEMA_VERSION = 1;
  21 +
  22 + /** Creates underlying database table using DAOs. */
  23 + public static void createAllTables(Database db, boolean ifNotExists) {
  24 + ChatMessageBeanDao1.createTable(db, ifNotExists);
  25 + }
  26 +
  27 + /** Drops underlying database table using DAOs. */
  28 + public static void dropAllTables(Database db, boolean ifExists) {
  29 + ChatMessageBeanDao1.dropTable(db, ifExists);
  30 + }
  31 +
  32 + /**
  33 + * WARNING: Drops all table on Upgrade! Use only during development.
  34 + * Convenience method using a {@link DevOpenHelper}.
  35 + */
  36 + public static DaoSession newDevSession(Context context, String name) {
  37 + Database db = new DevOpenHelper(context, name).getWritableDb();
  38 + DaoMaster daoMaster = new DaoMaster(db);
  39 + return daoMaster.newSession();
  40 + }
  41 +
  42 + public DaoMaster(SQLiteDatabase db) {
  43 + this(new StandardDatabase(db));
  44 + }
  45 +
  46 + public DaoMaster(Database db) {
  47 + super(db, SCHEMA_VERSION);
  48 + registerDaoClass(ChatMessageBeanDao1.class);
  49 + }
  50 +
  51 + public DaoSession newSession() {
  52 + return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
  53 + }
  54 +
  55 + public DaoSession newSession(IdentityScopeType type) {
  56 + return new DaoSession(db, type, daoConfigMap);
  57 + }
  58 +
  59 + /**
  60 + * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
  61 + */
  62 + public static abstract class OpenHelper extends DatabaseOpenHelper {
  63 + public OpenHelper(Context context, String name) {
  64 + super(context, name, SCHEMA_VERSION);
  65 + }
  66 +
  67 + public OpenHelper(Context context, String name, CursorFactory factory) {
  68 + super(context, name, factory, SCHEMA_VERSION);
  69 + }
  70 +
  71 + @Override
  72 + public void onCreate(Database db) {
  73 + Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
  74 + createAllTables(db, false);
  75 + }
  76 + }
  77 +
  78 + /** WARNING: Drops all table on Upgrade! Use only during development. */
  79 + public static class DevOpenHelper extends OpenHelper {
  80 + public DevOpenHelper(Context context, String name) {
  81 + super(context, name);
  82 + }
  83 +
  84 + public DevOpenHelper(Context context, String name, CursorFactory factory) {
  85 + super(context, name, factory);
  86 + }
  87 +
  88 + @Override
  89 + public void onUpgrade(Database db, int oldVersion, int newVersion) {
  90 + Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
  91 + dropAllTables(db, true);
  92 + onCreate(db);
  93 + }
  94 + }
  95 +
  96 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/DaoSession.java 0 → 100644
... ... @@ -0,0 +1,45 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import org.greenrobot.greendao.AbstractDao;
  6 +import org.greenrobot.greendao.AbstractDaoSession;
  7 +import org.greenrobot.greendao.database.Database;
  8 +import org.greenrobot.greendao.identityscope.IdentityScopeType;
  9 +import org.greenrobot.greendao.internal.DaoConfig;
  10 +
  11 +
  12 +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
  13 +
  14 +/**
  15 + * {@inheritDoc}
  16 + *
  17 + * @see AbstractDaoSession
  18 + */
  19 +public class DaoSession extends AbstractDaoSession {
  20 +
  21 + private final DaoConfig chatMessageBeanDaoConfig;
  22 +
  23 + private final ChatMessageBeanDao1 chatMessageBeanDao;
  24 +
  25 + public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
  26 + daoConfigMap) {
  27 + super(db);
  28 +
  29 + chatMessageBeanDaoConfig = daoConfigMap.get(ChatMessageBeanDao1.class).clone();
  30 + chatMessageBeanDaoConfig.initIdentityScope(type);
  31 +
  32 + chatMessageBeanDao = new ChatMessageBeanDao1(chatMessageBeanDaoConfig, this);
  33 +
  34 + registerDao(ChatMessageBean.class, chatMessageBeanDao);
  35 + }
  36 +
  37 + public void clear() {
  38 + chatMessageBeanDaoConfig.clearIdentityScope();
  39 + }
  40 +
  41 + public ChatMessageBeanDao1 getChatMessageBeanDao() {
  42 + return chatMessageBeanDao;
  43 + }
  44 +
  45 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/db/IDatabase.java 0 → 100644
... ... @@ -0,0 +1,98 @@
  1 +package com.shunzhi.mychartlibrary.db;
  2 +
  3 +import android.support.annotation.NonNull;
  4 +
  5 +import org.greenrobot.greendao.query.QueryBuilder;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * Created by Mao Jiqing on 2016/10/15.
  11 + */
  12 +
  13 +public interface IDatabase<M, K> {
  14 + boolean insert(M m);
  15 +
  16 + boolean delete(M m);
  17 +
  18 + boolean deleteByKey(K key);
  19 +
  20 + boolean deleteList(List<M> mList);
  21 +
  22 + boolean deleteByKeyInTx(K... key);
  23 +
  24 + boolean deleteAll();
  25 +
  26 + boolean insertOrReplace(@NonNull M m);
  27 +
  28 + boolean update(M m);
  29 +
  30 + boolean updateInTx(M... m);
  31 +
  32 + boolean updateList(List<M> mList);
  33 +
  34 + M selectByPrimaryKey(K key);
  35 +
  36 + List<M> loadAll();
  37 +
  38 + /**
  39 + * 分页加载
  40 + * @param page 设定当前页数
  41 + * @param number 设定一页显示数量
  42 + * @return
  43 + */
  44 + List<M> loadPages(int page, int number);
  45 +
  46 + /**
  47 + * 获取分页数
  48 + * @param number 设定一页显示数量
  49 + * @return
  50 + */
  51 + long getPages(int number);
  52 +
  53 + boolean refresh(M m);
  54 +
  55 + /**
  56 + * 清理缓存
  57 + */
  58 + void clearDaoSession();
  59 +
  60 + /**
  61 + * Delete all tables and content from our database
  62 + */
  63 + boolean dropDatabase();
  64 +
  65 + /**
  66 + * 事务
  67 + */
  68 + void runInTx(Runnable runnable);
  69 +
  70 + /**
  71 + * 添加集合
  72 + *
  73 + * @param mList
  74 + */
  75 + boolean insertList(List<M> mList);
  76 +
  77 + /**
  78 + * 添加集合
  79 + *
  80 + * @param mList
  81 + */
  82 + boolean insertOrReplaceList(List<M> mList);
  83 +
  84 + /**
  85 + * 自定义查询
  86 + *
  87 + * @return
  88 + */
  89 + QueryBuilder<M> getQueryBuilder();
  90 +
  91 + /**
  92 + * @param where
  93 + * @param selectionArg
  94 + * @return
  95 + */
  96 + List<M> queryRaw(String where, String... selectionArg);
  97 +
  98 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/AudioManager.java 0 → 100644
... ... @@ -0,0 +1,215 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.media.MediaRecorder;
  4 +import android.os.Handler;
  5 +
  6 +import java.io.File;
  7 +import java.io.IOException;
  8 +import java.util.HashSet;
  9 +import java.util.Set;
  10 +import java.util.UUID;
  11 +
  12 +public class AudioManager {
  13 + /**
  14 + * 录音的时候出错
  15 + */
  16 + public static final int MSG_ERROR_AUDIO_RECORD = -4;
  17 + private MediaRecorder mRecorder;
  18 + private String mDirString;
  19 + private String mCurrentFilePathString;
  20 + private Handler handler;
  21 + private boolean isPrepared;// 是否准备好了
  22 +
  23 + /**
  24 + * 单例化的方法 1 先声明一个static 类型的变量a 2 在声明默认的构造函数 3 再用public synchronized static
  25 + * 类名 getInstance() { if(a==null) { a=new 类();} return a; } 或者用以下的方法
  26 + */
  27 +
  28 + /**
  29 + * 单例化这个类
  30 + */
  31 + private static AudioManager mInstance;
  32 +
  33 + private AudioManager(String dir) {
  34 + mDirString = dir;
  35 + }
  36 +
  37 + public static AudioManager getInstance(String dir) {
  38 + if (mInstance == null) {
  39 + synchronized (AudioManager.class) {
  40 + if (mInstance == null) {
  41 + mInstance = new AudioManager(dir);
  42 +
  43 + }
  44 + }
  45 + }
  46 + return mInstance;
  47 +
  48 + }
  49 +
  50 + public void setHandle(Handler handler) {
  51 + this.handler = handler;
  52 + }
  53 +
  54 + /**
  55 + * 回调函数,准备完毕,准备好后,button才会开始显示录音框
  56 + *
  57 + */
  58 + public interface AudioStageListener {
  59 + void wellPrepared();
  60 + }
  61 +
  62 + public AudioStageListener mListener;
  63 +
  64 + public void setOnAudioStageListener(AudioStageListener listener) {
  65 + mListener = listener;
  66 + }
  67 +
  68 + public void setVocDir(String dir) {
  69 + mDirString = dir;
  70 + }
  71 +
  72 + // 准备方法
  73 + @SuppressWarnings("deprecation")
  74 + public void prepareAudio() {
  75 + try {
  76 + // 一开始应该是false的
  77 + isPrepared = false;
  78 +
  79 + File dir = new File(mDirString);
  80 + if (!dir.exists()) {
  81 + dir.mkdirs();
  82 + }
  83 +
  84 + String fileNameString = generalFileName();
  85 + File file = new File(dir, fileNameString);
  86 +
  87 + mCurrentFilePathString = file.getAbsolutePath();
  88 +
  89 + mRecorder = new MediaRecorder();
  90 + // 设置输出文件
  91 + mRecorder.setOutputFile(file.getAbsolutePath());
  92 + // 设置meidaRecorder的音频源是麦克风
  93 + mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
  94 + // 设置文件音频的输出格式为amr
  95 + mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
  96 + // 设置音频的编码格式为amr
  97 + mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
  98 +
  99 + // 严格遵守google官方api给出的mediaRecorder的状态流程图
  100 + mRecorder.prepare();
  101 +
  102 + mRecorder.start();
  103 + // 准备结束
  104 + // 已经准备好了,可以录制了
  105 + if (mListener != null) {
  106 + mListener.wellPrepared();
  107 + }
  108 + isPrepared = true;
  109 +
  110 + } catch (IllegalStateException e) {
  111 + // TODO Auto-generated catch block
  112 + e.printStackTrace();
  113 + if (handler != null) {
  114 + handler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);
  115 + }
  116 + } catch (IOException e) {
  117 + // TODO Auto-generated catch block
  118 + e.printStackTrace();
  119 + if (handler != null) {
  120 + handler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);
  121 + }
  122 + } catch (Exception e) {
  123 + e.printStackTrace();
  124 + if (handler != null) {
  125 + handler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);
  126 + }
  127 + }
  128 +
  129 + }
  130 +
  131 + /**
  132 + * 随机生成文件的名称
  133 + *
  134 + * @return
  135 + */
  136 + private String generalFileName() {
  137 + // TODO Auto-generated method stub
  138 +
  139 + return UUID.randomUUID().toString() + ".amr";
  140 + }
  141 +
  142 + private int vocAuthority[] = new int[10];
  143 + private int vocNum = 0;
  144 + private boolean check = true;
  145 +
  146 + // 获得声音的level
  147 + public int getVoiceLevel(int maxLevel) {
  148 + // mRecorder.getMaxAmplitude()这个是音频的振幅范围,值域是0-32767
  149 + if (isPrepared) {
  150 + try {
  151 + int vocLevel = mRecorder.getMaxAmplitude();
  152 + if (check) {
  153 + if (vocNum >= 10) {
  154 + Set<Integer> set = new HashSet<Integer>();
  155 + for (int i = 0; i < vocNum; i++) {
  156 + set.add(vocAuthority[i]);
  157 + }
  158 + if (set.size() == 1) {
  159 + if (handler != null)
  160 + handler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);
  161 + vocNum = 0;
  162 + vocAuthority = null;
  163 + vocAuthority = new int[10];
  164 + } else {
  165 + check = false;
  166 + }
  167 + } else {
  168 + vocAuthority[vocNum] = vocLevel;
  169 + vocNum++;
  170 + }
  171 + }
  172 + return maxLevel * vocLevel / 32768 + 1;
  173 + } catch (Exception e) {
  174 + // TODO Auto-generated catch block
  175 + if (handler != null)
  176 + handler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);
  177 + }
  178 + }
  179 +
  180 + return 1;
  181 + }
  182 +
  183 + // 释放资源
  184 + public void release() {
  185 + // 严格按照api流程进行
  186 + if (null != mRecorder) {
  187 + isPrepared = false;
  188 + try {
  189 + mRecorder.stop();
  190 + mRecorder.release();
  191 + } catch (Exception e) {
  192 + e.printStackTrace();
  193 + }
  194 + mRecorder = null;
  195 + }
  196 + }
  197 +
  198 + // 取消,因为prepare时产生了一个文件,所以cancel方法应该要删除这个文件,
  199 + // 这是与release的方法的区别
  200 + public void cancel() {
  201 + release();
  202 + if (mCurrentFilePathString != null) {
  203 + File file = new File(mCurrentFilePathString);
  204 + file.delete();
  205 + mCurrentFilePathString = null;
  206 + }
  207 +
  208 + }
  209 +
  210 + public String getCurrentFilePath() {
  211 + // TODO Auto-generated method stub
  212 + return mCurrentFilePathString;
  213 + }
  214 +
  215 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/FaceData.java 0 → 100644
... ... @@ -0,0 +1,102 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +
  4 +
  5 +import com.shunzhi.mychartlibrary.R;
  6 +
  7 +import java.util.HashMap;
  8 +import java.util.Map;
  9 +
  10 +public class FaceData {
  11 + public static Map<String, Integer> gifFaceInfo = new HashMap<String, Integer>();
  12 +
  13 + public static final String f1 = "[:f1]";
  14 + public static final String f2 = "[:f2]";
  15 + public static final String f3 = "[:f3]";
  16 + public static final String f4 = "[:f4]";
  17 + public static final String f5 = "[:f5]";
  18 + public static final String f6 = "[:f6]";
  19 + public static final String f7 = "[:f7]";
  20 + public static final String f8 = "[:f8]";
  21 + public static final String f9 = "[:f9]";
  22 + public static final String f10 = "[:f10]";
  23 + public static final String f11 = "[:f11]";
  24 + public static final String f12 = "[:f12]";
  25 + public static final String f13 = "[:f13]";
  26 + public static final String f14 = "[:f14]";
  27 + public static final String f15 = "[:f15]";
  28 + public static final String f16 = "[:f16]";
  29 + public static final String f17 = "[:f17]";
  30 + public static final String f18 = "[:f18]";
  31 + public static final String f19 = "[:f19]";
  32 + public static final String f20 = "[:f20]";
  33 + public static final String f21 = "[:f21]";
  34 + public static final String f22 = "[:f22]";
  35 + public static final String f23 = "[:f23]";
  36 + public static final String f24 = "[:f24]";
  37 + public static final String f25 = "[:f25]";
  38 + public static final String f26 = "[:f26]";
  39 + public static final String f27 = "[:f27]";
  40 + public static final String f28 = "[:f28]";
  41 + public static final String f29 = "[:f29]";
  42 + public static final String f30 = "[:f30]";
  43 + public static final String f31 = "[:f31]";
  44 + public static final String f32 = "[:f32]";
  45 + public static final String f33 = "[:f33]";
  46 + public static final String f34 = "[:f34]";
  47 + public static final String f35 = "[:f35]";
  48 + public static final String f36 = "[:f36]";
  49 + public static final String f37 = "[:f37]";
  50 + public static final String f38 = "[:f38]";
  51 + public static final String f39 = "[:f39]";
  52 + public static final String f40 = "[:f40]";
  53 +
  54 + static {
  55 +
  56 + addString(gifFaceInfo, f1, R.mipmap.f1);
  57 + addString(gifFaceInfo, f2, R.mipmap.f2);
  58 + addString(gifFaceInfo, f3, R.mipmap.f3);
  59 + addString(gifFaceInfo, f4, R.mipmap.f4);
  60 + addString(gifFaceInfo, f5, R.mipmap.f5);
  61 + addString(gifFaceInfo, f6, R.mipmap.f6);
  62 + addString(gifFaceInfo, f7, R.mipmap.f7);
  63 + addString(gifFaceInfo, f8, R.mipmap.f8);
  64 + addString(gifFaceInfo, f9, R.mipmap.f9);
  65 + addString(gifFaceInfo, f10, R.mipmap.f10);
  66 + addString(gifFaceInfo, f11, R.mipmap.f11);
  67 + addString(gifFaceInfo, f12, R.mipmap.f12);
  68 + addString(gifFaceInfo, f13, R.mipmap.f13);
  69 + addString(gifFaceInfo, f14, R.mipmap.f14);
  70 + addString(gifFaceInfo, f15, R.mipmap.f15);
  71 + addString(gifFaceInfo, f16, R.mipmap.f16);
  72 + addString(gifFaceInfo, f17, R.mipmap.f17);
  73 + addString(gifFaceInfo, f18, R.mipmap.f18);
  74 + addString(gifFaceInfo, f19, R.mipmap.f19);
  75 + addString(gifFaceInfo, f20, R.mipmap.f20);
  76 + addString(gifFaceInfo, f21, R.mipmap.f21);
  77 + addString(gifFaceInfo, f22, R.mipmap.f22);
  78 + addString(gifFaceInfo, f23, R.mipmap.f23);
  79 + addString(gifFaceInfo, f24, R.mipmap.f24);
  80 + addString(gifFaceInfo, f25, R.mipmap.f25);
  81 + addString(gifFaceInfo, f26, R.mipmap.f26);
  82 + addString(gifFaceInfo, f27, R.mipmap.f27);
  83 + addString(gifFaceInfo, f28, R.mipmap.f28);
  84 + addString(gifFaceInfo, f29, R.mipmap.f29);
  85 + addString(gifFaceInfo, f30, R.mipmap.f30);
  86 + addString(gifFaceInfo, f31, R.mipmap.f31);
  87 + addString(gifFaceInfo, f32, R.mipmap.f32);
  88 + addString(gifFaceInfo, f33, R.mipmap.f33);
  89 + addString(gifFaceInfo, f34, R.mipmap.f34);
  90 + addString(gifFaceInfo, f35, R.mipmap.f35);
  91 + addString(gifFaceInfo, f36, R.mipmap.f36);
  92 + addString(gifFaceInfo, f37, R.mipmap.f37);
  93 + addString(gifFaceInfo, f38, R.mipmap.f38);
  94 + addString(gifFaceInfo, f39, R.mipmap.f39);
  95 + addString(gifFaceInfo, f40, R.mipmap.f40);
  96 + }
  97 +
  98 + private static void addString(Map<String, Integer> map, String smile,
  99 + int resource) {
  100 + map.put(smile, resource);
  101 + }
  102 +}
0 103 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/FileSaveUtil.java 0 → 100644
... ... @@ -0,0 +1,372 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.annotation.TargetApi;
  5 +import android.content.ContentUris;
  6 +import android.content.Context;
  7 +import android.database.Cursor;
  8 +import android.graphics.Bitmap;
  9 +import android.net.Uri;
  10 +import android.os.Build;
  11 +import android.os.Environment;
  12 +import android.provider.DocumentsContract;
  13 +import android.provider.MediaStore;
  14 +import android.util.Base64;
  15 +
  16 +import java.io.BufferedReader;
  17 +import java.io.ByteArrayOutputStream;
  18 +import java.io.File;
  19 +import java.io.FileInputStream;
  20 +import java.io.FileNotFoundException;
  21 +import java.io.FileOutputStream;
  22 +import java.io.IOException;
  23 +import java.io.InputStream;
  24 +import java.io.InputStreamReader;
  25 +import java.util.ArrayList;
  26 +import java.util.List;
  27 +
  28 +public class FileSaveUtil {
  29 + public static final String SD_CARD_PATH = Environment.getExternalStorageDirectory().toString() + "/MAXI/";
  30 +
  31 + // public static final String saveFn = SD_CARD_PATH
  32 +// + "/user_chat_data/";
  33 +// public static final String savelistFn = SD_CARD_PATH
  34 +// + "/user_chat_data/chatList/";
  35 +// public static final String savechannelFn = SD_CARD_PATH
  36 +// + "/user_chat_data/channel_id/";
  37 +// public static final String saveUnReadFn = SD_CARD_PATH
  38 +// + "/user_chat_data/UnRead/";
  39 + public static final String voice_dir = SD_CARD_PATH
  40 + + "/voice_data/";
  41 +
  42 + /**
  43 + * SD卡是否存在
  44 + **/
  45 + private boolean hasSD = false;
  46 + /**
  47 + * 当前程序包的路径
  48 + **/
  49 + private String FILESPATH;
  50 +
  51 + public static boolean isFileExists(File file) {
  52 + if (!file.exists()) {
  53 + return false;
  54 + }
  55 + return true;
  56 + }
  57 +
  58 + /**
  59 + * 获取文件夹下的所有文件名
  60 + */
  61 + public static List<String> getFileName(String fileName) {
  62 + List<String> fileList = new ArrayList<String>();
  63 + String path = fileName; // 路径
  64 + File f = new File(path);
  65 + if (!f.exists()) {
  66 + System.out.println(path + " not exists");
  67 + return null;
  68 + }
  69 +
  70 + File fa[] = f.listFiles();
  71 + for (int i = 0; i < fa.length; i++) {
  72 + File fs = fa[i];
  73 + if (!fs.isDirectory()) {
  74 + fileList.add(fs.getName());
  75 + }
  76 + }
  77 + return fileList;
  78 + }
  79 +
  80 + /**
  81 + * 在SD卡上创建文件
  82 + *
  83 + * @throws IOException
  84 + */
  85 + public static File createSDFile(String fileName) throws IOException {
  86 + File file = new File(fileName);
  87 + if (!isFileExists(file))
  88 + if (file.isDirectory()) {
  89 + file.mkdirs();
  90 + } else {
  91 + file.createNewFile();
  92 + }
  93 + return file;
  94 + }
  95 +
  96 + /**
  97 + * 在SD卡上创建文件夹
  98 + *
  99 + * @throws IOException
  100 + */
  101 + public static File createSDDirectory(String fileName) throws IOException {
  102 + File file = new File(fileName);
  103 + if (!isFileExists(file))
  104 + file.mkdirs();
  105 + return file;
  106 + }
  107 +
  108 +// /**
  109 +// * @content 存储内容
  110 +// * @file 文件目录
  111 +// * @isAppend 是否追加
  112 +// */
  113 +// public synchronized static void writeString(String content, String file, boolean isAppend) {
  114 +// try {
  115 +// createSDDirectory(saveFn);
  116 +// createSDDirectory(savelistFn);
  117 +// createSDDirectory(savechannelFn);
  118 +// byte[] data = content.getBytes("utf-8");
  119 +// writeBytes(file, data, isAppend);
  120 +// } catch (Exception e) {
  121 +// System.out.println(e.getMessage());
  122 +// }
  123 +//
  124 +// }
  125 +
  126 + public synchronized static boolean writeBytes(String filePath, byte[] data,
  127 + boolean isAppend) {
  128 + try {
  129 + FileOutputStream fos;
  130 + if (isAppend)
  131 + fos = new FileOutputStream(filePath, true);
  132 + else
  133 + fos = new FileOutputStream(filePath);
  134 + fos.write(data);
  135 + fos.close();
  136 + return true;
  137 + } catch (Exception e) {
  138 + System.out.println(e.getMessage());
  139 + }
  140 + return false;
  141 + }
  142 +
  143 + /**
  144 + * 读取SD卡中文本文件
  145 + *
  146 + * @param fileName
  147 + * @return
  148 + */
  149 + public synchronized static String readSDFile(String fileName) {
  150 + StringBuffer sb = new StringBuffer();
  151 + File f1 = new File(fileName);
  152 + String str = null;
  153 + try {
  154 + InputStream is = new FileInputStream(f1);
  155 + InputStreamReader input = new InputStreamReader(is, "UTF-8");
  156 + @SuppressWarnings("resource")
  157 + BufferedReader reader = new BufferedReader(input);
  158 + while ((str = reader.readLine()) != null) {
  159 + sb.append(str);
  160 + }
  161 + } catch (FileNotFoundException e) {
  162 + // TODO Auto-generated catch block
  163 + e.printStackTrace();
  164 + } catch (IOException e) {
  165 + // TODO Auto-generated catch block
  166 + e.printStackTrace();
  167 + }
  168 + return sb.toString();
  169 + }
  170 +
  171 + public String getFILESPATH() {
  172 + return FILESPATH;
  173 + }
  174 +
  175 + public boolean hasSD() {
  176 + return hasSD;
  177 + }
  178 +
  179 + /**
  180 + * 删除单个文件
  181 + *
  182 + * @param filePath 被删除文件的文件名
  183 + * @return 文件删除成功返回true,否则返回false
  184 + */
  185 + public static boolean deleteFile(String filePath) {
  186 + File file = new File(filePath);
  187 + if (file.isFile() && file.exists()) {
  188 + return file.delete();
  189 + }
  190 + return false;
  191 + }
  192 +
  193 + /**
  194 + * 删除文件夹以及目录下的文件
  195 + *
  196 + * @param filePath 被删除目录的文件路径
  197 + * @return 目录删除成功返回true,否则返回false
  198 + */
  199 + public static boolean deleteDirectory(String filePath) {
  200 + boolean flag = false;
  201 + // 如果filePath不以文件分隔符结尾,自动添加文件分隔符
  202 + if (!filePath.endsWith(File.separator)) {
  203 + filePath = filePath + File.separator;
  204 + }
  205 + File dirFile = new File(filePath);
  206 + if (!dirFile.exists() || !dirFile.isDirectory()) {
  207 + return false;
  208 + }
  209 + flag = true;
  210 + File[] files = dirFile.listFiles();
  211 + // 遍历删除文件夹下的所有文件(包括子目录)
  212 + for (int i = 0; i < files.length; i++) {
  213 + if (files[i].isFile()) {
  214 + // 删除子文件
  215 + flag = deleteFile(files[i].getAbsolutePath());
  216 + if (!flag)
  217 + break;
  218 + } else {
  219 + // 删除子目录
  220 + flag = deleteDirectory(files[i].getAbsolutePath());
  221 + if (!flag)
  222 + break;
  223 + }
  224 + }
  225 + if (!flag)
  226 + return false;
  227 + // 删除当前空目录
  228 + return dirFile.delete();
  229 + }
  230 +
  231 + public static boolean saveBitmap(Bitmap bm, String picName) {
  232 + try {
  233 + File f = new File(picName);
  234 + if (f.exists()) {
  235 + f.delete();
  236 + }
  237 + FileOutputStream out = new FileOutputStream(f);
  238 + bm.compress(Bitmap.CompressFormat.PNG, 100, out);
  239 + out.flush();
  240 + out.close();
  241 + return true;
  242 + } catch (FileNotFoundException e) {
  243 + e.printStackTrace();
  244 + return false;
  245 + } catch (IOException e) {
  246 + e.printStackTrace();
  247 + return false;
  248 + }
  249 + }
  250 +
  251 + /**
  252 + * 把文件转换成base64
  253 + *
  254 + * @param path
  255 + * @return
  256 + */
  257 + public static String encodeBase64File(String path) throws Exception {
  258 + byte[] videoBytes;
  259 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  260 + @SuppressWarnings("resource")
  261 + FileInputStream fis = new FileInputStream(new File(path));
  262 + byte[] buf = new byte[1024];
  263 + int n;
  264 + while (-1 != (n = fis.read(buf)))
  265 + baos.write(buf, 0, n);
  266 + videoBytes = baos.toByteArray();
  267 + return Base64.encodeToString(videoBytes, Base64.NO_WRAP);
  268 + }
  269 +
  270 + /**
  271 + * 根据相册媒体库路径转换成sd卡路径
  272 + *
  273 + * @param context
  274 + * @param uri
  275 + * @return
  276 + */
  277 + @TargetApi(Build.VERSION_CODES.KITKAT)
  278 + public static String getPath(final Context context, final Uri uri) {
  279 + final boolean isOverKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  280 + // DocumentProvider
  281 + if (isOverKitKat && DocumentsContract.isDocumentUri(context, uri)) {
  282 + // ExternalStorageProvider
  283 + if (isExternalStorageDocument(uri)) {
  284 + final String docId = DocumentsContract.getDocumentId(uri);
  285 + final String[] split = docId.split(":");
  286 + final String type = split[0];
  287 + if ("primary".equalsIgnoreCase(type)) {
  288 + return Environment.getExternalStorageDirectory() + "/"
  289 + + split[1];
  290 + }
  291 + }
  292 + // DownloadsProvider
  293 + else if (isDownloadsDocument(uri)) {
  294 + final String id = DocumentsContract.getDocumentId(uri);
  295 + final Uri contentUri = ContentUris.withAppendedId(
  296 + Uri.parse("content://downloads/public_downloads"),
  297 + Long.valueOf(id));
  298 + return getDataColumn(context, contentUri, null, null);
  299 + }
  300 + // MediaProvider
  301 + else if (isMediaDocument(uri)) {
  302 + final String docId = DocumentsContract.getDocumentId(uri);
  303 + final String[] split = docId.split(":");
  304 + final String type = split[0];
  305 + Uri contentUri = null;
  306 + if ("image".equals(type)) {
  307 + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  308 + } else if ("video".equals(type)) {
  309 + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  310 + } else if ("audio".equals(type)) {
  311 + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  312 + }
  313 + final String selection = "_id=?";
  314 + final String[] selectionArgs = new String[]{split[1]};
  315 + return getDataColumn(context, contentUri, selection,
  316 + selectionArgs);
  317 + }
  318 + }
  319 + // MediaStore (and general)
  320 + else if ("content".equalsIgnoreCase(uri.getScheme())) {
  321 + // Return the remote address
  322 + if (isGooglePhotosUri(uri))
  323 + return uri.getLastPathSegment();
  324 + return getDataColumn(context, uri, null, null);
  325 + }
  326 + // File
  327 + else if ("file".equalsIgnoreCase(uri.getScheme())) {
  328 + return uri.getPath();
  329 + }
  330 + return null;
  331 + }
  332 +
  333 + @SuppressLint("NewApi")
  334 + public static String getDataColumn(Context context, Uri uri,
  335 + String selection, String[] selectionArgs) {
  336 + Cursor cursor = null;
  337 + final String column = "_data";
  338 + final String[] projection = {column};
  339 + try {
  340 + cursor = context.getContentResolver().query(uri, projection,
  341 + selection, selectionArgs, null);
  342 + if (cursor != null && cursor.moveToFirst()) {
  343 + final int index = cursor.getColumnIndexOrThrow(column);
  344 + return cursor.getString(index);
  345 + }
  346 + } finally {
  347 + if (cursor != null)
  348 + cursor.close();
  349 + }
  350 + return null;
  351 + }
  352 +
  353 + public static boolean isGooglePhotosUri(Uri uri) {
  354 + return "com.google.android.apps.photos.content".equals(uri
  355 + .getAuthority());
  356 + }
  357 +
  358 + public static boolean isDownloadsDocument(Uri uri) {
  359 + return "com.android.providers.downloads.documents".equals(uri
  360 + .getAuthority());
  361 + }
  362 +
  363 + public static boolean isMediaDocument(Uri uri) {
  364 + return "com.android.providers.media.documents".equals(uri
  365 + .getAuthority());
  366 + }
  367 +
  368 + public static boolean isExternalStorageDocument(Uri uri) {
  369 + return "com.android.externalstorage.documents".equals(uri
  370 + .getAuthority());
  371 + }
  372 +}
0 373 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/GifOpenHelper.java 0 → 100644
... ... @@ -0,0 +1,625 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.graphics.Bitmap;
  4 +import android.graphics.Bitmap.Config;
  5 +
  6 +import java.io.InputStream;
  7 +import java.util.Vector;
  8 +
  9 +//Handler for read & extract Bitmap from *.gif
  10 +public class GifOpenHelper {
  11 +
  12 + // to store *.gif data, Bitmap & delay
  13 + class GifFrame {
  14 + // to access image & delay w/o interface
  15 + public Bitmap image;
  16 + public int delay;
  17 +
  18 + public GifFrame(Bitmap im, int del) {
  19 + image = im;
  20 + delay = del;
  21 + }
  22 +
  23 + }
  24 +
  25 + // to define some error type
  26 + public static final int STATUS_OK = 0;
  27 + public static final int STATUS_FORMAT_ERROR = 1;
  28 + public static final int STATUS_OPEN_ERROR = 2;
  29 +
  30 + protected int status;
  31 +
  32 + protected InputStream in;
  33 +
  34 + protected int width; // full image width
  35 + protected int height; // full image height
  36 + protected boolean gctFlag; // global color table used
  37 + protected int gctSize; // size of global color table
  38 + protected int loopCount = 1; // iterations; 0 = repeat forever
  39 +
  40 + protected int[] gct; // global color table
  41 + protected int[] lct; // local color table
  42 + protected int[] act; // active color table
  43 +
  44 + protected int bgIndex; // background color index
  45 + protected int bgColor; // background color
  46 + protected int lastBgColor; // previous bg color
  47 + protected int pixelAspect; // pixel aspect ratio
  48 +
  49 + protected boolean lctFlag; // local color table flag
  50 + protected boolean interlace; // interlace flag
  51 + protected int lctSize; // local color table size
  52 +
  53 + protected int ix, iy, iw, ih; // current image rectangle
  54 + protected int lrx, lry, lrw, lrh;
  55 + protected Bitmap image; // current frame
  56 + protected Bitmap lastImage; // previous frame
  57 + protected int frameindex = 0;
  58 +
  59 + public int getFrameindex() {
  60 + return frameindex;
  61 + }
  62 +
  63 + public void setFrameindex(int frameindex) {
  64 + this.frameindex = frameindex;
  65 + if (frameindex > frames.size() - 1) {
  66 + frameindex = 0;
  67 + }
  68 + }
  69 +
  70 + protected byte[] block = new byte[256]; // current data block
  71 + protected int blockSize = 0; // block size
  72 +
  73 + // last graphic control extension info
  74 + protected int dispose = 0;
  75 + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
  76 + protected int lastDispose = 0;
  77 + protected boolean transparency = false; // use transparent color
  78 + protected int delay = 0; // delay in milliseconds
  79 + protected int transIndex; // transparent color index
  80 +
  81 + protected static final int MaxStackSize = 4096;
  82 + // max decoder pixel stack size
  83 +
  84 + // LZW decoder working arrays
  85 + protected short[] prefix;
  86 + protected byte[] suffix;
  87 + protected byte[] pixelStack;
  88 + protected byte[] pixels;
  89 +
  90 + protected Vector<GifFrame> frames; // frames read from current file
  91 + protected int frameCount;
  92 +
  93 + // to get its Width / Height
  94 + public int getWidth() {
  95 + return width;
  96 + }
  97 +
  98 + public int getHeigh() {
  99 + return height;
  100 + }
  101 +
  102 + /**
  103 + * Gets display duration for specified frame.
  104 + *
  105 + * @param n
  106 + * int index of frame
  107 + * @return delay in milliseconds
  108 + */
  109 + public int getDelay(int n) {
  110 + delay = -1;
  111 + if ((n >= 0) && (n < frameCount)) {
  112 + delay = ((GifFrame) frames.elementAt(n)).delay;
  113 + }
  114 + return delay;
  115 + }
  116 +
  117 + public int getFrameCount() {
  118 + return frameCount;
  119 + }
  120 +
  121 + public Bitmap getImage() {
  122 + return getFrame(0);
  123 + }
  124 +
  125 + public int getLoopCount() {
  126 + return loopCount;
  127 + }
  128 +
  129 + protected void setPixels() {
  130 + int[] dest = new int[width * height];
  131 + // fill in starting image contents based on last image's dispose code
  132 + if (lastDispose > 0) {
  133 + if (lastDispose == 3) {
  134 + // use image before last
  135 + int n = frameCount - 2;
  136 + if (n > 0) {
  137 + lastImage = getFrame(n - 1);
  138 + } else {
  139 + lastImage = null;
  140 + }
  141 + }
  142 + if (lastImage != null) {
  143 + lastImage.getPixels(dest, 0, width, 0, 0, width, height);
  144 + // copy pixels
  145 + if (lastDispose == 2) {
  146 + // fill last image rect area with background color
  147 + int c = 0;
  148 + if (!transparency) {
  149 + c = lastBgColor;
  150 + }
  151 + for (int i = 0; i < lrh; i++) {
  152 + int n1 = (lry + i) * width + lrx;
  153 + int n2 = n1 + lrw;
  154 + for (int k = n1; k < n2; k++) {
  155 + dest[k] = c;
  156 + }
  157 + }
  158 + }
  159 + }
  160 + }
  161 +
  162 + // copy each source line to the appropriate place in the destination
  163 + int pass = 1;
  164 + int inc = 8;
  165 + int iline = 0;
  166 + for (int i = 0; i < ih; i++) {
  167 + int line = i;
  168 + if (interlace) {
  169 + if (iline >= ih) {
  170 + pass++;
  171 + switch (pass) {
  172 + case 2:
  173 + iline = 4;
  174 + break;
  175 + case 3:
  176 + iline = 2;
  177 + inc = 4;
  178 + break;
  179 + case 4:
  180 + iline = 1;
  181 + inc = 2;
  182 + }
  183 + }
  184 + line = iline;
  185 + iline += inc;
  186 + }
  187 + line += iy;
  188 + if (line < height) {
  189 + int k = line * width;
  190 + int dx = k + ix; // start of line in dest
  191 + int dlim = dx + iw; // end of dest line
  192 + if ((k + width) < dlim) {
  193 + dlim = k + width; // past dest edge
  194 + }
  195 + int sx = i * iw; // start of line in source
  196 + while (dx < dlim) {
  197 + // map color and insert in destination
  198 + int index = ((int) pixels[sx++]) & 0xff;
  199 + int c = act[index];
  200 + if (c != 0) {
  201 + dest[dx] = c;
  202 + }
  203 + dx++;
  204 + }
  205 + }
  206 + }
  207 + image = Bitmap.createBitmap(dest, width, height, Config.ARGB_4444);
  208 + }
  209 +
  210 + public Bitmap getFrame(int n) {
  211 + Bitmap im = null;
  212 + if ((n >= 0) && (n < frameCount)) {
  213 + im = ((GifFrame) frames.elementAt(n)).image;
  214 + }
  215 + return im;
  216 + }
  217 +
  218 + public Bitmap nextBitmap() {
  219 + frameindex++;
  220 + if (frameindex > frames.size() - 1) {
  221 + frameindex = 0;
  222 + }
  223 + return ((GifFrame) frames.elementAt(frameindex)).image;
  224 + }
  225 +
  226 + public int nextDelay() {
  227 + return ((GifFrame) frames.elementAt(frameindex)).delay;
  228 + }
  229 +
  230 + // to read & parse all *.gif stream
  231 + public int read(InputStream is) {
  232 + init();
  233 + if (is != null) {
  234 + in = is;
  235 +
  236 + readHeader();
  237 + if (!err()) {
  238 + readContents();
  239 + if (frameCount < 0) {
  240 + status = STATUS_FORMAT_ERROR;
  241 + }
  242 + }
  243 + } else {
  244 + status = STATUS_OPEN_ERROR;
  245 + }
  246 + try {
  247 + is.close();
  248 + } catch (Exception e) {
  249 + e.printStackTrace();
  250 + }
  251 + return status;
  252 + }
  253 +
  254 + protected void decodeImageData() {
  255 + int NullCode = -1;
  256 + int npix = iw * ih;
  257 + int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi;
  258 +
  259 + if ((pixels == null) || (pixels.length < npix)) {
  260 + pixels = new byte[npix]; // allocate new pixel array
  261 + }
  262 + if (prefix == null) {
  263 + prefix = new short[MaxStackSize];
  264 + }
  265 + if (suffix == null) {
  266 + suffix = new byte[MaxStackSize];
  267 + }
  268 + if (pixelStack == null) {
  269 + pixelStack = new byte[MaxStackSize + 1];
  270 + }
  271 + // Initialize GIF data stream decoder.
  272 + data_size = read();
  273 + clear = 1 << data_size;
  274 + end_of_information = clear + 1;
  275 + available = clear + 2;
  276 + old_code = NullCode;
  277 + code_size = data_size + 1;
  278 + code_mask = (1 << code_size) - 1;
  279 + for (code = 0; code < clear; code++) {
  280 + prefix[code] = 0;
  281 + suffix[code] = (byte) code;
  282 + }
  283 +
  284 + // Decode GIF pixel stream.
  285 + datum = bits = count = first = top = pi = bi = 0;
  286 + for (i = 0; i < npix;) {
  287 + if (top == 0) {
  288 + if (bits < code_size) {
  289 + // Load bytes until there are enough bits for a code.
  290 + if (count == 0) {
  291 + // Read a new data block.
  292 + count = readBlock();
  293 + if (count <= 0) {
  294 + break;
  295 + }
  296 + bi = 0;
  297 + }
  298 + datum += (((int) block[bi]) & 0xff) << bits;
  299 + bits += 8;
  300 + bi++;
  301 + count--;
  302 + continue;
  303 + }
  304 + // Get the next code.
  305 + code = datum & code_mask;
  306 + datum >>= code_size;
  307 + bits -= code_size;
  308 +
  309 + // Interpret the code
  310 + if ((code > available) || (code == end_of_information)) {
  311 + break;
  312 + }
  313 + if (code == clear) {
  314 + // Reset decoder.
  315 + code_size = data_size + 1;
  316 + code_mask = (1 << code_size) - 1;
  317 + available = clear + 2;
  318 + old_code = NullCode;
  319 + continue;
  320 + }
  321 + if (old_code == NullCode) {
  322 + pixelStack[top++] = suffix[code];
  323 + old_code = code;
  324 + first = code;
  325 + continue;
  326 + }
  327 + in_code = code;
  328 + if (code == available) {
  329 + pixelStack[top++] = (byte) first;
  330 + code = old_code;
  331 + }
  332 + while (code > clear) {
  333 + pixelStack[top++] = suffix[code];
  334 + code = prefix[code];
  335 + }
  336 + first = ((int) suffix[code]) & 0xff;
  337 + // Add a new string to the string table,
  338 + if (available >= MaxStackSize) {
  339 + break;
  340 + }
  341 + pixelStack[top++] = (byte) first;
  342 + prefix[available] = (short) old_code;
  343 + suffix[available] = (byte) first;
  344 + available++;
  345 + if (((available & code_mask) == 0)
  346 + && (available < MaxStackSize)) {
  347 + code_size++;
  348 + code_mask += available;
  349 + }
  350 + old_code = in_code;
  351 + }
  352 +
  353 + // Pop a pixel off the pixel stack.
  354 + top--;
  355 + pixels[pi++] = pixelStack[top];
  356 + i++;
  357 + }
  358 + for (i = pi; i < npix; i++) {
  359 + pixels[i] = 0; // clear missing pixels
  360 + }
  361 + }
  362 +
  363 + protected boolean err() {
  364 + return status != STATUS_OK;
  365 + }
  366 +
  367 + // to initia variable
  368 + public void init() {
  369 + status = STATUS_OK;
  370 + frameCount = 0;
  371 + frames = new Vector<GifFrame>();
  372 + gct = null;
  373 + lct = null;
  374 + }
  375 +
  376 + protected int read() {
  377 + int curByte = 0;
  378 + try {
  379 + curByte = in.read();
  380 + } catch (Exception e) {
  381 + status = STATUS_FORMAT_ERROR;
  382 + }
  383 + return curByte;
  384 + }
  385 +
  386 + protected int readBlock() {
  387 + blockSize = read();
  388 + int n = 0;
  389 + if (blockSize > 0) {
  390 + try {
  391 + int count = 0;
  392 + while (n < blockSize) {
  393 + count = in.read(block, n, blockSize - n);
  394 + if (count == -1) {
  395 + break;
  396 + }
  397 + n += count;
  398 + }
  399 + } catch (Exception e) {
  400 + e.printStackTrace();
  401 + }
  402 + if (n < blockSize) {
  403 + status = STATUS_FORMAT_ERROR;
  404 + }
  405 + }
  406 + return n;
  407 + }
  408 +
  409 + // Global Color Table
  410 + protected int[] readColorTable(int ncolors) {
  411 + int nbytes = 3 * ncolors;
  412 + int[] tab = null;
  413 + byte[] c = new byte[nbytes];
  414 + int n = 0;
  415 + try {
  416 + n = in.read(c);
  417 + } catch (Exception e) {
  418 + e.printStackTrace();
  419 + }
  420 + if (n < nbytes) {
  421 + status = STATUS_FORMAT_ERROR;
  422 + } else {
  423 + tab = new int[256]; // max size to avoid bounds checks
  424 + int i = 0;
  425 + int j = 0;
  426 + while (i < ncolors) {
  427 + int r = ((int) c[j++]) & 0xff;
  428 + int g = ((int) c[j++]) & 0xff;
  429 + int b = ((int) c[j++]) & 0xff;
  430 + tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
  431 + }
  432 + }
  433 + return tab;
  434 + }
  435 +
  436 + // Image Descriptor
  437 + protected void readContents() {
  438 + // read GIF file content blocks
  439 + boolean done = false;
  440 + while (!(done || err())) {
  441 + int code = read();
  442 + switch (code) {
  443 + case 0x2C: // image separator
  444 + readImage();
  445 + break;
  446 + case 0x21: // extension
  447 + code = read();
  448 + switch (code) {
  449 + case 0xf9: // graphics control extension
  450 + readGraphicControlExt();
  451 + break;
  452 +
  453 + case 0xff: // application extension
  454 + readBlock();
  455 + String app = "";
  456 + for (int i = 0; i < 11; i++) {
  457 + app += (char) block[i];
  458 + }
  459 + if (app.equals("NETSCAPE2.0")) {
  460 + readNetscapeExt();
  461 + } else {
  462 + skip(); // don't care
  463 + }
  464 + break;
  465 + default: // uninteresting extension
  466 + skip();
  467 + }
  468 + break;
  469 +
  470 + case 0x3b: // terminator
  471 + done = true;
  472 + break;
  473 +
  474 + case 0x00: // bad byte, but keep going and see what happens
  475 + break;
  476 + default:
  477 + status = STATUS_FORMAT_ERROR;
  478 + }
  479 + }
  480 + }
  481 +
  482 + protected void readGraphicControlExt() {
  483 + read(); // block size
  484 + int packed = read(); // packed fields
  485 + dispose = (packed & 0x1c) >> 2; // disposal method
  486 + if (dispose == 0) {
  487 + dispose = 1; // elect to keep old image if discretionary
  488 + }
  489 + transparency = (packed & 1) != 0;
  490 + delay = readShort() * 10; // delay in milliseconds
  491 + transIndex = read(); // transparent color index
  492 + read(); // block terminator
  493 + }
  494 +
  495 + // to get Stream - Head
  496 + protected void readHeader() {
  497 + String id = "";
  498 + for (int i = 0; i < 6; i++) {
  499 + id += (char) read();
  500 + }
  501 + if (!id.startsWith("GIF")) {
  502 + status = STATUS_FORMAT_ERROR;
  503 + return;
  504 + }
  505 + readLSD();
  506 + if (gctFlag && !err()) {
  507 + gct = readColorTable(gctSize);
  508 + bgColor = gct[bgIndex];
  509 + }
  510 + }
  511 +
  512 + protected void readImage() {
  513 + // offset of X
  514 + ix = readShort(); // (sub)image position & size
  515 + // offset of Y
  516 + iy = readShort();
  517 + // width of bitmap
  518 + iw = readShort();
  519 + // height of bitmap
  520 + ih = readShort();
  521 +
  522 + // Local Color Table Flag
  523 + int packed = read();
  524 + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag
  525 +
  526 + // Interlace Flag, to array with interwoven if ENABLE, with order
  527 + // otherwise
  528 + interlace = (packed & 0x40) != 0; // 2 - interlace flag
  529 + // 3 - sort flag
  530 + // 4-5 - reserved
  531 + lctSize = 2 << (packed & 7); // 6-8 - local color table size
  532 + if (lctFlag) {
  533 + lct = readColorTable(lctSize); // read table
  534 + act = lct; // make local table active
  535 + } else {
  536 + act = gct; // make global table active
  537 + if (bgIndex == transIndex) {
  538 + bgColor = 0;
  539 + }
  540 + }
  541 + int save = 0;
  542 + if (transparency) {
  543 + save = act[transIndex];
  544 + act[transIndex] = 0; // set transparent color if specified
  545 + }
  546 + if (act == null) {
  547 + status = STATUS_FORMAT_ERROR; // no color table defined
  548 + }
  549 + if (err()) {
  550 + return;
  551 + }
  552 + decodeImageData(); // decode pixel data
  553 + skip();
  554 + if (err()) {
  555 + return;
  556 + }
  557 + frameCount++;
  558 + // create new image to receive frame data
  559 + image = Bitmap.createBitmap(width, height, Config.ARGB_4444);
  560 + // createImage(width, height);
  561 + setPixels(); // transfer pixel data to image
  562 + frames.addElement(new GifFrame(image, delay)); // add image to frame
  563 + // list
  564 + if (transparency) {
  565 + act[transIndex] = save;
  566 + }
  567 + resetFrame();
  568 + }
  569 +
  570 + // Logical Screen Descriptor
  571 + protected void readLSD() {
  572 + // logical screen size
  573 + width = readShort();
  574 + height = readShort();
  575 + // packed fields
  576 + int packed = read();
  577 + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
  578 + // 2-4 : color resolution
  579 + // 5 : gct sort flag
  580 + gctSize = 2 << (packed & 7); // 6-8 : gct size
  581 + bgIndex = read(); // background color index
  582 + pixelAspect = read(); // pixel aspect ratio
  583 + }
  584 +
  585 + protected void readNetscapeExt() {
  586 + do {
  587 + readBlock();
  588 + if (block[0] == 1) {
  589 + // loop count sub-block
  590 + int b1 = ((int) block[1]) & 0xff;
  591 + int b2 = ((int) block[2]) & 0xff;
  592 + loopCount = (b2 << 8) | b1;
  593 + }
  594 + } while ((blockSize > 0) && !err());
  595 + }
  596 +
  597 + // read 8 bit data
  598 + protected int readShort() {
  599 + // read 16-bit value, LSB first
  600 + return read() | (read() << 8);
  601 + }
  602 +
  603 + protected void resetFrame() {
  604 + lastDispose = dispose;
  605 + lrx = ix;
  606 + lry = iy;
  607 + lrw = iw;
  608 + lrh = ih;
  609 + lastImage = image;
  610 + lastBgColor = bgColor;
  611 + dispose = 0;
  612 + transparency = false;
  613 + delay = 0;
  614 + lct = null;
  615 + }
  616 +
  617 + /**
  618 + * Skips variable length blocks up to and including next zero length block.
  619 + */
  620 + protected void skip() {
  621 + do {
  622 + readBlock();
  623 + } while ((blockSize > 0) && !err());
  624 + }
  625 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/ImageCheckoutUtil.java 0 → 100644
... ... @@ -0,0 +1,61 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.graphics.Bitmap;
  5 +import android.graphics.BitmapFactory;
  6 +import android.os.Build;
  7 +
  8 +import java.io.BufferedInputStream;
  9 +import java.io.ByteArrayOutputStream;
  10 +import java.io.FileInputStream;
  11 +import java.io.FileNotFoundException;
  12 +import java.io.IOException;
  13 +
  14 +public class ImageCheckoutUtil {
  15 + /**
  16 + * 检测图片内存大小
  17 + *
  18 + * @param data
  19 + * @return
  20 + */
  21 + @SuppressLint("NewApi")
  22 + public static int getImageSize(Bitmap data) {
  23 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
  24 + return data.getRowBytes() * data.getHeight();
  25 + } else {
  26 + return data.getByteCount();
  27 + }
  28 + }
  29 +
  30 + public static Bitmap getLoacalBitmap(String url) {
  31 + try {
  32 + ByteArrayOutputStream out;
  33 + FileInputStream fis = new FileInputStream(url);
  34 + BufferedInputStream bis = new BufferedInputStream(fis);
  35 + out = new ByteArrayOutputStream();
  36 + @SuppressWarnings("unused")
  37 + int hasRead = 0;
  38 + byte[] buffer = new byte[1024 * 2];
  39 + while ((hasRead = bis.read(buffer)) > 0) {
  40 + // 读出多少数据,向输出流中写入多少
  41 + out.write(buffer);
  42 + out.flush();
  43 + }
  44 + out.close();
  45 + fis.close();
  46 + bis.close();
  47 + byte[] data = out.toByteArray();
  48 + // 长宽减半
  49 + BitmapFactory.Options opts = new BitmapFactory.Options();
  50 + opts.inSampleSize = 3;
  51 + return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
  52 + } catch (FileNotFoundException e) {
  53 + e.printStackTrace();
  54 + return null;
  55 + } catch (IOException e) {
  56 + // TODO Auto-generated catch block
  57 + e.printStackTrace();
  58 + return null;
  59 + }
  60 + }
  61 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/KeyBoardUtils.java 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.view.View;
  5 +import android.view.inputmethod.InputMethodManager;
  6 +
  7 +/**
  8 + * Created by Mao Jiqing on 2016/9/28.
  9 + */
  10 +public class KeyBoardUtils {
  11 + public static void hideKeyBoard(Context context, View view) {
  12 + InputMethodManager imm = (InputMethodManager) context
  13 + .getSystemService(Context.INPUT_METHOD_SERVICE);
  14 + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); // 强制隐藏键盘
  15 + }
  16 +
  17 + public static void showKeyBoard(Context context, View view) {
  18 + view.setFocusable(true);
  19 + view.setFocusableInTouchMode(true);
  20 + view.requestFocus();
  21 + view.findFocus();
  22 + InputMethodManager imm = (InputMethodManager) context
  23 + .getSystemService(Context.INPUT_METHOD_SERVICE);
  24 + imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
  25 + }
  26 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/PictureUtil.java 0 → 100644
... ... @@ -0,0 +1,157 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import java.io.ByteArrayInputStream;
  4 +import java.io.ByteArrayOutputStream;
  5 +import java.io.IOException;
  6 +
  7 +import android.graphics.Bitmap;
  8 +import android.graphics.BitmapFactory;
  9 +import android.graphics.Matrix;
  10 +import android.media.ExifInterface;
  11 +
  12 +public class PictureUtil {
  13 +
  14 + /**
  15 + * 计算图片的缩放值
  16 + *
  17 + * @param options
  18 + * @param reqWidth
  19 + * @param reqHeight
  20 + * @return
  21 + */
  22 + public static int calculateInSampleSize(BitmapFactory.Options options,
  23 + int reqWidth, int reqHeight) {
  24 + // Raw height and width of image
  25 + final int height = options.outHeight;
  26 + final int width = options.outWidth;
  27 + int inSampleSize = 1;
  28 +
  29 + if (height > reqHeight || width > reqWidth) {
  30 +
  31 + // Calculate ratios of height and width to requested height and
  32 + // width
  33 + final int heightRatio = Math.round((float) height
  34 + / (float) reqHeight);
  35 + final int widthRatio = Math.round((float) width / (float) reqWidth);
  36 +
  37 + // Choose the smallest ratio as inSampleSize value, this will
  38 + // guarantee
  39 + // a final image with both dimensions larger than or equal to the
  40 + // requested height and width.
  41 + inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
  42 + }
  43 +
  44 + return inSampleSize;
  45 + }
  46 +
  47 + /**
  48 + * 根据路径获得图片并压缩返回bitmap用于显示
  49 + *
  50 + * @param imagesrc
  51 + * @return
  52 + */
  53 + public static Bitmap getSmallBitmap(String filePath) {
  54 + final BitmapFactory.Options options = new BitmapFactory.Options();
  55 + options.inJustDecodeBounds = true;
  56 + BitmapFactory.decodeFile(filePath, options);
  57 +
  58 + // Calculate inSampleSize
  59 + options.inSampleSize = calculateInSampleSize(options, 320, 480);
  60 +
  61 + // Decode bitmap with inSampleSize set
  62 + options.inJustDecodeBounds = false;
  63 +
  64 + return BitmapFactory.decodeFile(filePath, options);
  65 + }
  66 +
  67 + /**
  68 + * 压缩大图片
  69 + * @param srcPath
  70 + * @return
  71 + */
  72 + public static Bitmap compressSizeImage(String srcPath) {
  73 + BitmapFactory.Options newOpts = new BitmapFactory.Options();
  74 + //开始读入图片,此时把options.inJustDecodeBounds 设回true了
  75 + newOpts.inJustDecodeBounds = true;
  76 + Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空
  77 +
  78 + newOpts.inJustDecodeBounds = false;
  79 + int w = newOpts.outWidth;
  80 + int h = newOpts.outHeight;
  81 + //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
  82 + float hh = 800f;//这里设置高度为800f
  83 + float ww = 480f;//这里设置宽度为480f
  84 + //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
  85 + int be = 1;//be=1表示不缩放
  86 + if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
  87 + be = (int) (newOpts.outWidth / ww);
  88 + } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
  89 + be = (int) (newOpts.outHeight / hh);
  90 + }
  91 + if (be <= 0)
  92 + be = 1;
  93 + newOpts.inSampleSize = be;//设置缩放比例
  94 + //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
  95 + bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
  96 + return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
  97 + }
  98 +
  99 + public static Bitmap compressImage(Bitmap image) {
  100 +
  101 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
  102 + image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
  103 + int options = 100;
  104 + while ( baos.toByteArray().length / 1024>100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
  105 + baos.reset();//重置baos即清空baos
  106 + image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
  107 + options -= 10;//每次都减少10
  108 + }
  109 + ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
  110 + Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
  111 + return bitmap;
  112 + }
  113 +
  114 + /**
  115 + * 获取图片文件的信息,是否旋转了90度,如果是则反转
  116 + * @param bitmap 需要旋转的图片
  117 + * @param path 图片的路径
  118 + */
  119 + public static Bitmap reviewPicRotate(Bitmap bitmap,String path){
  120 + int degree = getPicRotate(path);
  121 + if(degree!=0){
  122 + Matrix m = new Matrix();
  123 + int width = bitmap.getWidth();
  124 + int height = bitmap.getHeight();
  125 + m.setRotate(degree); // 旋转angle度
  126 + bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,m, true);// 从新生成图片
  127 + }
  128 + return bitmap;
  129 + }
  130 +
  131 + /**
  132 + * 读取图片文件旋转的角度
  133 + * @param path 图片绝对路径
  134 + * @return 图片旋转的角度
  135 + */
  136 + public static int getPicRotate(String path) {
  137 + int degree = 0;
  138 + try {
  139 + ExifInterface exifInterface = new ExifInterface(path);
  140 + int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
  141 + switch (orientation) {
  142 + case ExifInterface.ORIENTATION_ROTATE_90:
  143 + degree = 90;
  144 + break;
  145 + case ExifInterface.ORIENTATION_ROTATE_180:
  146 + degree = 180;
  147 + break;
  148 + case ExifInterface.ORIENTATION_ROTATE_270:
  149 + degree = 270;
  150 + break;
  151 + }
  152 + } catch (IOException e) {
  153 + e.printStackTrace();
  154 + }
  155 + return degree;
  156 + }
  157 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/ScreenUtil.java 0 → 100644
... ... @@ -0,0 +1,239 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.annotation.TargetApi;
  4 +import android.app.Activity;
  5 +import android.content.Context;
  6 +import android.content.res.Configuration;
  7 +import android.content.res.Resources;
  8 +import android.os.Build;
  9 +import android.util.DisplayMetrics;
  10 +import android.view.Display;
  11 +import android.view.ViewConfiguration;
  12 +import android.view.Window;
  13 +import android.view.WindowManager;
  14 +
  15 +import java.lang.reflect.Field;
  16 +import java.lang.reflect.Method;
  17 +
  18 +public class ScreenUtil {
  19 +
  20 + private static int screenWidth = 0;
  21 +
  22 + private static int screenHeight = 0;
  23 + private static int screenTotalHeight = 0;
  24 + private static int statusBarHeight = 0;
  25 +
  26 + private static final int TITLE_HEIGHT = 0;
  27 +
  28 + /**
  29 + */
  30 + public static int dip2px(Context context, float dpValue) {
  31 + final float scale = context.getResources().getDisplayMetrics().density;
  32 + return (int) (dpValue * scale + 0.5f);
  33 + }
  34 +
  35 + /**
  36 + */
  37 + public static int px2dip(Context context, float pxValue) {
  38 + final float scale = context.getResources().getDisplayMetrics().density;
  39 + return (int) (pxValue / scale + 0.5f);
  40 + }
  41 +
  42 + public static int getScreenWidth(Context context) {
  43 +// if (screenWidth != 0) {
  44 +// return screenWidth;
  45 +// }
  46 + DisplayMetrics dm = new DisplayMetrics();
  47 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  48 + wm.getDefaultDisplay().getMetrics(dm);
  49 + screenWidth = dm.widthPixels;
  50 + return screenWidth;
  51 + }
  52 +
  53 + public static int getScreenHeight(Context context) {
  54 +// if (screenHeight != 0) {
  55 +// return screenHeight;
  56 +// }
  57 + int top = 0;
  58 + if (context instanceof Activity) {
  59 + top = ((Activity) context).getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
  60 + if (top == 0) {
  61 + top = (int) (TITLE_HEIGHT * getScreenDensity(context));
  62 + }
  63 + }
  64 + DisplayMetrics dm = new DisplayMetrics();
  65 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  66 + wm.getDefaultDisplay().getMetrics(dm);
  67 + screenHeight = dm.heightPixels - top;
  68 + return screenHeight;
  69 + }
  70 +
  71 + public static int getScreenTotalHeight(Context context) {
  72 + if (screenTotalHeight != 0) {
  73 + return screenTotalHeight;
  74 + }
  75 + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
  76 + screenTotalHeight = displayMetrics.heightPixels;
  77 + return screenTotalHeight;
  78 + }
  79 + public static float getScreenDensity(Context context) {
  80 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  81 + DisplayMetrics metric = new DisplayMetrics();
  82 + wm.getDefaultDisplay().getMetrics(metric);
  83 + return metric.density;
  84 + }
  85 +
  86 + public static float getScreenDensityDpi(Context context) {
  87 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  88 + DisplayMetrics metric = new DisplayMetrics();
  89 + wm.getDefaultDisplay().getMetrics(metric);
  90 + return metric.densityDpi;
  91 + }
  92 + public static int getStatusBarHeight(Context context) {
  93 + if (statusBarHeight != 0) {
  94 + return statusBarHeight;
  95 + }
  96 + Class<?> c = null;
  97 + Object obj = null;
  98 + Field field = null;
  99 + int x = 0;
  100 + try {
  101 + c = Class.forName("com.android.internal.R$dimen");
  102 + obj = c.newInstance();
  103 + field = c.getField("status_bar_height");
  104 + x = Integer.parseInt(field.get(obj).toString());
  105 + statusBarHeight = context.getResources().getDimensionPixelSize(x);
  106 + } catch (Exception e1) {
  107 + e1.printStackTrace();
  108 + }
  109 + return statusBarHeight;
  110 + }
  111 + public static boolean isTablet(Context context) {
  112 + return (context.getResources().getConfiguration().screenLayout
  113 + & Configuration.SCREENLAYOUT_SIZE_MASK)
  114 + >= Configuration.SCREENLAYOUT_SIZE_LARGE;
  115 + }
  116 +
  117 +
  118 + //获取屏幕原始尺寸高度,包括虚拟功能键高度
  119 + public static int getDpi(Context context){
  120 + int dpi = 0;
  121 + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  122 + Display display = windowManager.getDefaultDisplay();
  123 + DisplayMetrics displayMetrics = new DisplayMetrics();
  124 + @SuppressWarnings("rawtypes")
  125 + Class c;
  126 + try {
  127 + c = Class.forName("android.view.Display");
  128 + @SuppressWarnings("unchecked")
  129 + Method method = c.getMethod("getRealMetrics",DisplayMetrics.class);
  130 + method.invoke(display, displayMetrics);
  131 + dpi=displayMetrics.heightPixels;
  132 + }catch(Exception e){
  133 + e.printStackTrace();
  134 + }
  135 + return dpi;
  136 + }
  137 +
  138 + /**
  139 + * 获取 虚拟按键的高度
  140 + * @param context
  141 + * @return
  142 + */
  143 + public static int getBottomStatusHeight(Context context){
  144 + int totalHeight = getDpi(context);
  145 +
  146 + int contentHeight = getScreenHeight(context);
  147 +
  148 + return totalHeight - contentHeight;
  149 + }
  150 +
  151 + /**
  152 + * 标题栏高度
  153 + * @return
  154 + */
  155 + public static int getTitleHeight(Activity activity){
  156 + return activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
  157 + }
  158 +
  159 + /**
  160 + * 获得状态栏的高度
  161 + *
  162 + * @param context
  163 + * @return
  164 + */
  165 + public static int getStatusHeight(Context context)
  166 + {
  167 +
  168 + int statusHeight = -1;
  169 + try
  170 + {
  171 + Class<?> clazz = Class.forName("com.android.internal.R$dimen");
  172 + Object object = clazz.newInstance();
  173 + int height = Integer.parseInt(clazz.getField("status_bar_height")
  174 + .get(object).toString());
  175 + statusHeight = context.getResources().getDimensionPixelSize(height);
  176 + } catch (Exception e)
  177 + {
  178 + e.printStackTrace();
  179 + }
  180 + return statusHeight;
  181 + }
  182 +
  183 + //获取虚拟按键的高度
  184 + public static int getNavigationBarHeight(Context context) {
  185 + int result = 0;
  186 + if (hasNavBar(context)) {
  187 + Resources res = context.getResources();
  188 + int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
  189 + if (resourceId > 0) {
  190 + result = res.getDimensionPixelSize(resourceId);
  191 + }
  192 + }
  193 + return result;
  194 + }
  195 +
  196 + /**
  197 + * 检查是否存在虚拟按键栏
  198 + *
  199 + * @param context
  200 + * @return
  201 + */
  202 + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
  203 + public static boolean hasNavBar(Context context) {
  204 + Resources res = context.getResources();
  205 + int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
  206 + if (resourceId != 0) {
  207 + boolean hasNav = res.getBoolean(resourceId);
  208 + // check override flag
  209 + String sNavBarOverride = getNavBarOverride();
  210 + if ("1".equals(sNavBarOverride)) {
  211 + hasNav = false;
  212 + } else if ("0".equals(sNavBarOverride)) {
  213 + hasNav = true;
  214 + }
  215 + return hasNav;
  216 + } else { // fallback
  217 + return !ViewConfiguration.get(context).hasPermanentMenuKey();
  218 + }
  219 + }
  220 +
  221 + /**
  222 + * 判断虚拟按键栏是否重写
  223 + *
  224 + * @return
  225 + */
  226 + private static String getNavBarOverride() {
  227 + String sNavBarOverride = null;
  228 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  229 + try {
  230 + Class c = Class.forName("android.os.SystemProperties");
  231 + Method m = c.getDeclaredMethod("get", String.class);
  232 + m.setAccessible(true);
  233 + sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
  234 + } catch (Throwable e) {
  235 + }
  236 + }
  237 + return sNavBarOverride;
  238 + }
  239 +}
0 240 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/SharedPreferencesUtils.java 0 → 100644
... ... @@ -0,0 +1,68 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.content.SharedPreferences;
  5 +
  6 +/**
  7 + * Created by Mao Jiqing on 2016/10/10.
  8 + */
  9 +public class SharedPreferencesUtils {
  10 + /**
  11 + * 保存在手机里面的文件名
  12 + */
  13 + private static final String FILE_NAME = "share_date";
  14 +
  15 + /**
  16 + * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
  17 + *
  18 + * @param context
  19 + * @param key
  20 + * @param object
  21 + */
  22 + public static void setParam(Context context, String key, Object object) {
  23 +
  24 + String type = object.getClass().getSimpleName();
  25 + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
  26 + SharedPreferences.Editor editor = sp.edit();
  27 +
  28 + if ("String".equals(type)) {
  29 + editor.putString(key, (String) object);
  30 + } else if ("Integer".equals(type)) {
  31 + editor.putInt(key, (Integer) object);
  32 + } else if ("Boolean".equals(type)) {
  33 + editor.putBoolean(key, (Boolean) object);
  34 + } else if ("Float".equals(type)) {
  35 + editor.putFloat(key, (Float) object);
  36 + } else if ("Long".equals(type)) {
  37 + editor.putLong(key, (Long) object);
  38 + }
  39 +
  40 + editor.commit();
  41 + }
  42 +
  43 + /**
  44 + * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
  45 + *
  46 + * @param context
  47 + * @param key
  48 + * @param defaultObject
  49 + * @return
  50 + */
  51 + public static Object getParam(Context context, String key, Object defaultObject) {
  52 + String type = defaultObject.getClass().getSimpleName();
  53 + SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
  54 +
  55 + if ("String".equals(type)) {
  56 + return sp.getString(key, (String) defaultObject);
  57 + } else if ("Integer".equals(type)) {
  58 + return sp.getInt(key, (Integer) defaultObject);
  59 + } else if ("Boolean".equals(type)) {
  60 + return sp.getBoolean(key, (Boolean) defaultObject);
  61 + } else if ("Float".equals(type)) {
  62 + return sp.getFloat(key, (Float) defaultObject);
  63 + } else if ("Long".equals(type)) {
  64 + return sp.getLong(key, (Long) defaultObject);
  65 + }
  66 + return null;
  67 + }
  68 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/SmileUtils.java 0 → 100644
... ... @@ -0,0 +1,178 @@
  1 +/**
  2 + * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + * http://www.apache.org/licenses/LICENSE-2.0
  8 + * Unless required by applicable law or agrtbd to in writing, software
  9 + * distributed under the License is distributed on an "AS IS" BASIS,
  10 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11 + * Stb the License for the specific language governing permissions and
  12 + * limitations under the License.
  13 + */
  14 +package com.shunzhi.mychartlibrary.utils;
  15 +
  16 +import android.content.Context;
  17 +import android.text.Spannable;
  18 +import android.text.Spannable.Factory;
  19 +import android.text.style.ImageSpan;
  20 +
  21 +
  22 +import com.shunzhi.mychartlibrary.R;
  23 +
  24 +import java.util.HashMap;
  25 +import java.util.Map;
  26 +import java.util.Map.Entry;
  27 +import java.util.regex.Matcher;
  28 +import java.util.regex.Pattern;
  29 +
  30 +public class SmileUtils {
  31 + public static final String f1 = "[:f1]";
  32 + public static final String f2 = "[:f2]";
  33 + public static final String f3 = "[:f3]";
  34 + public static final String f4 = "[:f4]";
  35 + public static final String f5 = "[:f5]";
  36 + public static final String f6 = "[:f6]";
  37 + public static final String f7 = "[:f7]";
  38 + public static final String f8 = "[:f8]";
  39 + public static final String f9 = "[:f9]";
  40 + public static final String f10 = "[:f10]";
  41 + public static final String f11 = "[:f11]";
  42 + public static final String f12 = "[:f12]";
  43 + public static final String f13 = "[:f13]";
  44 + public static final String f14 = "[:f14]";
  45 + public static final String f15 = "[:f15]";
  46 + public static final String f16 = "[:f16]";
  47 + public static final String f17 = "[:f17]";
  48 + public static final String f18 = "[:f18]";
  49 + public static final String f19 = "[:f19]";
  50 + public static final String f20 = "[:f20]";
  51 + public static final String f21 = "[:f21]";
  52 + public static final String f22 = "[:f22]";
  53 + public static final String f23 = "[:f23]";
  54 + public static final String f24 = "[:f24]";
  55 + public static final String f25 = "[:f25]";
  56 + public static final String f26 = "[:f26]";
  57 + public static final String f27 = "[:f27]";
  58 + public static final String f28 = "[:f28]";
  59 + public static final String f29 = "[:f29]";
  60 + public static final String f30 = "[:f30]";
  61 + public static final String f31 = "[:f31]";
  62 + public static final String f32 = "[:f32]";
  63 + public static final String f33 = "[:f33]";
  64 + public static final String f34 = "[:f34]";
  65 + public static final String f35 = "[:f35]";
  66 + public static final String f36 = "[:f36]";
  67 + public static final String f37 = "[:f37]";
  68 + public static final String f38 = "[:f38]";
  69 + public static final String f39 = "[:f39]";
  70 + public static final String f40 = "[:f40]";
  71 +
  72 + private static final Factory spannableFactory = Factory
  73 + .getInstance();
  74 +
  75 + private static final Map<Pattern, Integer> emoticons = new HashMap<Pattern, Integer>();
  76 +
  77 + static {
  78 +
  79 + addPattern(emoticons, f1, R.mipmap.f1);
  80 + addPattern(emoticons, f2, R.mipmap.f2);
  81 + addPattern(emoticons, f3, R.mipmap.f3);
  82 + addPattern(emoticons, f4, R.mipmap.f4);
  83 + addPattern(emoticons, f5, R.mipmap.f5);
  84 + addPattern(emoticons, f6, R.mipmap.f6);
  85 + addPattern(emoticons, f7, R.mipmap.f7);
  86 + addPattern(emoticons, f8, R.mipmap.f8);
  87 + addPattern(emoticons, f9, R.mipmap.f9);
  88 + addPattern(emoticons, f10, R.mipmap.f10);
  89 + addPattern(emoticons, f11, R.mipmap.f11);
  90 + addPattern(emoticons, f12, R.mipmap.f12);
  91 + addPattern(emoticons, f13, R.mipmap.f13);
  92 + addPattern(emoticons, f14, R.mipmap.f14);
  93 + addPattern(emoticons, f15, R.mipmap.f15);
  94 + addPattern(emoticons, f16, R.mipmap.f16);
  95 + addPattern(emoticons, f17, R.mipmap.f17);
  96 + addPattern(emoticons, f18, R.mipmap.f18);
  97 + addPattern(emoticons, f19, R.mipmap.f19);
  98 + addPattern(emoticons, f20, R.mipmap.f20);
  99 + addPattern(emoticons, f21, R.mipmap.f21);
  100 + addPattern(emoticons, f22, R.mipmap.f22);
  101 + addPattern(emoticons, f23, R.mipmap.f23);
  102 + addPattern(emoticons, f24, R.mipmap.f24);
  103 + addPattern(emoticons, f25, R.mipmap.f25);
  104 + addPattern(emoticons, f26, R.mipmap.f26);
  105 + addPattern(emoticons, f27, R.mipmap.f27);
  106 + addPattern(emoticons, f28, R.mipmap.f28);
  107 + addPattern(emoticons, f29, R.mipmap.f29);
  108 + addPattern(emoticons, f30, R.mipmap.f30);
  109 + addPattern(emoticons, f31, R.mipmap.f31);
  110 + addPattern(emoticons, f32, R.mipmap.f32);
  111 + addPattern(emoticons, f33, R.mipmap.f33);
  112 + addPattern(emoticons, f34, R.mipmap.f34);
  113 + addPattern(emoticons, f35, R.mipmap.f35);
  114 + addPattern(emoticons, f36, R.mipmap.f36);
  115 + addPattern(emoticons, f37, R.mipmap.f37);
  116 + addPattern(emoticons, f38, R.mipmap.f38);
  117 + addPattern(emoticons, f39, R.mipmap.f39);
  118 + addPattern(emoticons, f40, R.mipmap.f40);
  119 + }
  120 +
  121 + private static void addPattern(Map<Pattern, Integer> map, String smile,
  122 + int resource) {
  123 + map.put(Pattern.compile(Pattern.quote(smile)), resource);
  124 + }
  125 +
  126 + /**
  127 + * replace existing spannable with smiles
  128 + *
  129 + * @param context
  130 + * @param spannable
  131 + * @return
  132 + */
  133 + public static boolean addSmiles(Context context, Spannable spannable) {
  134 + boolean hasChanges = false;
  135 + for (Entry<Pattern, Integer> entry : emoticons.entrySet()) {
  136 + Matcher matcher = entry.getKey().matcher(spannable);
  137 + while (matcher.find()) {
  138 + boolean set = true;
  139 + for (ImageSpan span : spannable.getSpans(matcher.start(),
  140 + matcher.end(), ImageSpan.class))
  141 + if (spannable.getSpanStart(span) >= matcher.start()
  142 + && spannable.getSpanEnd(span) <= matcher.end())
  143 + spannable.removeSpan(span);
  144 + else {
  145 + set = false;
  146 + break;
  147 + }
  148 + if (set) {
  149 + hasChanges = true;
  150 + spannable.setSpan(new ImageSpan(context, entry.getValue()),
  151 + matcher.start(), matcher.end(),
  152 + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  153 + }
  154 + }
  155 + }
  156 + return hasChanges;
  157 + }
  158 +
  159 + public static Spannable getSmiledText(Context context, CharSequence text) {
  160 + Spannable spannable = spannableFactory.newSpannable(text);
  161 + addSmiles(context, spannable);
  162 + return spannable;
  163 + }
  164 +
  165 + public static boolean containsKey(String key) {
  166 + boolean b = false;
  167 + for (Entry<Pattern, Integer> entry : emoticons.entrySet()) {
  168 + Matcher matcher = entry.getKey().matcher(key);
  169 + if (matcher.find()) {
  170 + b = true;
  171 + break;
  172 + }
  173 + }
  174 +
  175 + return b;
  176 + }
  177 +
  178 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/StatusBarUtils.java 0 → 100644
... ... @@ -0,0 +1,140 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +import android.graphics.Color;
  6 +import android.os.Build;
  7 +import android.support.annotation.ColorInt;
  8 +import android.support.v7.widget.Toolbar;
  9 +import android.view.View;
  10 +import android.view.ViewGroup;
  11 +import android.view.Window;
  12 +import android.view.WindowManager;
  13 +
  14 +import java.lang.reflect.Field;
  15 +
  16 +
  17 +/**
  18 + * Created by Horrarndoo on 2017/8/31.
  19 + * <p>
  20 + * StatusBar工具类
  21 + */
  22 +public class StatusBarUtils {
  23 +
  24 + private static final int DEFAULT_STATUS_BAR_ALPHA = 0;
  25 +
  26 + /**
  27 + * 设置状态栏颜色
  28 + *
  29 + * @param activity 需要设置的 activity
  30 + * @param color 状态栏颜色值
  31 + */
  32 + public static void setColor(Activity activity, @ColorInt int color) {
  33 + setBarColor(activity, color);
  34 + }
  35 +
  36 + /**
  37 + * 设置状态栏背景色
  38 + * 4.4以下不处理
  39 + * 4.4使用默认沉浸式状态栏
  40 + *
  41 + * @param color 要为状态栏设置的颜色值
  42 + */
  43 + public static void setBarColor(Activity activity, int color) {
  44 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  45 + Window win = activity.getWindow();
  46 + View decorView = win.getDecorView();
  47 + win.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//沉浸式状态栏(4.4-5.0透明,5.0以上半透明)
  48 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//android5.0以上设置透明效果
  49 + win.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//清除flag,为了android5.0以上也全透明效果
  50 + //让应用的主体内容占用系统状态栏的空间
  51 +// int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  52 +// | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  53 + int option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  54 + decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | option);
  55 + win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  56 + win.setStatusBarColor(color);//设置状态栏背景色
  57 + }
  58 + }
  59 + }
  60 +
  61 + /**
  62 + * 设置状态栏全透明
  63 + *
  64 + * @param activity 需要设置的activity
  65 + */
  66 + public static void setTransparent(Activity activity) {
  67 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  68 + return;
  69 + }
  70 + setColor(activity, Color.TRANSPARENT);
  71 + }
  72 +
  73 + /**
  74 + * 修正 Toolbar 的位置
  75 + * 在 Android 4.4 版本下无法显示内容在 StatusBar 下,所以无需修正 Toolbar 的位置
  76 + *
  77 + * @param toolbar
  78 + */
  79 + public static void fixToolbar(Toolbar toolbar, Activity activity) {
  80 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  81 + int statusHeight = getStatusBarHeight(activity);
  82 + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams();
  83 + layoutParams.setMargins(0, statusHeight, 0, 0);
  84 + }
  85 + }
  86 +
  87 + /**
  88 + * 获取系统状态栏高度
  89 + *
  90 + * @param context
  91 + * @return
  92 + */
  93 + public static int getStatusBarHeight(Context context) {
  94 + Class<?> c = null;
  95 + Object obj = null;
  96 + Field field = null;
  97 + int x = 0, statusBarHeight = 0;
  98 + try {
  99 + c = Class.forName("com.android.internal.R$dimen");
  100 + obj = c.newInstance();
  101 + field = c.getField("status_bar_height");
  102 + x = Integer.parseInt(field.get(obj).toString());
  103 + statusBarHeight = context.getResources().getDimensionPixelSize(x);
  104 + } catch (Exception e1) {
  105 + e1.printStackTrace();
  106 + }
  107 + return statusBarHeight;
  108 + }
  109 +
  110 +// /**
  111 +// * 获取状态栏高度
  112 +// *
  113 +// * @param context context
  114 +// * @return 状态栏高度
  115 +// */
  116 +// private static int getStatusBarHeight(Context context) {
  117 +// // 获得状态栏高度
  118 +// int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
  119 +// "android");
  120 +// return context.getResources().getDimensionPixelSize(resourceId);
  121 +// }
  122 +
  123 + /**
  124 + * 计算状态栏颜色
  125 + *
  126 + * @param color color值
  127 + * @param alpha alpha值
  128 + * @return 最终的状态栏颜色
  129 + */
  130 + private static int calculateStatusColor(@ColorInt int color, int alpha) {
  131 + float a = 1 - alpha / 255f;
  132 + int red = color >> 16 & 0xff;
  133 + int green = color >> 8 & 0xff;
  134 + int blue = color & 0xff;
  135 + red = (int) (red * a + 0.5);
  136 + green = (int) (green * a + 0.5);
  137 + blue = (int) (blue * a + 0.5);
  138 + return 0xff << 24 | red << 16 | green << 8 | blue;
  139 + }
  140 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/utils/ThreadPoolUtils.java 0 → 100644
... ... @@ -0,0 +1,57 @@
  1 +package com.shunzhi.mychartlibrary.utils;
  2 +
  3 +import java.util.concurrent.ArrayBlockingQueue;
  4 +import java.util.concurrent.BlockingQueue;
  5 +import java.util.concurrent.FutureTask;
  6 +import java.util.concurrent.ThreadFactory;
  7 +import java.util.concurrent.ThreadPoolExecutor;
  8 +import java.util.concurrent.TimeUnit;
  9 +import java.util.concurrent.atomic.AtomicInteger;
  10 +
  11 +/**
  12 + * Created by Mao Jiqing on 2016/11/7.
  13 + */
  14 +
  15 +public class ThreadPoolUtils {
  16 + //线程池核心线程数
  17 + private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
  18 + private static int CORE_POOL_SIZE = CPU_COUNT + 1;
  19 + //线程池最大线程数
  20 + private static int MAX_POOL_SIZE = CPU_COUNT * 2 + 1;
  21 + //额外线程空状态生存时间
  22 + private static int KEEP_ALIVE_TIME = 10000;
  23 + //阻塞队列。当核心线程都被占用,且阻塞队列已满的情况下,才会开启额外线程。
  24 + private static BlockingQueue workQueue = new ArrayBlockingQueue(10);
  25 + //线程池
  26 + private static ThreadPoolExecutor threadPool;
  27 +
  28 + private ThreadPoolUtils() {
  29 + }
  30 +
  31 + //线程工厂
  32 + private static ThreadFactory threadFactory = new ThreadFactory() {
  33 + private final AtomicInteger integer = new AtomicInteger();
  34 +
  35 + @Override
  36 + public Thread newThread(Runnable r) {
  37 + return new Thread(r, "myThreadPool thread:" + integer.getAndIncrement());
  38 + }
  39 + };
  40 +
  41 + static {
  42 + threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME,
  43 + TimeUnit.SECONDS, workQueue, threadFactory);
  44 + }
  45 +
  46 + public static void execute(Runnable runnable) {
  47 + threadPool.execute(runnable);
  48 + }
  49 +
  50 + public static void execute(FutureTask futureTask) {
  51 + threadPool.execute(futureTask);
  52 + }
  53 +
  54 + public static void cancel(FutureTask futureTask) {
  55 + futureTask.cancel(true);
  56 + }
  57 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/AudioRecordButton.java 0 → 100644
... ... @@ -0,0 +1,336 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.os.Handler;
  6 +import android.os.Message;
  7 +import android.util.AttributeSet;
  8 +import android.view.MotionEvent;
  9 +import android.view.View;
  10 +import android.widget.Button;
  11 +import android.widget.Toast;
  12 +
  13 +
  14 +import com.shunzhi.mychartlibrary.R;
  15 +import com.shunzhi.mychartlibrary.utils.AudioManager;
  16 +import com.shunzhi.mychartlibrary.utils.FileSaveUtil;
  17 +
  18 +import java.io.File;
  19 +import java.io.IOException;
  20 +import java.math.BigDecimal;
  21 +
  22 +public class AudioRecordButton extends Button implements AudioManager.AudioStageListener {
  23 + private static final int STATE_NORMAL = 1;
  24 + private static final int STATE_RECORDING = 2;
  25 + private static final int STATE_WANT_TO_CANCEL = 3;
  26 + private static final int DISTANCE_Y_CANCEL = 50;
  27 + private static final int OVERTIME = 60;
  28 + private int mCurrentState = STATE_NORMAL;
  29 + // 已经开始录音
  30 + private boolean isRecording = false;
  31 + private DialogManager mDialogManager;
  32 + private float mTime = 0;
  33 + // 是否触发了onlongclick,准备好了
  34 + private boolean mReady;
  35 + private AudioManager mAudioManager;
  36 + private String saveDir = FileSaveUtil.voice_dir;
  37 +
  38 + private Handler mp3handler = new Handler() {
  39 +
  40 + @Override
  41 + public void handleMessage(Message msg) {
  42 + // TODO Auto-generated method stub
  43 + switch (msg.what) {
  44 + case AudioManager.MSG_ERROR_AUDIO_RECORD:
  45 + Toast.makeText(getContext(), "录音权限被屏蔽或者录音设备损坏!\n请在设置中检查是否开启权限!",
  46 + Toast.LENGTH_SHORT).show();
  47 + mDialogManager.dimissDialog();
  48 + mAudioManager.cancel();
  49 + reset();
  50 + break;
  51 + default:
  52 + break;
  53 + }
  54 + }
  55 +
  56 + };
  57 +
  58 + /**
  59 + * 先实现两个参数的构造方法,布局会默认引用这个构造方法, 用一个 构造参数的构造方法来引用这个方法 * @param context
  60 + */
  61 +
  62 + public AudioRecordButton(Context context) {
  63 + this(context, null);
  64 + // TODO Auto-generated constructor stub
  65 + }
  66 +
  67 + public AudioRecordButton(Context context, AttributeSet attrs) {
  68 + super(context, attrs);
  69 +
  70 + mDialogManager = new DialogManager(getContext());
  71 +
  72 + try {
  73 + FileSaveUtil.createSDDirectory(FileSaveUtil.voice_dir);
  74 + } catch (IOException e) {
  75 + // TODO Auto-generated catch block
  76 + e.printStackTrace();
  77 + }
  78 + mAudioManager = AudioManager.getInstance(FileSaveUtil.voice_dir);
  79 + mAudioManager.setOnAudioStageListener(this);
  80 + mAudioManager.setHandle(mp3handler);
  81 + setOnLongClickListener(new OnLongClickListener() {
  82 +
  83 + @Override
  84 + public boolean onLongClick(View v) {
  85 + // TODO Auto-generated method
  86 + try {
  87 + FileSaveUtil.createSDDirectory(saveDir);
  88 + } catch (IOException e) {
  89 + // TODO Auto-generated catch block
  90 + e.printStackTrace();
  91 + }
  92 + mAudioManager.setVocDir(saveDir);
  93 + mListener.onStart();
  94 + mReady = true;
  95 + mAudioManager.prepareAudio();
  96 + return false;
  97 + }
  98 + });
  99 + // TODO Auto-generated constructor stub
  100 + }
  101 +
  102 + public void setSaveDir(String saveDir) {
  103 + this.saveDir = saveDir + saveDir;
  104 + }
  105 +
  106 + /**
  107 + * 录音完成后的回调,回调给activiy,可以获得mtime和文件的路径
  108 + */
  109 + public interface AudioFinishRecorderListener {
  110 + void onStart();
  111 +
  112 + void onFinished(float seconds, String filePath);
  113 + }
  114 +
  115 + private AudioFinishRecorderListener mListener;
  116 +
  117 + public void setAudioFinishRecorderListener(
  118 + AudioFinishRecorderListener listener) {
  119 + mListener = listener;
  120 + }
  121 +
  122 + // 获取音量大小的runnable
  123 + private Runnable mGetVoiceLevelRunnable = new Runnable() {
  124 +
  125 + @Override
  126 + public void run() {
  127 + // TODO Auto-generated method stub
  128 + while (isRecording) {
  129 + try {
  130 + Thread.sleep(100);
  131 + mTime += 0.1f;
  132 + mhandler.sendEmptyMessage(MSG_VOICE_CHANGE);
  133 + if (mTime >= OVERTIME) {
  134 + mTime = 60;
  135 + mhandler.sendEmptyMessage(MSG_OVERTIME_SEND);
  136 + isRecording = false;
  137 + break;
  138 + }
  139 + } catch (InterruptedException e) {
  140 + // TODO Auto-generated catch block
  141 + e.printStackTrace();
  142 + }
  143 + }
  144 + }
  145 + };
  146 +
  147 + // 准备三个常量
  148 + private static final int MSG_AUDIO_PREPARED = 0X110;
  149 + private static final int MSG_VOICE_CHANGE = 0X111;
  150 + private static final int MSG_DIALOG_DIMISS = 0X112;
  151 + private static final int MSG_OVERTIME_SEND = 0X113;
  152 +
  153 + private Handler mhandler = new Handler() {
  154 + public void handleMessage(Message msg) {
  155 + switch (msg.what) {
  156 + case MSG_AUDIO_PREPARED:
  157 + // 显示应该是在audio end prepare之后回调
  158 + if (isTouch) {
  159 + mTime = 0;
  160 + mDialogManager.showRecordingDialog();
  161 + isRecording = true;
  162 + new Thread(mGetVoiceLevelRunnable).start();
  163 + }
  164 + // 需要开启一个线程来变换音量
  165 + break;
  166 + case MSG_VOICE_CHANGE:
  167 + mDialogManager.updateVoiceLevel(mAudioManager.getVoiceLevel(3));
  168 + break;
  169 + case MSG_DIALOG_DIMISS:
  170 + isRecording = false;
  171 + mDialogManager.dimissDialog();
  172 + break;
  173 + case MSG_OVERTIME_SEND:
  174 + mDialogManager.tooLong();
  175 + mhandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);// 持续1.3s
  176 + if (mListener != null) {// 并且callbackActivity,保存录音
  177 + File file = new File(mAudioManager.getCurrentFilePath());
  178 + if (FileSaveUtil.isFileExists(file)) {
  179 + mListener.onFinished(mTime,
  180 + mAudioManager.getCurrentFilePath());
  181 + }else{
  182 + mp3handler.sendEmptyMessage(AudioManager.MSG_ERROR_AUDIO_RECORD);
  183 + }
  184 + }
  185 + isRecording = false;
  186 + reset();// 恢复标志位
  187 + break;
  188 + }
  189 + };
  190 + };
  191 +
  192 + // 在这里面发送一个handler的消息
  193 + @Override
  194 + public void wellPrepared() {
  195 + // TODO Auto-generated method stub
  196 + mhandler.sendEmptyMessage(MSG_AUDIO_PREPARED);
  197 + }
  198 +
  199 + /**
  200 + * 直接复写这个监听函数
  201 + */
  202 + private boolean isTouch = false;
  203 +
  204 + @SuppressLint("ClickableViewAccessibility")
  205 + @Override
  206 + public boolean onTouchEvent(MotionEvent event) {
  207 + // TODO Auto-generated method stub
  208 + int action = event.getAction();
  209 + int x = (int) event.getX();
  210 + int y = (int) event.getY();
  211 +
  212 + switch (action) {
  213 + case MotionEvent.ACTION_DOWN:
  214 + isTouch = true;
  215 + changeState(STATE_RECORDING);
  216 + break;
  217 + case MotionEvent.ACTION_MOVE:
  218 +
  219 + if (isRecording) {
  220 +
  221 + // 根据x,y来判断用户是否想要取消
  222 + if (wantToCancel(x, y)) {
  223 + changeState(STATE_WANT_TO_CANCEL);
  224 + } else {
  225 + changeState(STATE_RECORDING);
  226 + }
  227 +
  228 + }
  229 +
  230 + break;
  231 + case MotionEvent.ACTION_UP:
  232 + // 首先判断是否有触发onlongclick事件,没有的话直接返回reset
  233 + isTouch = false;
  234 + if (!mReady) {
  235 + reset();
  236 + return super.onTouchEvent(event);
  237 + }
  238 + // 如果按的时间太短,还没准备好或者时间录制太短,就离开了,则显示这个dialog
  239 + if (!isRecording || mTime < 0.6f) {
  240 + mDialogManager.tooShort();
  241 + mAudioManager.cancel();
  242 + mhandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);// 持续1.3s
  243 + } else if (mCurrentState == STATE_RECORDING) {// 正常录制结束
  244 + mDialogManager.dimissDialog();
  245 + mAudioManager.release();// release释放一个mediarecorder
  246 + if (mListener != null) {// 并且callbackActivity,保存录音
  247 + BigDecimal b = new BigDecimal(mTime);
  248 + float f1 = b.setScale(1, BigDecimal.ROUND_HALF_UP)
  249 + .floatValue();
  250 + File file = new File(mAudioManager.getCurrentFilePath());
  251 + if (FileSaveUtil.isFileExists(file)) {
  252 + mListener.onFinished(f1,mAudioManager.getCurrentFilePath());
  253 + }else{
  254 + mp3handler.sendEmptyMessage(AudioManager.MSG_ERROR_AUDIO_RECORD);
  255 + }
  256 + }
  257 + } else if (mCurrentState == STATE_WANT_TO_CANCEL) {
  258 + mAudioManager.cancel();
  259 + mDialogManager.dimissDialog();
  260 + }
  261 + isRecording = false;
  262 + reset();// 恢复标志位
  263 +
  264 + break;
  265 + case MotionEvent.ACTION_CANCEL:
  266 + isTouch = false;
  267 + reset();
  268 + break;
  269 +
  270 + }
  271 +
  272 + return super.onTouchEvent(event);
  273 + }
  274 +
  275 + /**
  276 + * 回复标志位以及状态
  277 + */
  278 + private void reset() {
  279 + // TODO Auto-generated method stub
  280 + isRecording = false;
  281 + changeState(STATE_NORMAL);
  282 + mReady = false;
  283 + mTime = 0;
  284 + }
  285 +
  286 + private boolean wantToCancel(int x, int y) {
  287 + // TODO Auto-generated method stub
  288 +
  289 + if (x < 0 || x > getWidth()) {// 判断是否在左边,右边,上边,下边
  290 + return true;
  291 + }
  292 + if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
  293 + return true;
  294 + }
  295 +
  296 + return false;
  297 + }
  298 +
  299 + private void changeState(int state) {
  300 + // TODO Auto-generated method stub
  301 + if (mCurrentState != state) {
  302 + mCurrentState = state;
  303 + switch (mCurrentState) {
  304 + case STATE_NORMAL:
  305 + setBackgroundResource(R.drawable.button_recordnormal);
  306 + setText(R.string.normal);
  307 +
  308 + break;
  309 + case STATE_RECORDING:
  310 + setBackgroundResource(R.drawable.button_recording);
  311 + setText(R.string.recording);
  312 + if (isRecording) {
  313 + mDialogManager.recording();
  314 + // 复写dialog.recording();
  315 + }
  316 + break;
  317 +
  318 + case STATE_WANT_TO_CANCEL:
  319 + setBackgroundResource(R.drawable.button_recording);
  320 + setText(R.string.want_to_cancle);
  321 + // dialog want to cancel
  322 + mDialogManager.wantToCancel();
  323 + break;
  324 +
  325 + }
  326 + }
  327 +
  328 + }
  329 +
  330 + @Override
  331 + public boolean onPreDraw() {
  332 + // TODO Auto-generated method stub
  333 + return false;
  334 + }
  335 +
  336 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/BubbleImageView.java 0 → 100644
... ... @@ -0,0 +1,139 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.graphics.Bitmap;
  6 +import android.graphics.Bitmap.Config;
  7 +import android.graphics.BitmapFactory;
  8 +import android.graphics.Canvas;
  9 +import android.graphics.NinePatch;
  10 +import android.graphics.Paint;
  11 +import android.graphics.PorterDuff.Mode;
  12 +import android.graphics.PorterDuffXfermode;
  13 +import android.graphics.Rect;
  14 +import android.os.Handler;
  15 +import android.util.AttributeSet;
  16 +import android.view.Display;
  17 +import android.view.WindowManager;
  18 +import android.widget.ImageView;
  19 +
  20 +import com.bumptech.glide.Glide;
  21 +import com.bumptech.glide.request.animation.GlideAnimation;
  22 +import com.bumptech.glide.request.target.SimpleTarget;
  23 +
  24 +
  25 +public class BubbleImageView extends ImageView {
  26 + private Context context;
  27 + private Bitmap iconBitmap;
  28 + private int res;
  29 + private static final int OK_INT = 0x0001;
  30 + private static final int ERROR_INT = 0x0000;
  31 + @SuppressLint("HandlerLeak")
  32 + private Handler bitmapHandler = new Handler() {
  33 + public void handleMessage(android.os.Message msg) {
  34 + switch (msg.what) {
  35 + case OK_INT:
  36 + Bitmap bitmap_bg = BitmapFactory.decodeResource(getResources(),
  37 + res);
  38 + final Bitmap bp = getRoundCornerImage(bitmap_bg, iconBitmap);
  39 + setImageBitmap(bp);
  40 + break;
  41 + case ERROR_INT:
  42 + break;
  43 + }
  44 + };
  45 + };
  46 +
  47 + public BubbleImageView(Context context) {
  48 + super(context);
  49 + this.context = context;
  50 + }
  51 +
  52 + public BubbleImageView(Context context, AttributeSet attrs) {
  53 + super(context, attrs);
  54 + this.context = context;
  55 + }
  56 +
  57 + public BubbleImageView(Context context, AttributeSet attrs, int defStyle) {
  58 + super(context, attrs, defStyle);
  59 + this.context = context;
  60 + }
  61 +
  62 + public void load(String url, int res, int placeHolderPic) {
  63 + this.setImageResource(placeHolderPic);
  64 + this.res = res;
  65 + Glide.with(context).load(url).asBitmap().into(new SimpleTarget<Bitmap>() {
  66 + @Override
  67 + public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
  68 + if (resource != null) {
  69 + iconBitmap = resource;
  70 + bitmapHandler.sendEmptyMessage(OK_INT);
  71 + }
  72 + }
  73 + });
  74 + }
  75 +
  76 + public void setLocalImageBitmap(Bitmap bm, int res) {
  77 + // TODO Auto-generated method stub
  78 + Bitmap bitmap_bg = BitmapFactory.decodeResource(getResources(), res);
  79 + final Bitmap bp = getRoundCornerImage(bitmap_bg, bm);
  80 + setImageBitmap(bp);
  81 + }
  82 +
  83 + public Bitmap getRoundCornerImage(Bitmap bitmap_bg, Bitmap bitmap_in) {
  84 + int width = bitmap_in.getWidth();
  85 + int height = bitmap_in.getHeight();
  86 + if(height != 0){
  87 + double scale = (width * 1.00) / height;
  88 + if (width >= height) {
  89 + width = getBitmapWidth();
  90 + height = (int) (width / scale);
  91 + } else {
  92 + height = getBitmapHeight();
  93 + width = (int) (height * scale);
  94 + }
  95 + }else{
  96 + width = 100;
  97 + height = 100;
  98 + }
  99 + Bitmap roundConcerImage = Bitmap.createBitmap(width, height,
  100 + Config.ARGB_8888);
  101 + Canvas canvas = new Canvas(roundConcerImage);
  102 + Paint paint = new Paint();
  103 + Rect rect = new Rect(0, 0, width, height);
  104 + Rect rectF = new Rect(0, 0, bitmap_in.getWidth(), bitmap_in.getHeight());
  105 + paint.setAntiAlias(true);
  106 + NinePatch patch = new NinePatch(bitmap_bg,
  107 + bitmap_bg.getNinePatchChunk(), null);
  108 + patch.draw(canvas, rect);
  109 + paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
  110 + canvas.drawBitmap(bitmap_in, rectF, rect, paint);
  111 + return roundConcerImage;
  112 + }
  113 +
  114 + // 获取屏幕的宽度
  115 + @SuppressWarnings("deprecation")
  116 + public int getScreenWidth(Context context) {
  117 + WindowManager manager = (WindowManager) context
  118 + .getSystemService(Context.WINDOW_SERVICE);
  119 + Display display = manager.getDefaultDisplay();
  120 + return display.getWidth();
  121 + }
  122 +
  123 + // 获取屏幕的高度
  124 + @SuppressWarnings("deprecation")
  125 + public int getScreenHeight(Context context) {
  126 + WindowManager manager = (WindowManager) context
  127 + .getSystemService(Context.WINDOW_SERVICE);
  128 + Display display = manager.getDefaultDisplay();
  129 + return display.getHeight();
  130 + }
  131 +
  132 + public int getBitmapWidth() {
  133 + return getScreenWidth(context) / 3;
  134 + }
  135 +
  136 + public int getBitmapHeight() {
  137 + return getScreenHeight(context) / 4;
  138 + }
  139 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/ChatBottomView.java 0 → 100644
... ... @@ -0,0 +1,70 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.content.Context;
  4 +import android.util.AttributeSet;
  5 +import android.view.LayoutInflater;
  6 +import android.view.View;
  7 +import android.widget.LinearLayout;
  8 +
  9 +import com.shunzhi.mychartlibrary.R;
  10 +
  11 +public class ChatBottomView extends LinearLayout{
  12 + private View baseView;
  13 + private LinearLayout imageGroup;
  14 + private LinearLayout cameraGroup;
  15 + private LinearLayout phraseGroup;
  16 + private HeadIconSelectorView.OnHeadIconClickListener onHeadIconClickListener;
  17 + public static final int FROM_CAMERA = 1;
  18 + public static final int FROM_GALLERY = 2;
  19 + public static final int FROM_PHRASE = 3;
  20 + public ChatBottomView(Context context, AttributeSet attrs) {
  21 + super(context, attrs);
  22 + // TODO Auto-generated constructor stub
  23 + findView();
  24 + init();
  25 + }
  26 +
  27 + private void findView(){
  28 + baseView = LayoutInflater.from(getContext()).inflate(R.layout.layout_tongbaobottom, this);
  29 + imageGroup = (LinearLayout) baseView.findViewById(R.id.image_bottom_group);
  30 + cameraGroup = (LinearLayout) baseView.findViewById(R.id.camera_group);
  31 + phraseGroup = (LinearLayout) baseView.findViewById(R.id.phrase_group);
  32 + }
  33 + private void init(){
  34 + cameraGroup.setOnClickListener(new OnClickListener() {
  35 +
  36 + @Override
  37 + public void onClick(View v) {
  38 + if (null != onHeadIconClickListener) {
  39 + onHeadIconClickListener.onClick(FROM_CAMERA);
  40 + }
  41 + }
  42 + });
  43 + imageGroup.setOnClickListener(new OnClickListener() {
  44 +
  45 + @Override
  46 + public void onClick(View v) {
  47 +
  48 + if (null != onHeadIconClickListener) {
  49 + onHeadIconClickListener.onClick(FROM_GALLERY);
  50 + }
  51 + }
  52 + });
  53 + phraseGroup.setOnClickListener(new OnClickListener() {
  54 +
  55 + @Override
  56 + public void onClick(View v) {
  57 +
  58 + if (null != onHeadIconClickListener) {
  59 + onHeadIconClickListener.onClick(FROM_PHRASE);
  60 + }
  61 + }
  62 + });
  63 + }
  64 +
  65 + public void setOnHeadIconClickListener(
  66 + HeadIconSelectorView.OnHeadIconClickListener onHeadIconClickListener) {
  67 + // TODO Auto-generated method stub
  68 + this.onHeadIconClickListener = onHeadIconClickListener;
  69 + }
  70 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/CustomShapeTransformation.java 0 → 100644
... ... @@ -0,0 +1,109 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Bitmap;
  5 +import android.graphics.Canvas;
  6 +import android.graphics.Paint;
  7 +import android.graphics.PorterDuff;
  8 +import android.graphics.PorterDuffXfermode;
  9 +import android.graphics.drawable.Drawable;
  10 +import android.support.v4.content.ContextCompat;
  11 +import android.view.Display;
  12 +import android.view.WindowManager;
  13 +
  14 +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
  15 +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
  16 +import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
  17 +
  18 +/**
  19 + * Created by Mao Jiqing on 2016/11/4.
  20 + */
  21 +
  22 +public class CustomShapeTransformation extends BitmapTransformation {
  23 +
  24 + private Paint mPaint; // 画笔
  25 + private Context mContext;
  26 + private int mShapeRes; // 形状的drawable资源
  27 +
  28 + public CustomShapeTransformation(Context context, int shapeRes) {
  29 + super(context);
  30 + mContext = context;
  31 + mShapeRes = shapeRes;
  32 + // 实例化Paint对象,并设置Xfermode为SRC_IN
  33 + mPaint = new Paint();
  34 + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  35 + }
  36 +
  37 + @Override
  38 + // 复写该方法,完成图片的转换
  39 + public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
  40 + // 获取到形状资源的Drawable对象
  41 + Drawable shape = ContextCompat.getDrawable(mContext, mShapeRes);
  42 + int width = toTransform.getWidth();
  43 + int height = toTransform.getHeight();
  44 + if(height != 0){
  45 + double scale = (width * 1.00) / height;
  46 + if (width >= height) {
  47 + width = getBitmapWidth();
  48 + height = (int) (width / scale);
  49 + } else {
  50 + height = getBitmapHeight();
  51 + width = (int) (height * scale);
  52 + }
  53 + }else{
  54 + width = 100;
  55 + height = 100;
  56 + }
  57 + // 居中裁剪图片,调用Glide库中TransformationUtils类的centerCrop()方法完成裁剪,保证图片居中且填满
  58 + final Bitmap toReuse = pool.get(width, height, toTransform.getConfig() != null
  59 + ? toTransform.getConfig() : Bitmap.Config.ARGB_8888);
  60 + Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, width, height);
  61 + if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {
  62 + toReuse.recycle();
  63 + }
  64 +
  65 + // 根据算出的宽高新建Bitmap对象并设置到画布上
  66 + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  67 + Canvas canvas = new Canvas(bitmap);
  68 + // 设置形状的大小与图片的大小一致
  69 + shape.setBounds(0, 0, width, height);
  70 + // 将图片画到画布上
  71 + shape.draw(canvas);
  72 + // 将裁剪后的图片画得画布上
  73 + canvas.drawBitmap(transformed, 0, 0, mPaint);
  74 +
  75 + return bitmap;
  76 + }
  77 +
  78 + @Override
  79 + public String getId() {
  80 + // 用于缓存的唯一标识符
  81 + return "CustomShapeTransformation" + mShapeRes;
  82 + }
  83 +
  84 + // 获取屏幕的宽度
  85 + @SuppressWarnings("deprecation")
  86 + public int getScreenWidth(Context context) {
  87 + WindowManager manager = (WindowManager) context
  88 + .getSystemService(Context.WINDOW_SERVICE);
  89 + Display display = manager.getDefaultDisplay();
  90 + return display.getWidth();
  91 + }
  92 +
  93 + // 获取屏幕的高度
  94 + @SuppressWarnings("deprecation")
  95 + public int getScreenHeight(Context context) {
  96 + WindowManager manager = (WindowManager) context
  97 + .getSystemService(Context.WINDOW_SERVICE);
  98 + Display display = manager.getDefaultDisplay();
  99 + return display.getHeight();
  100 + }
  101 +
  102 + public int getBitmapWidth() {
  103 + return getScreenWidth(mContext) / 3;
  104 + }
  105 +
  106 + public int getBitmapHeight() {
  107 + return getScreenHeight(mContext) / 4;
  108 + }
  109 +}
0 110 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/DialogManager.java 0 → 100644
... ... @@ -0,0 +1,148 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.app.Dialog;
  5 +import android.content.Context;
  6 +import android.view.LayoutInflater;
  7 +import android.view.View;
  8 +import android.view.Window;
  9 +import android.view.WindowManager;
  10 +import android.widget.ImageView;
  11 +import android.widget.TextView;
  12 +
  13 +import com.shunzhi.mychartlibrary.R;
  14 +import com.shunzhi.mychartlibrary.utils.ScreenUtil;
  15 +
  16 +@SuppressLint("InflateParams")
  17 +public class DialogManager {
  18 +
  19 + /**
  20 + * 以下为dialog的初始化控件,包括其中的布局文件
  21 + */
  22 +
  23 + private Dialog mDialog;
  24 +
  25 + private ImageView mIcon;
  26 + private ImageView mVoice;
  27 +
  28 + private TextView mLable;
  29 +
  30 + private Context mContext;
  31 +
  32 + public DialogManager(Context context) {
  33 + // TODO Auto-generated constructor stub
  34 + mContext = context;
  35 + }
  36 +
  37 + public void showRecordingDialog() {
  38 + // TODO Auto-generated method stub
  39 +
  40 + mDialog = new Dialog(mContext, R.style.Theme_audioDialog);
  41 + mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
  42 +
  43 + // 用layoutinflater来引用布局
  44 + LayoutInflater inflater = LayoutInflater.from(mContext);
  45 + View view = inflater.inflate(R.layout.layout_voice_dialog_manager, null);
  46 + mDialog.setContentView(view);
  47 +
  48 + mIcon = (ImageView) mDialog.findViewById(R.id.dialog_icon);
  49 + mVoice = (ImageView) mDialog.findViewById(R.id.dialog_voice);
  50 + mLable = (TextView) mDialog.findViewById(R.id.recorder_dialogtext);
  51 +
  52 + Window dialogWindow = mDialog.getWindow();
  53 + WindowManager.LayoutParams lp = dialogWindow.getAttributes();
  54 + int width = ScreenUtil.getScreenWidth(mContext) / 2;
  55 + lp.width = width; // 宽度
  56 + lp.height = width; // 高度
  57 + dialogWindow.setAttributes(lp);
  58 + mDialog.setCancelable(false);
  59 + mDialog.show();
  60 +
  61 + }
  62 +
  63 + /**
  64 + * 设置正在录音时的dialog界面
  65 + */
  66 + public void recording() {
  67 + if (mDialog != null && mDialog.isShowing()) {
  68 + mIcon.setVisibility(View.GONE);
  69 + mVoice.setVisibility(View.VISIBLE);
  70 + mLable.setVisibility(View.VISIBLE);
  71 + mLable.setText(R.string.shouzhishanghua);
  72 + }
  73 + }
  74 +
  75 + /**
  76 + * 取消界面
  77 + */
  78 + public void wantToCancel() {
  79 + // TODO Auto-generated method stub
  80 + if (mDialog != null && mDialog.isShowing()) {
  81 + mIcon.setVisibility(View.VISIBLE);
  82 + mVoice.setVisibility(View.GONE);
  83 + mLable.setVisibility(View.VISIBLE);
  84 +
  85 + mIcon.setImageResource(R.mipmap.cancel);
  86 + mLable.setText(R.string.want_to_cancle);
  87 + }
  88 +
  89 + }
  90 +
  91 + // 时间过短
  92 + public void tooShort() {
  93 + // TODO Auto-generated method stub
  94 + if (mDialog != null && mDialog.isShowing()) {
  95 + mIcon.setVisibility(View.VISIBLE);
  96 + mVoice.setVisibility(View.GONE);
  97 + mLable.setVisibility(View.VISIBLE);
  98 +
  99 + mIcon.setImageResource(R.mipmap.voice_to_short);
  100 + mLable.setText(R.string.tooshort);
  101 + }
  102 +
  103 + }
  104 + // 时间过长
  105 + public void tooLong() {
  106 + // TODO Auto-generated method stub
  107 + if (mDialog != null && mDialog.isShowing()) {
  108 + mIcon.setVisibility(View.VISIBLE);
  109 + mVoice.setVisibility(View.GONE);
  110 + mLable.setVisibility(View.VISIBLE);
  111 +
  112 + mIcon.setImageResource(R.mipmap.voice_to_short);
  113 + mLable.setText(R.string.toolong);
  114 + }
  115 +
  116 + }
  117 + // 隐藏dialog
  118 + public void dimissDialog() {
  119 + // TODO Auto-generated method stub
  120 +
  121 + if (mDialog != null && mDialog.isShowing()) {
  122 + mDialog.dismiss();
  123 + mDialog = null;
  124 + }
  125 +
  126 + }
  127 +
  128 + public void updateVoiceLevel(int level) {
  129 + // TODO Auto-generated method stub
  130 +
  131 + if (mDialog != null && mDialog.isShowing()) {
  132 + int resId;
  133 + if(level >= 1 && level < 2){
  134 + resId = mContext.getResources().getIdentifier("tb_voice1",
  135 + "mipmap", mContext.getPackageName());
  136 + }else if(level >= 2 && level < 3){
  137 + resId = mContext.getResources().getIdentifier("tb_voice2",
  138 + "mipmap", mContext.getPackageName());
  139 + }else{
  140 + resId = mContext.getResources().getIdentifier("tb_voice3",
  141 + "mipmap", mContext.getPackageName());
  142 + }
  143 + mVoice.setImageResource(resId);
  144 + }
  145 +
  146 + }
  147 +
  148 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/ExpandGridView.java 0 → 100644
... ... @@ -0,0 +1,38 @@
  1 +/**
  2 + * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + * http://www.apache.org/licenses/LICENSE-2.0
  8 + * Unless required by applicable law or agreed to in writing, software
  9 + * distributed under the License is distributed on an "AS IS" BASIS,
  10 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11 + * See the License for the specific language governing permissions and
  12 + * limitations under the License.
  13 + */
  14 +package com.shunzhi.mychartlibrary.widget;
  15 +
  16 +import android.content.Context;
  17 +import android.util.AttributeSet;
  18 +import android.widget.GridView;
  19 +
  20 +public class ExpandGridView extends GridView {
  21 +
  22 + public ExpandGridView(Context context) {
  23 + super(context);
  24 + }
  25 +
  26 + public ExpandGridView(Context context, AttributeSet attrs) {
  27 + super(context, attrs);
  28 + }
  29 +
  30 +
  31 + @Override
  32 + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  33 + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
  34 + super.onMeasure(widthMeasureSpec, expandSpec);
  35 + }
  36 +
  37 +
  38 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/GifTextView.java 0 → 100644
... ... @@ -0,0 +1,303 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.graphics.Bitmap;
  6 +import android.graphics.BitmapFactory;
  7 +import android.os.Handler;
  8 +import android.text.Spannable;
  9 +import android.text.SpannableString;
  10 +import android.text.style.ImageSpan;
  11 +import android.util.AttributeSet;
  12 +import android.widget.EditText;
  13 +
  14 +
  15 +import com.shunzhi.mychartlibrary.utils.FaceData;
  16 +import com.shunzhi.mychartlibrary.utils.GifOpenHelper;
  17 +import com.shunzhi.mychartlibrary.utils.ScreenUtil;
  18 +
  19 +import java.lang.ref.WeakReference;
  20 +import java.util.ArrayList;
  21 +import java.util.regex.Matcher;
  22 +import java.util.regex.Pattern;
  23 +
  24 +public class GifTextView extends EditText {
  25 + /**
  26 + * 注:如果获取的gif帧与帧之间的时间间隔都不相同,建议调个固定的,最好的方法是将gif图的间隔设置相同
  27 + */
  28 + private static final int DELAYED = 300;
  29 +
  30 + /**
  31 + * @author Dragon SpanInfo
  32 + * 类用于存储一个要显示的图片(动态或静态)的信息,包括分解后的每一帧mapList、替代文字的起始位置、终止位置
  33 + * 、帧的总数、当前需要显示的帧、帧与帧之间的时间间隔
  34 + */
  35 + private class SpanInfo {
  36 + ArrayList<Bitmap> mapList;
  37 + @SuppressWarnings("unused")
  38 + int start, end, frameCount, currentFrameIndex, delay;
  39 +
  40 + public SpanInfo() {
  41 + mapList = new ArrayList<Bitmap>();
  42 + start = end = frameCount = currentFrameIndex = delay = 0;
  43 + }
  44 + }
  45 +
  46 + /**
  47 + * spanInfoList 是一个SpanInfo的list ,用于处理一个TextView中出现多个要匹配的图片的情况
  48 + */
  49 + private ArrayList<SpanInfo> spanInfoList = null;
  50 + private Handler handler; // 用于处理从子线程TextView传来的消息
  51 + private String myText; // 存储textView应该显示的文本
  52 +
  53 + /**
  54 + * 这三个构造方法一个也不要少,否则会产生CastException,注意在这三个构造函数中都为spanInfoList实例化,可能有些浪费
  55 + * ,但保证不会有空指针异常
  56 + *
  57 + * @param context
  58 + * @param attrs
  59 + * @param defStyle
  60 + */
  61 + @SuppressLint("NewApi")
  62 + public GifTextView(Context context, AttributeSet attrs, int defStyle) {
  63 + super(context, attrs, defStyle);
  64 + // TODO Auto-generated constructor stub
  65 + // spanInfoList = new ArrayList<SpanInfo>();
  66 + GifTextView.this.setFocusableInTouchMode(false);
  67 + }
  68 +
  69 + @SuppressLint("NewApi")
  70 + public GifTextView(Context context, AttributeSet attrs) {
  71 + super(context, attrs);
  72 + // TODO Auto-generated constructor stub
  73 + // spanInfoList = new ArrayList<SpanInfo>();
  74 + GifTextView.this.setFocusableInTouchMode(false);
  75 + }
  76 +
  77 + @SuppressLint("NewApi")
  78 + public GifTextView(Context context) {
  79 + super(context);
  80 + // TODO Auto-generated constructor stub
  81 + // spanInfoList = new ArrayList<SpanInfo>();
  82 + GifTextView.this.setFocusableInTouchMode(false);
  83 + }
  84 +
  85 + /**
  86 + * 对要显示在textView上的文本进行解析,看看是否文本中有需要与Gif或者静态图片匹配的文本 若有,那么调用parseGif
  87 + * 对该文本对应的Gif图片进行解析 或者嗲用parseBmp解析静态图片
  88 + *
  89 + * @param inputStr
  90 + */
  91 + private boolean parseText(String inputStr) {
  92 + myText = inputStr;
  93 +// Pattern mPattern = Pattern.compile("\\[:..\\]|\\[:...\\]");
  94 + Pattern mPattern = Pattern.compile("\\[[^\\]]+\\]");
  95 + Matcher mMatcher = mPattern.matcher(inputStr);
  96 + boolean hasGif = false;
  97 + while (mMatcher.find()) {
  98 + String faceName = mMatcher.group();
  99 + Integer faceId = null;
  100 + /**
  101 + * 这里匹配时用到了图片库,即一个专门存放图片id和其匹配的名称的静态对象,这两个静态对象放在了FaceData.java
  102 + * 中,并采用了静态块的方法进行了初始化,不会有空指针异常
  103 + */
  104 + if ((faceId = FaceData.gifFaceInfo.get(faceName)) != null) {
  105 + if (isGif) {
  106 + parseGif(faceId, mMatcher.start(), mMatcher.end());
  107 + } else {
  108 + parseBmp(faceId, mMatcher.start(), mMatcher.end());
  109 + }
  110 + }
  111 + hasGif = true;
  112 + }
  113 + return hasGif;
  114 + }
  115 +
  116 + /**
  117 + * 对静态图片进行解析:
  118 + * 创建一个SpanInfo对象,帧数设为1,按照下面的参数设置,最后不要忘记将SpanInfo对象添加进spanInfoList中, 否则不会显示
  119 + *
  120 + * @param resourceId
  121 + * @param start
  122 + * @param end
  123 + */
  124 + @SuppressWarnings("unused")
  125 + private void parseBmp(int resourceId, int start, int end) {
  126 + Bitmap bitmap = BitmapFactory.decodeResource(getContext()
  127 + .getResources(), resourceId);
  128 + ImageSpan imageSpan = new ImageSpan(getContext(), bitmap);
  129 + SpanInfo spanInfo = new SpanInfo();
  130 + spanInfo.currentFrameIndex = 0;
  131 + spanInfo.frameCount = 1;
  132 + spanInfo.start = start;
  133 + spanInfo.end = end;
  134 + spanInfo.delay = 100;
  135 + spanInfo.mapList.add(bitmap);
  136 + spanInfoList.add(spanInfo);
  137 +
  138 + }
  139 +
  140 + /**
  141 + * 解析Gif图片,与静态图片唯一的不同是这里需要调用GifOpenHelper类读取Gif返回一系一组bitmap(用for 循环把这一
  142 + * 组的bitmap存储在SpanInfo.mapList中,此时的frameCount参数也大于1了)
  143 + *
  144 + * @param resourceId
  145 + * @param start
  146 + * @param end
  147 + */
  148 + private void parseGif(int resourceId, int start, int end) {
  149 +
  150 + GifOpenHelper helper = new GifOpenHelper();
  151 + helper.read(getContext().getResources().openRawResource(resourceId));
  152 + SpanInfo spanInfo = new SpanInfo();
  153 + spanInfo.currentFrameIndex = 0;
  154 + spanInfo.frameCount = helper.getFrameCount();
  155 + spanInfo.start = start;
  156 + spanInfo.end = end;
  157 + spanInfo.mapList.add(helper.getImage());
  158 + for (int i = 1; i < helper.getFrameCount(); i++) {
  159 + spanInfo.mapList.add(helper.nextBitmap());
  160 + }
  161 + spanInfo.delay = helper.nextDelay(); // 获得每一帧之间的延迟
  162 + spanInfoList.add(spanInfo);
  163 +
  164 + }
  165 +
  166 + private boolean isGif;
  167 +
  168 + /**
  169 + * GifTextView 与外部对象的接口,以后设置文本内容时使用setSpanText() 而不再是setText();
  170 + *
  171 + * @param handler
  172 + * @param text
  173 + */
  174 + public void setSpanText(Handler handler, final String text, boolean isGif) {
  175 + this.handler = handler; // 获得UI的Handler
  176 + this.isGif = isGif;
  177 + spanInfoList = new ArrayList<SpanInfo>();
  178 +// ThreadPoolUtils.execute(new Runnable() {
  179 +//
  180 +// @Override
  181 +// public void run() {
  182 +//// // TODO Auto-generated method stub
  183 + if (parseText(text)) {// 对String对象进行解析
  184 +// mStartHandler.sendEmptyMessage(0);
  185 + if (parseMessage(this)) {
  186 + startPost();
  187 + }
  188 + } else {
  189 +// mStartHandler.sendEmptyMessage(1);
  190 + setText(myText);
  191 + }
  192 +// }
  193 +// });
  194 + }
  195 +
  196 +// private StartHandler mStartHandler = new StartHandler(this);
  197 +//
  198 +// public static class StartHandler extends Handler {
  199 +// private final WeakReference<GifTextView> mGifWeakReference;
  200 +//
  201 +// public StartHandler(GifTextView gifTextView) {
  202 +// mGifWeakReference = new WeakReference<GifTextView>(gifTextView);
  203 +// }
  204 +//
  205 +// @Override
  206 +// public void handleMessage(Message msg) {
  207 +// GifTextView gifTextView = mGifWeakReference.get();
  208 +// if (gifTextView != null) {
  209 +// if (msg.what == 0) {
  210 +// gifTextView.startPost();
  211 +// } else if (msg.what == 1) {
  212 +// gifTextView.setText(gifTextView.myText);
  213 +// }
  214 +// }
  215 +// }
  216 +// }
  217 +
  218 + public boolean parseMessage(GifTextView gifTextView) {
  219 + if (gifTextView.myText != null && !gifTextView.myText.equals("")) {
  220 + SpannableString sb = new SpannableString("" + gifTextView.myText); // 获得要显示的文本
  221 + int gifCount = 0;
  222 + SpanInfo info = null;
  223 + for (int i = 0; i < gifTextView.spanInfoList.size(); i++) { // for循环,处理显示多个图片的问题
  224 + info = gifTextView.spanInfoList.get(i);
  225 + if (info.mapList.size() > 1) {
  226 + /*
  227 + * gifCount用来区分是Gif还是BMP,若是gif gifCount>0
  228 + * ,否则gifCount=0
  229 + */
  230 + gifCount++;
  231 +
  232 + }
  233 + Bitmap bitmap = info.mapList
  234 + .get(info.currentFrameIndex);
  235 + info.currentFrameIndex = (info.currentFrameIndex + 1)
  236 + % (info.frameCount);
  237 + /**
  238 + * currentFrameIndex
  239 + * 用于控制当前应该显示的帧的序号,每次显示之后currentFrameIndex 应该加1
  240 + * ,加到frameCount后再变成0循环显示
  241 + */
  242 + int size = ScreenUtil.dip2px(gifTextView.getContext(), 30);
  243 + if (gifCount != 0) {
  244 + bitmap = Bitmap.createScaledBitmap(bitmap, size,
  245 + size, true);
  246 +
  247 + } else {
  248 + bitmap = Bitmap.createScaledBitmap(bitmap, size,
  249 + size, true);
  250 + }
  251 + ImageSpan imageSpan = new ImageSpan(gifTextView.getContext(),
  252 + bitmap);
  253 + if (info.end <= sb.length()) {
  254 + sb.setSpan(imageSpan, info.start, info.end,
  255 + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  256 + } else {
  257 + break;
  258 + }
  259 +
  260 + }
  261 + // 对所有的图片对应的ImageSpan完成设置后,调用TextView的setText方法设置文本
  262 + gifTextView.setText(sb);
  263 + if (gifCount != 0) {
  264 + return true;
  265 + } else {
  266 + return false;
  267 + }
  268 + }
  269 + return false;
  270 + }
  271 +
  272 + public TextRunnable rTextRunnable;
  273 +
  274 + public void startPost() {
  275 + rTextRunnable = new TextRunnable(this); // 生成Runnable对象
  276 + handler.post(rTextRunnable); // 利用UI线程的Handler 将r添加进消息队列中。
  277 + }
  278 +
  279 + public static final class TextRunnable implements Runnable {
  280 + private final WeakReference<GifTextView> mWeakReference;
  281 +
  282 + public TextRunnable(GifTextView f) {
  283 + mWeakReference = new WeakReference<GifTextView>(f);
  284 + }
  285 +
  286 + @Override
  287 + public void run() {
  288 + // TODO Auto-generated method stub
  289 + GifTextView gifTextView = mWeakReference.get();
  290 + if (gifTextView != null) {
  291 + /**
  292 + * 这一步是为了节省内存而是用,即如果文本中只有静态图片没有动态图片,那么该线程就此终止,不会重复执行
  293 + * 。而如果有动图,那么会一直执行
  294 + */
  295 + if (gifTextView.parseMessage(gifTextView)) {
  296 + gifTextView.handler.postDelayed(this, DELAYED);
  297 + }
  298 + }
  299 + }
  300 + }
  301 +
  302 +}
  303 +
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/HeadIconSelectorView.java 0 → 100644
... ... @@ -0,0 +1,331 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.view.GestureDetector;
  6 +import android.view.KeyEvent;
  7 +import android.view.LayoutInflater;
  8 +import android.view.MotionEvent;
  9 +import android.view.View;
  10 +import android.view.ViewGroup;
  11 +import android.view.animation.AlphaAnimation;
  12 +import android.view.animation.Animation;
  13 +import android.view.animation.Animation.AnimationListener;
  14 +import android.view.animation.ScaleAnimation;
  15 +import android.widget.LinearLayout;
  16 +import android.widget.RelativeLayout;
  17 +
  18 +import com.shunzhi.mychartlibrary.R;
  19 +
  20 +
  21 +public class HeadIconSelectorView extends RelativeLayout implements
  22 + GestureDetector.OnGestureListener {
  23 +
  24 + private View baseView;
  25 +
  26 + private RelativeLayout mainRl;
  27 + private LinearLayout bottomLl;
  28 + private LinearLayout cameraLl;
  29 + private LinearLayout galleryLl;
  30 + private LinearLayout cancelLl;
  31 +
  32 + private GestureDetector gestureDetector; // 手势检测器
  33 + private boolean isAnimationing = false;
  34 + private OnHeadIconClickListener onHeadIconClickListener;
  35 + public static final int FROM_CAMERA = 2;
  36 + public static final int FROM_GALLERY = 3;
  37 + public static final int CANCEL = 4;
  38 + public static final int BLANK_CANCEL = 5;
  39 +
  40 + public HeadIconSelectorView(Context context) {
  41 + super(context);
  42 + init();
  43 + }
  44 +
  45 + @SuppressLint("ClickableViewAccessibility")
  46 + private void init() {
  47 + findView();
  48 + this.setOnTouchListener(new OnTouchListener() {
  49 + @Override
  50 + public boolean onTouch(View v, MotionEvent event) {
  51 + return gestureDetector.onTouchEvent(event);
  52 + }
  53 + });
  54 + bottomLl.setVisibility(View.INVISIBLE);
  55 + mainRl.setOnClickListener(new OnClickListener() {
  56 +
  57 + @Override
  58 + public void onClick(View v) {
  59 + if (null != onHeadIconClickListener) {
  60 + onHeadIconClickListener.onClick(BLANK_CANCEL);
  61 + }
  62 + cancel();
  63 + }
  64 + });
  65 + cancelLl.setOnClickListener(new OnClickListener() {
  66 +
  67 + @Override
  68 + public void onClick(View v) {
  69 + if (null != onHeadIconClickListener) {
  70 + onHeadIconClickListener.onClick(CANCEL);
  71 + }
  72 + cancel();
  73 + }
  74 + });
  75 + cameraLl.setOnClickListener(new OnClickListener() {
  76 +
  77 + @Override
  78 + public void onClick(View v) {
  79 + if (null != onHeadIconClickListener) {
  80 + onHeadIconClickListener.onClick(FROM_CAMERA);
  81 + }
  82 + cancel();
  83 + }
  84 + });
  85 + galleryLl.setOnClickListener(new OnClickListener() {
  86 +
  87 + @Override
  88 + public void onClick(View v) {
  89 +
  90 + if (null != onHeadIconClickListener) {
  91 + onHeadIconClickListener.onClick(FROM_GALLERY);
  92 + }
  93 + cancel();
  94 + }
  95 + });
  96 + }
  97 +
  98 + @SuppressWarnings("deprecation")
  99 + private void findView() {
  100 + gestureDetector = new GestureDetector(this);
  101 + baseView = LayoutInflater.from(getContext()).inflate(
  102 + R.layout.layout_view_headicon, this);
  103 + mainRl = (RelativeLayout) baseView.findViewById(R.id.head_icon_main_rl);
  104 + bottomLl = (LinearLayout) baseView.findViewById(R.id.head_icon_main_ll);
  105 + cameraLl = (LinearLayout) baseView
  106 + .findViewById(R.id.head_icon_camera_ll);
  107 + galleryLl = (LinearLayout) baseView
  108 + .findViewById(R.id.head_icon_gallery_ll);
  109 + cancelLl = (LinearLayout) baseView
  110 + .findViewById(R.id.head_icon_cancel_ll);
  111 + }
  112 +
  113 + protected void bottomViewFlyIn() {
  114 + final ScaleAnimation sa1 = new ScaleAnimation(1, 1, 0, 1.2f,
  115 + Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 1f);
  116 + sa1.setDuration(250);
  117 + final ScaleAnimation sa2 = new ScaleAnimation(1, 1, 1.2f, 1,
  118 + Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 1f);
  119 + sa2.setDuration(150);
  120 + sa1.setAnimationListener(new AnimationListener() {
  121 +
  122 + @Override
  123 + public void onAnimationStart(Animation animation) {
  124 + isAnimationing = true;
  125 + bottomLl.setVisibility(VISIBLE);
  126 + }
  127 +
  128 + @Override
  129 + public void onAnimationRepeat(Animation animation) {
  130 + }
  131 +
  132 + @Override
  133 + public void onAnimationEnd(Animation animation) {
  134 + isAnimationing = false;
  135 + bottomLl.startAnimation(sa2);
  136 + }
  137 + });
  138 + bottomLl.startAnimation(sa1);
  139 + }
  140 +
  141 + protected void bottomViewFlyOut() {
  142 + final ScaleAnimation sa1 = new ScaleAnimation(1, 1, 1, 1.2f,
  143 + Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 1f);
  144 + sa1.setDuration(150);
  145 + final ScaleAnimation sa2 = new ScaleAnimation(1, 1, 1.2f, 0,
  146 + Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 1f);
  147 + sa2.setDuration(250);
  148 + sa1.setAnimationListener(new AnimationListener() {
  149 +
  150 + @Override
  151 + public void onAnimationStart(Animation animation) {
  152 + isAnimationing = true;
  153 + bottomLl.setVisibility(VISIBLE);
  154 + }
  155 +
  156 + @Override
  157 + public void onAnimationRepeat(Animation animation) {
  158 + }
  159 +
  160 + @Override
  161 + public void onAnimationEnd(Animation animation) {
  162 + bottomLl.startAnimation(sa2);
  163 + }
  164 + });
  165 + sa2.setAnimationListener(new AnimationListener() {
  166 +
  167 + @Override
  168 + public void onAnimationStart(Animation animation) {
  169 + }
  170 +
  171 + @Override
  172 + public void onAnimationRepeat(Animation animation) {
  173 + }
  174 +
  175 + @Override
  176 + public void onAnimationEnd(Animation animation) {
  177 + isAnimationing = false;
  178 + bottomLl.setVisibility(INVISIBLE);
  179 + flyOut();
  180 + }
  181 + });
  182 + bottomLl.startAnimation(sa1);
  183 + }
  184 +
  185 + protected void cancel() {
  186 + if (!isAnimationing) {
  187 + if (bottomLl.getVisibility() == VISIBLE) {
  188 + bottomViewFlyOut();
  189 + return;
  190 + }
  191 + }
  192 + }
  193 +
  194 + public void flyIn() {
  195 + AlphaAnimation aa = new AlphaAnimation(0, 1);
  196 + aa.setDuration(300);
  197 + aa.setAnimationListener(new AnimationListener() {
  198 +
  199 + @Override
  200 + public void onAnimationStart(Animation animation) {
  201 + isAnimationing = true;
  202 + setVisibility(VISIBLE);
  203 + }
  204 +
  205 + @Override
  206 + public void onAnimationRepeat(Animation animation) {
  207 + }
  208 +
  209 + @Override
  210 + public void onAnimationEnd(Animation animation) {
  211 + isAnimationing = false;
  212 + bottomViewFlyIn();
  213 + }
  214 + });
  215 + startAnimation(aa);
  216 + }
  217 +
  218 + public void flyOut() {
  219 + AlphaAnimation aa = new AlphaAnimation(1, 0);
  220 + aa.setDuration(300);
  221 + aa.setAnimationListener(new AnimationListener() {
  222 +
  223 + @Override
  224 + public void onAnimationStart(Animation animation) {
  225 + isAnimationing = true;
  226 + setVisibility(VISIBLE);
  227 + }
  228 +
  229 + @Override
  230 + public void onAnimationRepeat(Animation animation) {
  231 + }
  232 +
  233 + @Override
  234 + public void onAnimationEnd(Animation animation) {
  235 + isAnimationing = false;
  236 + destroy();
  237 + }
  238 + });
  239 + startAnimation(aa);
  240 + }
  241 +
  242 + protected void destroy() {
  243 + if (this.getParent() != null) {
  244 + ((ViewGroup) this.getParent()).removeView(this);
  245 + }
  246 + }
  247 +
  248 + @Override
  249 + public boolean onKeyDown(int keyCode, KeyEvent event) {
  250 + if (keyCode == KeyEvent.KEYCODE_BACK) {
  251 + if (!isAnimationing) {
  252 + if (bottomLl.getVisibility() == VISIBLE) {
  253 + bottomViewFlyOut();
  254 + return true;
  255 + }
  256 + } else {
  257 + return true;
  258 + }
  259 + }
  260 + return super.onKeyDown(keyCode, event);
  261 + }
  262 +
  263 + public OnHeadIconClickListener getOnHeadIconClickListener() {
  264 + return onHeadIconClickListener;
  265 + }
  266 +
  267 + public void setOnHeadIconClickListener(
  268 + OnHeadIconClickListener onHeadIconClickListener) {
  269 + this.onHeadIconClickListener = onHeadIconClickListener;
  270 + }
  271 +
  272 + public interface OnHeadIconClickListener {
  273 + public void onClick(int from);
  274 + }
  275 +
  276 + @SuppressLint("ClickableViewAccessibility")
  277 + @Override
  278 + public boolean onTouchEvent(MotionEvent event) {
  279 + return gestureDetector.onTouchEvent(event);
  280 + }
  281 +
  282 + @Override
  283 + public boolean onDown(MotionEvent e) {
  284 + // TODO Auto-generated method stub
  285 + return false;
  286 + }
  287 +
  288 + @Override
  289 + public void onShowPress(MotionEvent e) {
  290 + // TODO Auto-generated method stub
  291 +
  292 + }
  293 +
  294 + @Override
  295 + public boolean onSingleTapUp(MotionEvent e) {
  296 + // TODO Auto-generated method stub
  297 + return false;
  298 + }
  299 +
  300 + @Override
  301 + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
  302 + float distanceY) {
  303 + // TODO Auto-generated method stub
  304 + return false;
  305 + }
  306 +
  307 + @Override
  308 + public void onLongPress(MotionEvent e) {
  309 + // TODO Auto-generated method stub
  310 +
  311 + }
  312 +
  313 + private float minVelocityY = 100f;// 10个像素每秒
  314 + private float minDistanceY = 100f;// 100个像素
  315 +
  316 + // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN,
  317 + // 多个ACTION_MOVE, 1个ACTION_UP触发
  318 + // e1:第1个ACTION_DOWN MotionEvent
  319 + // e2:最后一个ACTION_MOVE MotionEvent
  320 + // velocityX:X轴上的移动速度,像素/秒
  321 + // velocityY:Y轴上的移动速度,像素/秒
  322 + @Override
  323 + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
  324 + float velocityY) {
  325 + // 手势从上到下且移动速度较快
  326 + if (e2.getY() - e1.getY() > minDistanceY && velocityY > minVelocityY) {
  327 + cancel();
  328 + }
  329 + return false;
  330 + }
  331 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/MediaManager.java 0 → 100644
... ... @@ -0,0 +1,84 @@
  1 +package com.shunzhi.mychartlibrary.widget;
  2 +
  3 +
  4 +
  5 +import android.media.AudioManager;
  6 +import android.media.MediaPlayer;
  7 +import android.media.MediaPlayer.OnCompletionListener;
  8 +import android.media.MediaPlayer.OnErrorListener;
  9 +
  10 +import java.io.IOException;
  11 +
  12 +public class MediaManager {
  13 +
  14 +
  15 + private static MediaPlayer mPlayer;
  16 +
  17 + private static boolean isPause;
  18 +
  19 + public static void playSound(String filePathString,
  20 + OnCompletionListener onCompletionListener) {
  21 + // TODO Auto-generated method stub
  22 + if (mPlayer==null) {
  23 + mPlayer=new MediaPlayer();
  24 + //保险起见,设置报错监听
  25 + mPlayer.setOnErrorListener(new OnErrorListener() {
  26 +
  27 + @Override
  28 + public boolean onError(MediaPlayer mp, int what, int extra) {
  29 + // TODO Auto-generated method stub
  30 + mPlayer.reset();
  31 + return false;
  32 + }
  33 + });
  34 + }else {
  35 + mPlayer.reset();//就恢复
  36 + }
  37 +
  38 + try {
  39 + mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  40 + mPlayer.setOnCompletionListener(onCompletionListener);
  41 + mPlayer.setDataSource(filePathString);
  42 + mPlayer.prepare();
  43 + mPlayer.start();
  44 + } catch (IllegalArgumentException e) {
  45 + // TODO Auto-generated catch block
  46 + e.printStackTrace();
  47 + } catch (SecurityException e) {
  48 + // TODO Auto-generated catch block
  49 + e.printStackTrace();
  50 + } catch (IllegalStateException e) {
  51 + // TODO Auto-generated catch block
  52 + e.printStackTrace();
  53 + } catch (IOException e) {
  54 + // TODO Auto-generated catch block
  55 + e.printStackTrace();
  56 + }
  57 + }
  58 +
  59 + //停止函数
  60 + public static void pause(){
  61 + if (mPlayer!=null&&mPlayer.isPlaying()) {
  62 + mPlayer.pause();
  63 + isPause=true;
  64 + }
  65 + }
  66 +
  67 + //继续
  68 + public static void resume()
  69 + {
  70 + if (mPlayer!=null&&isPause) {
  71 + mPlayer.start();
  72 + isPause=false;
  73 + }
  74 + }
  75 +
  76 +
  77 + public static void release()
  78 + {
  79 + if (mPlayer!=null) {
  80 + mPlayer.release();
  81 + mPlayer=null;
  82 + }
  83 + }
  84 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/pulltorefresh/PullToRefreshLayout.java 0 → 100644
... ... @@ -0,0 +1,250 @@
  1 +package com.shunzhi.mychartlibrary.widget.pulltorefresh;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.graphics.Color;
  6 +import android.support.v4.view.ViewCompat;
  7 +import android.support.v4.widget.ViewDragHelper;
  8 +import android.util.AttributeSet;
  9 +import android.view.Gravity;
  10 +import android.view.MotionEvent;
  11 +import android.view.View;
  12 +import android.view.ViewGroup;
  13 +import android.widget.LinearLayout;
  14 +import android.widget.TextView;
  15 +
  16 +import com.shunzhi.mychartlibrary.utils.ScreenUtil;
  17 +
  18 +
  19 +/**
  20 + * Created by Mao Jiqing on 2016/9/27.
  21 + */
  22 +public class PullToRefreshLayout extends LinearLayout {
  23 + private ViewDragHelper VDH;
  24 + private View myList;
  25 + private TextView pullText;
  26 + private pulltorefreshNotifier pullNotifier;
  27 + private boolean isPull = true;
  28 +
  29 + public PullToRefreshLayout(Context context, AttributeSet attrs) {
  30 + super(context, attrs);
  31 + // TODO Auto-generated constructor stub
  32 +// init();
  33 + VDH = ViewDragHelper.create(this, 10.0f, new DragHelperCallback());
  34 + }
  35 +
  36 + public void setSlideView(View view) {
  37 + init(view);
  38 + }
  39 +
  40 + private void init(View view) {
  41 + LayoutParams lp1 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
  42 + ViewGroup.LayoutParams.MATCH_PARENT);
  43 + myList = view;
  44 + myList.setBackgroundColor(Color.parseColor("#FFFFFF"));
  45 + myList.setLayoutParams(lp1);
  46 + LayoutParams lp2 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ScreenUtil.dip2px(getContext(), 100));
  47 + pullText = new TextView(getContext());
  48 + pullText.setText("下拉加载更多");
  49 + pullText.setBackgroundColor(Color.parseColor("#FFFFFF"));
  50 + pullText.setGravity(Gravity.CENTER);
  51 + pullText.setLayoutParams(lp2);
  52 + setOrientation(LinearLayout.VERTICAL);
  53 + addView(pullText);
  54 + addView(myList);
  55 + }
  56 +
  57 + public View returnMylist() {
  58 + return myList;
  59 + }
  60 +
  61 + @Override
  62 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  63 + measureChildren(widthMeasureSpec, heightMeasureSpec);
  64 +
  65 + int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
  66 + int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
  67 + setMeasuredDimension(
  68 + resolveSizeAndState(maxWidth, widthMeasureSpec, 0),
  69 + resolveSizeAndState(maxHeight, heightMeasureSpec, 0));
  70 + }
  71 +
  72 + @Override
  73 + protected void onLayout(boolean changed, int l, int t, int r, int b) {
  74 + if (pullText.getTop() == 0) {
  75 + viewHeight = pullText.getMeasuredHeight();
  76 + pullText.layout(l, 0, r, viewHeight);
  77 + myList.layout(l, 0, r, b);
  78 + pullText.offsetTopAndBottom(-viewHeight);
  79 + } else {
  80 + pullText.layout(l, pullText.getTop(), r, pullText.getBottom());
  81 + myList.layout(l, myList.getTop(), r, myList.getBottom());
  82 + }
  83 + }
  84 +
  85 + /**
  86 + * 这是View的方法,该方法不支持android低版本(2.2、2.3)的操作系统,所以手动复制过来以免强制退出
  87 + */
  88 + public static int resolveSizeAndState(int size, int measureSpec,
  89 + int childMeasuredState) {
  90 + int result = size;
  91 + int specMode = MeasureSpec.getMode(measureSpec);
  92 + int specSize = MeasureSpec.getSize(measureSpec);
  93 + switch (specMode) {
  94 + case MeasureSpec.UNSPECIFIED:
  95 + result = size;
  96 + break;
  97 + case MeasureSpec.AT_MOST:
  98 + if (specSize < size) {
  99 + result = specSize | MEASURED_STATE_TOO_SMALL;
  100 + } else {
  101 + result = size;
  102 + }
  103 + break;
  104 + case MeasureSpec.EXACTLY:
  105 + result = specSize;
  106 + break;
  107 + }
  108 + return result | (childMeasuredState & MEASURED_STATE_MASK);
  109 + }
  110 +
  111 + @Override
  112 + public boolean onInterceptTouchEvent(MotionEvent event) {
  113 + boolean shouldIntercept = VDH.shouldInterceptTouchEvent(event) && isPull;
  114 + return shouldIntercept;
  115 + }
  116 +
  117 + @SuppressLint("ClickableViewAccessibility")
  118 + @Override
  119 + public boolean onTouchEvent(MotionEvent event) {
  120 + VDH.processTouchEvent(event);
  121 + return true;
  122 + }
  123 +
  124 + /**
  125 + * 这是拖拽效果的主要逻辑
  126 + */
  127 + private class DragHelperCallback extends ViewDragHelper.Callback {
  128 +
  129 + @Override
  130 + public void onViewPositionChanged(View changedView, int left, int top,
  131 + int dx, int dy) {
  132 + int childIndex = 1;
  133 + if (changedView == myList) {
  134 + childIndex = 2;
  135 + }
  136 + onViewPosChanged(childIndex, top);
  137 + }
  138 +
  139 + @Override
  140 + public boolean tryCaptureView(View child, int pointerId) {
  141 + return true;
  142 + }
  143 +
  144 + @Override
  145 + public int getViewVerticalDragRange(View child) {
  146 + return 1;
  147 + }
  148 +
  149 + @Override
  150 + public void onViewReleased(View releasedChild, float xvel, float yvel) {
  151 + refreshOrNot(releasedChild, yvel);
  152 + }
  153 +
  154 + @Override
  155 + public int clampViewPositionVertical(View child, int top, int dy) {
  156 + int finalTop = top;
  157 + if (child == pullText) {
  158 + if (top > 0) {
  159 + finalTop = 0;
  160 + }
  161 + } else if (child == myList) {
  162 + if (top < 0) {
  163 + finalTop = 0;
  164 + }
  165 + if (top >= viewHeight) {
  166 + pullText.setText("松开加载");
  167 + } else {
  168 + pullText.setText("下拉加载更多");
  169 + }
  170 + }
  171 + return child.getTop() + (finalTop - child.getTop()) / 2;
  172 + }
  173 + }
  174 +
  175 + /**
  176 + * 滑动时view位置改变协调处理
  177 + *
  178 + * @param viewIndex
  179 + * 滑动view的index(1或2)
  180 + * @param posTop
  181 + * 滑动View的top位置
  182 + */
  183 + private static int viewHeight;
  184 +
  185 + private void onViewPosChanged(int viewIndex, int posTop) {
  186 + if (viewIndex == 1) {
  187 + int offsetTopBottom = viewHeight + pullText.getTop()
  188 + - myList.getTop();
  189 + myList.offsetTopAndBottom(offsetTopBottom);
  190 + } else if (viewIndex == 2) {
  191 + int offsetTopBottom = myList.getTop() - viewHeight
  192 + - pullText.getTop();
  193 + pullText.offsetTopAndBottom(offsetTopBottom);
  194 + }
  195 + invalidate();
  196 + }
  197 +
  198 + private void refreshOrNot(View releasedChild, float yvel) {
  199 + int finalTop = 0;
  200 + if (releasedChild == pullText) {
  201 + // 拖动第一个view松手
  202 + if (yvel < -50) {
  203 + finalTop = 0;
  204 + } else {
  205 + finalTop = viewHeight;
  206 + }
  207 + } else {
  208 + // 拖动第二个view松手
  209 + if (yvel > viewHeight - 5 || releasedChild.getTop() >= viewHeight) {
  210 + finalTop = viewHeight;
  211 + if (null != pullNotifier) {
  212 + pullNotifier.onPull();
  213 + }
  214 + pullText.setText("正在加载");
  215 + }
  216 + }
  217 +
  218 + if (VDH.smoothSlideViewTo(myList, 0, finalTop)) {
  219 + ViewCompat.postInvalidateOnAnimation(this);
  220 + }
  221 + }
  222 +
  223 + public void refreshComplete() {
  224 + if (VDH.smoothSlideViewTo(myList, 0, 0)) {
  225 + ViewCompat.postInvalidateOnAnimation(this);
  226 + }
  227 + }
  228 +
  229 + @Override
  230 + public void computeScroll() {
  231 + if (VDH.continueSettling(true)) {
  232 + ViewCompat.postInvalidateOnAnimation(this);
  233 + }
  234 + }
  235 +
  236 + public void setpulltorefreshNotifier(pulltorefreshNotifier pullNotifier) {
  237 + this.pullNotifier = pullNotifier;
  238 + }
  239 +
  240 + public interface pulltorefreshNotifier {
  241 + public void onPull();
  242 + }
  243 +
  244 + /**
  245 + * 禁止下拉
  246 + */
  247 + public void setPullGone() {
  248 + isPull = false;
  249 + }
  250 +}
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/pulltorefresh/PullToRefreshListView.java 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +package com.shunzhi.mychartlibrary.widget.pulltorefresh;
  2 +
  3 +import android.content.Context;
  4 +import android.util.AttributeSet;
  5 +import android.view.MotionEvent;
  6 +import android.view.View;
  7 +import android.widget.ListView;
  8 +
  9 +/**
  10 + * Created by Mao Jiqing on 2016/10/10.
  11 + */
  12 +public class PullToRefreshListView extends ListView {
  13 + boolean allowDragBottom = true;
  14 + float downY = 0;
  15 + boolean needConsumeTouch = true;
  16 +
  17 + public PullToRefreshListView(Context context) {
  18 + super(context);
  19 + setDivider(null);
  20 + }
  21 +
  22 + public PullToRefreshListView(Context context, AttributeSet attrs) {
  23 + super(context, attrs);
  24 + // TODO Auto-generated constructor stub
  25 + }
  26 +
  27 + @Override
  28 + public boolean dispatchTouchEvent(MotionEvent ev) {
  29 + if (ev.getAction() == MotionEvent.ACTION_DOWN) {
  30 + downY = ev.getRawY();
  31 + needConsumeTouch = true;
  32 + if (getMyScrollY() == 0) {
  33 + allowDragBottom = true;
  34 + } else {
  35 + allowDragBottom = false;
  36 + }
  37 + } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
  38 + if (!needConsumeTouch) {
  39 + getParent().requestDisallowInterceptTouchEvent(false);
  40 + return false;
  41 + } else if (allowDragBottom) {
  42 + if (downY - ev.getRawY() < -2) {
  43 + needConsumeTouch = false;
  44 + getParent().requestDisallowInterceptTouchEvent(false);
  45 + return false;
  46 + }
  47 + }
  48 + }
  49 + getParent().requestDisallowInterceptTouchEvent(needConsumeTouch);
  50 + return super.dispatchTouchEvent(ev);
  51 + }
  52 +
  53 + public int getMyScrollY() {
  54 + View c = getChildAt(0);
  55 + if (c == null) {
  56 + return 0;
  57 + }
  58 + int firstVisiblePosition = getFirstVisiblePosition();
  59 + int top = c.getTop();
  60 + return -top + firstVisiblePosition * c.getHeight();
  61 + }
  62 +
  63 +}
0 64 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/pulltorefresh/PullToRefreshRecyclerView.java 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +package com.shunzhi.mychartlibrary.widget.pulltorefresh;
  2 +
  3 +import android.content.Context;
  4 +import android.support.v7.widget.LinearLayoutManager;
  5 +import android.support.v7.widget.RecyclerView;
  6 +import android.util.AttributeSet;
  7 +import android.view.MotionEvent;
  8 +import android.view.View;
  9 +
  10 +/**
  11 + * Created by Mao Jiqing on 2016/9/27.
  12 + */
  13 +public class PullToRefreshRecyclerView extends RecyclerView {
  14 + boolean allowDragBottom = true;
  15 + float downY = 0;
  16 + boolean needConsumeTouch = true;
  17 +
  18 + public PullToRefreshRecyclerView(Context context) {
  19 + super(context);
  20 + }
  21 +
  22 + public PullToRefreshRecyclerView(Context context, AttributeSet attrs) {
  23 + super(context, attrs);
  24 + // TODO Auto-generated constructor stub
  25 + }
  26 +
  27 + @Override
  28 + public boolean dispatchTouchEvent(MotionEvent ev) {
  29 + if (ev.getAction() == MotionEvent.ACTION_DOWN) {
  30 + downY = ev.getRawY();
  31 + needConsumeTouch = true;
  32 + if (getMyScrollY() == 0) {
  33 + allowDragBottom = true;
  34 + } else {
  35 + allowDragBottom = false;
  36 + }
  37 + } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
  38 + if (!needConsumeTouch) {
  39 + getParent().requestDisallowInterceptTouchEvent(false);
  40 + return false;
  41 + } else if (allowDragBottom) {
  42 + if (downY - ev.getRawY() < -2) {
  43 + needConsumeTouch = false;
  44 + getParent().requestDisallowInterceptTouchEvent(false);
  45 + return false;
  46 + }
  47 + }
  48 + }
  49 + getParent().requestDisallowInterceptTouchEvent(needConsumeTouch);
  50 + return super.dispatchTouchEvent(ev);
  51 + }
  52 +
  53 + public int getMyScrollY() {
  54 + View c = getChildAt(0);
  55 + if (c == null) {
  56 + return 0;
  57 + }
  58 + int firstVisiblePosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
  59 + int top = c.getTop();
  60 + return -top + firstVisiblePosition * c.getHeight();
  61 + }
  62 +
  63 +}
0 64 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/pulltorefresh/WrapContentLinearLayoutManager.java 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +package com.shunzhi.mychartlibrary.widget.pulltorefresh;
  2 +
  3 +import android.content.Context;
  4 +import android.support.v7.widget.LinearLayoutManager;
  5 +import android.support.v7.widget.RecyclerView;
  6 +import android.util.Log;
  7 +import android.view.View;
  8 +import android.view.ViewGroup;
  9 +
  10 +/**
  11 + * Created by Mao Jiqing on 2016/9/30.
  12 + */
  13 +public class WrapContentLinearLayoutManager extends LinearLayoutManager {
  14 + private int[] mMeasuredDimension = new int[2];
  15 + private int recyclerHeight = 0;
  16 + private RecyclerView.Recycler recycler;
  17 +
  18 + public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
  19 + super(context, orientation, reverseLayout);
  20 + }
  21 +
  22 + //... constructor
  23 + @Override
  24 + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
  25 + try {
  26 + this.recycler = recycler;
  27 + super.onLayoutChildren(recycler, state);
  28 + } catch (IndexOutOfBoundsException e) {
  29 + Log.e("probe", "ERROR = " + e.getMessage());
  30 + }
  31 + }
  32 +
  33 + public int getRecyclerHeight() {
  34 + if (recycler == null) {
  35 + return 0;
  36 + }
  37 + int height = 0;
  38 + for (int i = 0; i < getItemCount(); i++) {
  39 + measureScrapChild(recycler, i,
  40 + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
  41 + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
  42 + mMeasuredDimension);
  43 +
  44 + if (getOrientation() == HORIZONTAL) {
  45 + if (i == 0) {
  46 + height = mMeasuredDimension[1];
  47 + }
  48 + } else {
  49 + height = height + mMeasuredDimension[1];
  50 + }
  51 + }
  52 + recyclerHeight = height;
  53 + return recyclerHeight;
  54 + }
  55 +
  56 + private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
  57 + int heightSpec, int[] measuredDimension) {
  58 + try {
  59 + View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException
  60 +
  61 + if (view != null) {
  62 + RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
  63 +
  64 + int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
  65 + getPaddingLeft() + getPaddingRight(), p.width);
  66 +
  67 + int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
  68 + getPaddingTop() + getPaddingBottom(), p.height);
  69 +
  70 + view.measure(childWidthSpec, childHeightSpec);
  71 + measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
  72 + measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
  73 + recycler.recycleView(view);
  74 + }
  75 + } catch (Exception e) {
  76 + e.printStackTrace();
  77 + } finally {
  78 + }
  79 + }
  80 +}
0 81 \ No newline at end of file
... ...
mychartlibrary/src/main/java/com/shunzhi/mychartlibrary/widget/pulltorefresh/base/PullToRefreshView.java 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +package com.shunzhi.mychartlibrary.widget.pulltorefresh.base;
  2 +
  3 +import android.content.Context;
  4 +import android.view.View;
  5 +
  6 +import com.shunzhi.mychartlibrary.widget.pulltorefresh.PullToRefreshListView;
  7 +import com.shunzhi.mychartlibrary.widget.pulltorefresh.PullToRefreshRecyclerView;
  8 +
  9 +
  10 +/**
  11 + * Created by Mao Jiqing on 2016/10/10.
  12 + */
  13 +public class PullToRefreshView extends View {
  14 +
  15 + public static final int LISTVIEW = 0;
  16 + public static final int RECYCLERVIEW = 1;
  17 +
  18 + public PullToRefreshView(Context context) {
  19 + super(context);
  20 + }
  21 +
  22 + public View getSlideView(int slideViewType) {
  23 + View baseView = null;
  24 + switch (slideViewType) {
  25 + case LISTVIEW:
  26 + baseView = new PullToRefreshListView(getContext());
  27 + break;
  28 + case RECYCLERVIEW:
  29 + baseView = new PullToRefreshRecyclerView(getContext());
  30 + break;
  31 + default:
  32 + baseView = null;
  33 + break;
  34 + }
  35 + return baseView;
  36 + }
  37 +}
... ...
mychartlibrary/src/main/res/drawable/btn_back_dark_24dp.xml 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<vector xmlns:tools="http://schemas.android.com/tools"
  3 + xmlns:android="http://schemas.android.com/apk/res/android"
  4 + android:width="24dp"
  5 + android:height="24dp"
  6 + android:viewportWidth="24.0"
  7 + android:viewportHeight="24.0">
  8 + <path
  9 + android:fillColor="#fff"
  10 + android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
  11 +</vector>
0 12 \ No newline at end of file
... ...
mychartlibrary/src/main/res/drawable/button_recording.xml 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android" >
  3 +
  4 + <solid android:color="#eeeeee" /> <!-- 背景色solid -->
  5 + <stroke
  6 + android:width="1px"
  7 + android:color="#9b9b9b" /> <!-- 边框设置 -->
  8 + <corners android:radius="3dp" /> <!-- 转角 -->
  9 +
  10 +</shape>
0 11 \ No newline at end of file
... ...
mychartlibrary/src/main/res/drawable/button_recordnormal.xml 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android" >
  3 +
  4 + <solid android:color="#ffffff" /> <!-- 背景色solid -->
  5 + <stroke
  6 + android:width="1px"
  7 + android:color="#9b9b9b" /> <!-- 边框设置 -->
  8 + <corners android:radius="3dp" /> <!-- 转角 -->
  9 +
  10 +</shape>
0 11 \ No newline at end of file
... ...
mychartlibrary/src/main/res/drawable/click_bg.xml 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<selector xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:state_pressed="true"><shape>
  5 + <solid android:color="@color/click_bg" />
  6 + </shape></item>
  7 + <item android:state_focused="true"><shape>
  8 + <solid android:color="@color/click_bg" />
  9 + </shape></item>
  10 + <item android:state_enabled="true"><shape>
  11 + <solid android:color="@color/white" />
  12 + </shape></item>
  13 + <item><shape>
  14 + <solid android:color="@color/white" />
  15 + </shape></item>
  16 +
  17 +</selector>
0 18 \ No newline at end of file
... ...
mychartlibrary/src/main/res/drawable/item_divider_line.xml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<shape xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:shape="rectangle" >
  4 +
  5 + <solid android:color="@color/zz_divider"/>
  6 +
  7 + <size android:height="1dp" />
  8 +
  9 +</shape>
0 10 \ No newline at end of file
... ...
mychartlibrary/src/main/res/layout/activity_chat.xml 0 → 100644
... ... @@ -0,0 +1,156 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:id="@+id/layout_tongbao_rl"
  4 + android:layout_width="match_parent"
  5 + android:layout_height="match_parent"
  6 + android:background="@android:color/white">
  7 +
  8 + <com.shunzhi.mychartlibrary.widget.pulltorefresh.PullToRefreshLayout
  9 + android:id="@+id/content_lv"
  10 + android:layout_width="match_parent"
  11 + android:layout_height="match_parent"
  12 + android:layout_above="@+id/bottom_container_ll"
  13 + android:listSelector="@android:color/transparent"
  14 + android:orientation="vertical" />
  15 +
  16 + <LinearLayout
  17 + android:id="@+id/bottom_container_ll"
  18 + android:layout_width="match_parent"
  19 + android:layout_height="wrap_content"
  20 + android:layout_alignParentBottom="true"
  21 + android:orientation="vertical">
  22 +
  23 + <LinearLayout
  24 + android:id="@+id/tongbao_utils"
  25 + android:layout_width="match_parent"
  26 + android:layout_height="wrap_content"
  27 + android:background="@drawable/frame_bg"
  28 + android:orientation="horizontal"
  29 + android:paddingBottom="5dp"
  30 + android:paddingLeft="10dp"
  31 + android:paddingRight="10dp"
  32 + android:paddingTop="5dp">
  33 +
  34 + <EditText
  35 + android:id="@+id/mess_et"
  36 + android:layout_width="0dp"
  37 + android:layout_height="wrap_content"
  38 + android:layout_gravity="center_vertical"
  39 + android:layout_weight="1"
  40 + android:background="@drawable/xmxq_tc_bj"
  41 + android:imeOptions="actionSend"
  42 + android:inputType="text"
  43 + android:padding="5dp"
  44 + android:textSize="16sp" />
  45 +
  46 + <ImageView
  47 + android:id="@+id/voice_iv"
  48 + android:layout_width="wrap_content"
  49 + android:layout_height="wrap_content"
  50 + android:layout_gravity="center_vertical"
  51 + android:layout_marginLeft="5dp"
  52 + android:layout_marginRight="5dp"
  53 + android:visibility="gone"
  54 + android:background="@mipmap/voice_btn_normal"
  55 + android:padding="4dp" />
  56 +
  57 + <com.shunzhi.mychartlibrary.widget.AudioRecordButton
  58 + android:id="@+id/voice_btn"
  59 + android:layout_width="0dp"
  60 + android:layout_height="wrap_content"
  61 + android:layout_gravity="center_vertical"
  62 + android:layout_margin="5dp"
  63 + android:layout_weight="1"
  64 + android:background="@drawable/button_recordnormal"
  65 + android:gravity="center"
  66 + android:minHeight="0dp"
  67 + android:padding="5dp"
  68 + android:text="@string/normal"
  69 + android:textColor="#727272"
  70 + android:visibility="gone"></com.shunzhi.mychartlibrary.widget.AudioRecordButton>
  71 +
  72 + <ImageView
  73 + android:id="@+id/emoji"
  74 + android:visibility="gone"
  75 + android:layout_width="wrap_content"
  76 + android:layout_height="wrap_content"
  77 + android:layout_gravity="center_vertical"
  78 + android:layout_marginLeft="5dp"
  79 + android:background="@mipmap/emoji"
  80 + android:padding="4dp" />
  81 +
  82 + <ImageView
  83 + android:id="@+id/mess_iv"
  84 + android:layout_width="wrap_content"
  85 + android:layout_height="wrap_content"
  86 + android:layout_gravity="center_vertical"
  87 + android:layout_marginLeft="5dp"
  88 + android:visibility="gone"
  89 + android:background="@mipmap/tb_more"
  90 + android:padding="4dp" />
  91 + </LinearLayout>
  92 +
  93 + <LinearLayout
  94 + android:id="@+id/emoji_group"
  95 + android:layout_width="match_parent"
  96 + android:layout_height="wrap_content"
  97 + android:background="@color/white"
  98 + android:orientation="vertical"
  99 + android:visibility="gone">
  100 +
  101 + <android.support.v4.view.ViewPager
  102 + android:id="@+id/vPager"
  103 + android:layout_width="match_parent"
  104 + android:layout_height="150dp"
  105 + android:layout_marginTop="3dp"
  106 + android:background="@color/light_gray_2" />
  107 +
  108 + <RelativeLayout
  109 + android:layout_width="match_parent"
  110 + android:layout_height="wrap_content">
  111 +
  112 + <ImageView
  113 + android:layout_width="wrap_content"
  114 + android:layout_height="wrap_content"
  115 + android:layout_alignParentLeft="true"
  116 + android:background="@color/light_gray_2"
  117 + android:paddingBottom="5dp"
  118 + android:paddingLeft="5dp"
  119 + android:paddingRight="5dp"
  120 + android:paddingTop="5dp"
  121 + android:src="@mipmap/emoji_icon" />
  122 +
  123 + <TextView
  124 + android:id="@+id/send_emoji_icon"
  125 + android:layout_width="wrap_content"
  126 + android:layout_height="wrap_content"
  127 + android:layout_alignParentRight="true"
  128 + android:background="@drawable/frame_blue_to_thin_bg"
  129 + android:paddingBottom="5dp"
  130 + android:paddingLeft="10dp"
  131 + android:paddingRight="10dp"
  132 + android:paddingTop="5dp"
  133 + android:text="发送"
  134 + android:textColor="@color/white"
  135 + android:textSize="16sp" />
  136 + </RelativeLayout>
  137 + </LinearLayout>
  138 +
  139 + <FrameLayout
  140 + android:layout_width="match_parent"
  141 + android:layout_height="wrap_content">
  142 +
  143 + <com.shunzhi.mychartlibrary.widget.ChatBottomView
  144 + android:id="@+id/other_lv"
  145 + android:layout_width="match_parent"
  146 + android:layout_height="200dp"
  147 + android:visibility="gone" />
  148 +
  149 + <ListView
  150 + android:id="@+id/mess_lv"
  151 + android:layout_width="match_parent"
  152 + android:layout_height="wrap_content"
  153 + android:visibility="gone" />
  154 + </FrameLayout>
  155 + </LinearLayout>
  156 +</RelativeLayout>
0 157 \ No newline at end of file
... ...
mychartlibrary/src/main/res/layout/layout_action_bar.xml 0 → 100644
... ... @@ -0,0 +1,61 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:background="@color/titleColor"
  6 + >
  7 +
  8 + <ImageView
  9 + android:id="@+id/ivLeft"
  10 + android:layout_width="wrap_content"
  11 + android:layout_height="match_parent"
  12 + android:layout_alignParentLeft="true"
  13 + android:layout_centerVertical="true"
  14 + android:focusable="true"
  15 + android:paddingLeft="10dp"
  16 + android:paddingRight="20dp"
  17 + android:src="@drawable/btn_back_dark_24dp" />
  18 +
  19 + <TextView
  20 + android:id="@+id/tvTitle"
  21 + android:layout_width="wrap_content"
  22 + android:layout_height="wrap_content"
  23 + android:layout_centerInParent="true"
  24 + android:text="@string/app_name"
  25 + android:textColor="@color/white"
  26 + android:textSize="16sp"
  27 + android:textStyle="bold" />
  28 +
  29 + <LinearLayout
  30 + android:id="@+id/llRight"
  31 + android:layout_width="wrap_content"
  32 + android:layout_height="match_parent"
  33 + android:layout_alignParentRight="true"
  34 + android:focusable="true"
  35 + android:gravity="center_vertical"
  36 + android:orientation="horizontal"
  37 + android:paddingLeft="20dp"
  38 + android:paddingRight="10dp"
  39 + android:visibility="gone">
  40 +
  41 + <TextView
  42 + android:id="@+id/tvRight"
  43 + android:layout_width="wrap_content"
  44 + android:layout_height="match_parent"
  45 + android:layout_gravity="center_vertical"
  46 + android:gravity="center_vertical"
  47 + android:textColor="@color/white"
  48 + android:textSize="16sp"
  49 + android:textStyle="bold"
  50 + android:visibility="gone" />
  51 +
  52 + <ImageView
  53 + android:id="@+id/ivRight"
  54 + android:layout_width="wrap_content"
  55 + android:layout_height="match_parent"
  56 + android:layout_gravity="center_vertical"
  57 + android:gravity="center_vertical"
  58 + android:visibility="gone" />
  59 + </LinearLayout>
  60 +
  61 +</RelativeLayout>
0 62 \ No newline at end of file
... ...
mychartlibrary/src/main/res/layout/layout_expression_gridview.xml 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical" >
  6 +
  7 + <com.shunzhi.mychartlibrary.widget.ExpandGridView
  8 + android:id="@+id/gridview"
  9 + android:layout_width="match_parent"
  10 + android:layout_height="match_parent"
  11 + android:numColumns="7"
  12 + android:scrollbars="none"
  13 + android:verticalSpacing="5dp"
  14 + android:gravity="center"
  15 + android:layout_gravity="center"
  16 + android:layout_marginTop="6dp"
  17 + android:layout_marginBottom="6dp"
  18 + android:fadingEdge="none"
  19 + />
  20 +
  21 +</LinearLayout>
... ...
mychartlibrary/src/main/res/layout/layout_mess_iv_listitem.xml 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="wrap_content"
  5 + android:orientation="vertical" >
  6 +
  7 + <TextView
  8 + android:id="@+id/title"
  9 + android:layout_width="match_parent"
  10 + android:layout_height="wrap_content"
  11 + android:layout_gravity="center_vertical"
  12 + android:gravity="left"
  13 + android:paddingBottom="5dp"
  14 + android:paddingLeft="10dp"
  15 + android:paddingTop="5dp"
  16 + android:textColor="@color/black" />
  17 +
  18 + <View
  19 + android:layout_width="match_parent"
  20 + android:layout_height="1dp"
  21 + android:layout_marginTop="5dp"
  22 + android:background="@drawable/item_divider_line" />
  23 +
  24 +</LinearLayout>
0 25 \ No newline at end of file
... ...
mychartlibrary/src/main/res/layout/layout_row_expression.xml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:id="@+id/iv_expression"
  4 + android:layout_width="wrap_content"
  5 + android:layout_height="wrap_content"
  6 + android:padding="8dp"
  7 + android:scaleType="centerInside">
  8 +
  9 +</ImageView>
... ...
mychartlibrary/src/main/res/layout/layout_tongbaobottom.xml 0 → 100644
... ... @@ -0,0 +1,70 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:padding="10dp"
  6 + android:orientation="horizontal" >
  7 + <LinearLayout
  8 + android:id="@+id/image_bottom_group"
  9 + android:layout_width="0dp"
  10 + android:layout_height="wrap_content"
  11 + android:layout_gravity="center_horizontal"
  12 + android:layout_weight="1"
  13 + android:orientation="vertical" >
  14 +
  15 + <ImageView
  16 + android:layout_width="wrap_content"
  17 + android:layout_height="wrap_content"
  18 + android:layout_gravity="center_horizontal"
  19 + android:background="@mipmap/tb_bottom_images" />
  20 +
  21 + <TextView
  22 + android:layout_width="wrap_content"
  23 + android:layout_height="wrap_content"
  24 + android:layout_gravity="center_horizontal"
  25 + android:text="图像" />
  26 + </LinearLayout>
  27 +
  28 + <LinearLayout
  29 + android:id="@+id/camera_group"
  30 + android:layout_width="0dp"
  31 + android:layout_height="wrap_content"
  32 + android:layout_gravity="center_horizontal"
  33 + android:layout_weight="1"
  34 + android:orientation="vertical" >
  35 +
  36 + <ImageView
  37 + android:layout_width="wrap_content"
  38 + android:layout_height="wrap_content"
  39 + android:layout_gravity="center_horizontal"
  40 + android:background="@mipmap/tb_bottom_take_photo" />
  41 +
  42 + <TextView
  43 + android:layout_width="wrap_content"
  44 + android:layout_height="wrap_content"
  45 + android:layout_gravity="center_horizontal"
  46 + android:text="照相" />
  47 + </LinearLayout>
  48 +
  49 + <LinearLayout
  50 + android:id="@+id/phrase_group"
  51 + android:layout_width="0dp"
  52 + android:layout_height="wrap_content"
  53 + android:layout_gravity="center_horizontal"
  54 + android:layout_weight="1"
  55 + android:orientation="vertical" >
  56 +
  57 + <ImageView
  58 + android:layout_width="wrap_content"
  59 + android:layout_height="wrap_content"
  60 + android:layout_gravity="center_horizontal"
  61 + android:background="@mipmap/tb_bottom_offen" />
  62 +
  63 + <TextView
  64 + android:layout_width="wrap_content"
  65 + android:layout_height="wrap_content"
  66 + android:layout_gravity="center_horizontal"
  67 + android:text="常用语" />
  68 + </LinearLayout>
  69 +
  70 +</LinearLayout>
0 71 \ No newline at end of file
... ...
mychartlibrary/src/main/res/layout/layout_view_headicon.xml 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:id="@+id/head_icon_main_rl"
  4 + android:layout_width="match_parent"
  5 + android:layout_height="match_parent"
  6 + android:background="@color/zz_half_transparent" >
  7 +
  8 + <LinearLayout
  9 + android:id="@+id/head_icon_main_ll"
  10 + android:layout_width="match_parent"
  11 + android:layout_height="wrap_content"
  12 + android:layout_alignParentBottom="true"
  13 + android:layout_alignParentLeft="true"
  14 + android:background="@color/light_gray_2"
  15 + android:orientation="vertical" >
  16 +
  17 + <LinearLayout
  18 + android:id="@+id/head_icon_camera_ll"
  19 + android:layout_width="match_parent"
  20 + android:layout_height="wrap_content"
  21 + android:background="@drawable/click_bg"
  22 + android:gravity="center" >
  23 +
  24 + <TextView
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_margin="10dp"
  28 + android:text="拍照"
  29 + android:textColor="@color/dark_gray_1" />
  30 + </LinearLayout>
  31 +
  32 + <View
  33 + android:layout_width="match_parent"
  34 + android:layout_height="1dp"
  35 + android:background="@drawable/item_divider_line" />
  36 +
  37 + <LinearLayout
  38 + android:id="@+id/head_icon_gallery_ll"
  39 + android:layout_width="match_parent"
  40 + android:layout_height="wrap_content"
  41 + android:background="@drawable/click_bg"
  42 + android:gravity="center" >
  43 +
  44 + <TextView
  45 + android:layout_width="wrap_content"
  46 + android:layout_height="wrap_content"
  47 + android:layout_margin="10dp"
  48 + android:text="从相册选择"
  49 + android:textColor="@color/dark_gray_1" />
  50 + </LinearLayout>
  51 +
  52 + <View
  53 + android:layout_width="match_parent"
  54 + android:layout_height="1dp"
  55 + android:background="@drawable/item_divider_line" />
  56 +
  57 + <View
  58 + android:layout_width="match_parent"
  59 + android:layout_height="1dp"
  60 + android:layout_marginTop="10dp"
  61 + android:background="@drawable/item_divider_line" />
  62 +
  63 + <LinearLayout
  64 + android:id="@+id/head_icon_cancel_ll"
  65 + android:layout_width="match_parent"
  66 + android:layout_height="wrap_content"
  67 + android:background="@drawable/click_bg"
  68 + android:gravity="center" >
  69 +
  70 + <TextView
  71 + android:id="@+id/cancle"
  72 + android:layout_width="wrap_content"
  73 + android:layout_height="wrap_content"
  74 + android:layout_margin="10dp"
  75 + android:text="取消"
  76 + android:textColor="@color/dark_gray_1" />
  77 + </LinearLayout>
  78 + </LinearLayout>
  79 +
  80 +</RelativeLayout>
0 81 \ No newline at end of file
... ...
mychartlibrary/src/main/res/layout/layout_voice_dialog_manager.xml 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:tools="http://schemas.android.com/tools"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="wrap_content"
  5 + android:gravity="center"
  6 + android:orientation="vertical" >
  7 +
  8 + <LinearLayout
  9 + android:layout_width="wrap_content"
  10 + android:layout_height="wrap_content"
  11 + android:orientation="horizontal" >
  12 +
  13 + <ImageView
  14 + android:id="@+id/dialog_icon"
  15 + android:layout_width="wrap_content"
  16 + android:layout_height="wrap_content"
  17 + android:src="@mipmap/cancel"
  18 + android:visibility="gone" />
  19 +
  20 + <ImageView
  21 + android:id="@+id/dialog_voice"
  22 + android:layout_width="wrap_content"
  23 + android:layout_height="wrap_content"
  24 + android:src="@mipmap/tb_voice1"
  25 + android:visibility="visible" />
  26 + </LinearLayout>
  27 +
  28 + <TextView
  29 + android:id="@+id/recorder_dialogtext"
  30 + android:layout_width="wrap_content"
  31 + android:layout_height="wrap_content"
  32 + android:layout_marginTop="5dp"
  33 + android:text="@string/shouzhishanghua"
  34 + android:textColor="#ffffffff" />
  35 +
  36 +</LinearLayout>
0 37 \ No newline at end of file
... ...
mychartlibrary/src/main/res/mipmap-hdpi/f1.gif 0 → 100644

4.06 KB

mychartlibrary/src/main/res/mipmap-hdpi/f10.gif 0 → 100644

3.79 KB

mychartlibrary/src/main/res/mipmap-hdpi/f11.gif 0 → 100644

7.89 KB

mychartlibrary/src/main/res/mipmap-hdpi/f12.gif 0 → 100644

2.24 KB

mychartlibrary/src/main/res/mipmap-hdpi/f13.gif 0 → 100644

1.74 KB

mychartlibrary/src/main/res/mipmap-hdpi/f14.gif 0 → 100644

1.81 KB

mychartlibrary/src/main/res/mipmap-hdpi/f15.gif 0 → 100644

1.57 KB

mychartlibrary/src/main/res/mipmap-hdpi/f16.gif 0 → 100644

1.42 KB

mychartlibrary/src/main/res/mipmap-hdpi/f17.gif 0 → 100644

7.99 KB

mychartlibrary/src/main/res/mipmap-hdpi/f18.gif 0 → 100644

7.99 KB

mychartlibrary/src/main/res/mipmap-hdpi/f19.gif 0 → 100644

1.81 KB

mychartlibrary/src/main/res/mipmap-hdpi/f2.gif 0 → 100644

1.59 KB

mychartlibrary/src/main/res/mipmap-hdpi/f20.gif 0 → 100644

1.87 KB

mychartlibrary/src/main/res/mipmap-hdpi/f21.gif 0 → 100644

3.02 KB

mychartlibrary/src/main/res/mipmap-hdpi/f22.gif 0 → 100644

1.95 KB

mychartlibrary/src/main/res/mipmap-hdpi/f23.gif 0 → 100644

2.25 KB

mychartlibrary/src/main/res/mipmap-hdpi/f24.gif 0 → 100644

2.43 KB

mychartlibrary/src/main/res/mipmap-hdpi/f25.gif 0 → 100644

3.96 KB

mychartlibrary/src/main/res/mipmap-hdpi/f26.gif 0 → 100644

2.64 KB

mychartlibrary/src/main/res/mipmap-hdpi/f27.gif 0 → 100644

3.34 KB

mychartlibrary/src/main/res/mipmap-hdpi/f28.gif 0 → 100644

4.84 KB

mychartlibrary/src/main/res/mipmap-hdpi/f29.gif 0 → 100644

1.78 KB

mychartlibrary/src/main/res/mipmap-hdpi/f3.gif 0 → 100644

1.81 KB

mychartlibrary/src/main/res/mipmap-hdpi/f30.gif 0 → 100644

7.24 KB

mychartlibrary/src/main/res/mipmap-hdpi/f31.gif 0 → 100644

4.39 KB

mychartlibrary/src/main/res/mipmap-hdpi/f32.gif 0 → 100644

2.13 KB

mychartlibrary/src/main/res/mipmap-hdpi/f33.gif 0 → 100644

1.43 KB

mychartlibrary/src/main/res/mipmap-hdpi/f34.gif 0 → 100644

1.21 KB

mychartlibrary/src/main/res/mipmap-hdpi/f35.gif 0 → 100644

1.68 KB

mychartlibrary/src/main/res/mipmap-hdpi/f36.gif 0 → 100644

1.8 KB

mychartlibrary/src/main/res/mipmap-hdpi/f37.gif 0 → 100644

1.14 KB

mychartlibrary/src/main/res/mipmap-hdpi/f38.gif 0 → 100644

2.54 KB

mychartlibrary/src/main/res/mipmap-hdpi/f39.gif 0 → 100644

1.39 KB

mychartlibrary/src/main/res/mipmap-hdpi/f4.gif 0 → 100644

1.85 KB

mychartlibrary/src/main/res/mipmap-hdpi/f40.gif 0 → 100644

1.28 KB

mychartlibrary/src/main/res/mipmap-hdpi/f5.gif 0 → 100644

1.98 KB

mychartlibrary/src/main/res/mipmap-hdpi/f6.gif 0 → 100644

3.19 KB

mychartlibrary/src/main/res/mipmap-hdpi/f7.gif 0 → 100644

3.9 KB

mychartlibrary/src/main/res/mipmap-hdpi/f8.gif 0 → 100644

4.92 KB

mychartlibrary/src/main/res/mipmap-hdpi/f9.gif 0 → 100644

3.37 KB

mychartlibrary/src/main/res/mipmap-hdpi/ic_launcher.png 0 → 100644

3.34 KB

mychartlibrary/src/main/res/mipmap-hdpi/ic_launcher_round.png 0 → 100644

4.91 KB

mychartlibrary/src/main/res/mipmap-hdpi/msg_state_fail_resend_pressed.png 0 → 100644

1.72 KB

mychartlibrary/src/main/res/mipmap-hdpi/xsearch_loading.png 0 → 100644

3.01 KB

mychartlibrary/src/main/res/mipmap-xhdpi/cancel.png 0 → 100644

2.87 KB

mychartlibrary/src/main/res/mipmap-xhdpi/chatting_setmode_keyboard_btn_normal.png 0 → 100644

1.18 KB

mychartlibrary/src/main/res/mipmap-xhdpi/emoji.png 0 → 100644

2.45 KB

mychartlibrary/src/main/res/mipmap-xhdpi/tb_bottom_images.png 0 → 100644

2.04 KB

mychartlibrary/src/main/res/mipmap-xhdpi/tb_bottom_offen.png 0 → 100644

2.42 KB

mychartlibrary/src/main/res/mipmap-xhdpi/tb_bottom_take_photo.png 0 → 100644

2.41 KB

mychartlibrary/src/main/res/mipmap-xhdpi/tb_more.png 0 → 100644

1.21 KB

mychartlibrary/src/main/res/mipmap-xhdpi/voice_btn_normal.png 0 → 100644

1.6 KB

mychartlibrary/src/main/res/mipmap-xhdpi/voice_to_short.png 0 → 100644

2.32 KB

mychartlibrary/src/main/res/values/colors.xml 0 → 100644
... ... @@ -0,0 +1,157 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <color name="colorPrimary">#3F51B5</color>
  4 + <color name="colorPrimaryDark">#303F9F</color>
  5 + <color name="colorAccent">#FF4081</color>
  6 + <color name="three_transparent">#30ffffff</color>
  7 + <color name="black">#000000</color>
  8 + <color name="white">#ffffff</color>
  9 + <color name="light_gray_1">#e5e5e5</color>
  10 + <color name="light_gray_2">#f0f2f6</color>
  11 + <color name="light_gray_3">#fafafa</color>
  12 + <color name="light_gray_4">#f5f5f5</color>
  13 + <color name="light_gray_5">#f3f3f3</color>
  14 + <color name="light_gray_6">#aaaaaa</color>
  15 + <color name="light_gray_7">#f0f0f0</color>
  16 + <color name="light_gray_8">#666666</color>
  17 + <color name="light_gray_9">#f4f5f7</color>
  18 + <color name="light_gray_10">#bfbfbf</color>
  19 + <color name="light_gray_11">#f1f2f6</color>
  20 + <color name="light_gray_12">#333333</color>
  21 + <color name="middle_gray_1">#999999</color>
  22 + <color name="middle_gray_2">#818181</color>
  23 + <color name="dark_gray_1">#051b28</color>
  24 + <color name="dark_gray_2">#848689</color>
  25 + <color name="dark_gray_3">#252525</color>
  26 + <color name="dark_gray_4">#232326</color>
  27 + <color name="dark_gray_5">#f2f4f5</color>
  28 +
  29 + <color name="blue2">#0a85ff</color>
  30 + <color name="blue3">#356cb0</color>
  31 + <color name="blue4">#5795f3</color>
  32 + <color name="blue5">#2297fe</color>
  33 +
  34 + <color name="yellow">#edbb74</color>
  35 + <color name="yellow_1">#ffb802</color>
  36 + <color name="yellow_2">#fff5e5</color>
  37 + <color name="yellow_3">#fd9c00</color>
  38 + <color name="red">#ffdd2727</color> <!-- 酱红色 -->
  39 + <color name="red1">#c82300</color> <!-- 深红色 -->
  40 + <color name="red2">#e64a4b</color>
  41 + <color name="red3">#ff4719</color>
  42 + <color name="red4">#f2426c</color>
  43 + <color name="red5">#ff7870</color>
  44 + <color name="red6">#dd2727</color>
  45 + <color name="red7">#ff4258</color>
  46 + <color name="red8">#e72701</color>
  47 +
  48 + <color name="mjq_red">#ff5757</color>
  49 + <color name="mjq_albumback">#E1E0DE</color>
  50 + <color name="mjq_none_color">#00000000</color>
  51 + <color name="click_bg">#d9d9d9</color>
  52 + <color name="edit_frame_bg">#e9eaec</color>
  53 + <color name="light_blue1">#3097e6</color>
  54 + <color name="light_blue2">#503097e6</color>
  55 + <color name="light_blue3">#dcf4ff</color>
  56 + <color name="light_blue4">#84d4f9</color>
  57 + <color name="light_blue5">#45b1e3</color>
  58 + <color name="light_blue6">#3299e8</color>
  59 + <color name="light_blue7">#1597f2</color>
  60 +
  61 + <color name="zhu_light_blue">#346cb0</color>
  62 +
  63 + <color name="zz_light_blue">#278ff3</color>
  64 + <color name="zz_divider">#e6e6e6</color>
  65 + <color name="zz_divider1">#dedede</color>
  66 + <color name="zz_invest_light_gray">#808080</color>
  67 + <color name="zz_half_transparent">#7f000000</color>
  68 + <color name="black_30_transparent">#48000000</color>
  69 + <color name="black_50_transparent">#50000000</color>
  70 + <color name="zz_seven_transparent">#70ffffff</color>
  71 + <color name="zz_light_gray_6">#ebebeb</color>
  72 + <color name="zz_4_11_16">#bbbbbb</color>
  73 + <color name="zz_gray_22">#222222</color>
  74 + <color name="text_color_gray1">#626262</color>
  75 + <color name="lines_view">#cccccc</color>
  76 + <color name="navpage">#FFE1E8EB</color>
  77 + <color name="dark_yellow_1">#ffb84c</color>
  78 + <color name="dark_white_1">#feeedc</color>
  79 + <color name="hint_red_1">#fadcdc</color>
  80 + <color name="black1">#2f2f2f</color>
  81 + <color name="black2">#656565</color>
  82 + <color name="black3">#595959</color>
  83 + <color name="black4">#343434</color>
  84 + <color name="light_blue_1">#4ca4fe</color>
  85 + <color name="light_blue_2">#14ccca</color>
  86 + <color name="light_red_1">#f26464</color>
  87 + <color name="light_blue">#1597f2</color>
  88 +
  89 + <color name="light_gray_13">#dddddd</color>
  90 + <color name="light_gray_14">#838383</color>
  91 + <color name="light_gray_15">#999999</color>
  92 + <color name="light_gray_16">#f2f5f5</color>
  93 + <color name="light_gray_17">#f8f8f8</color>
  94 + <color name="light_gray_18">#c9c7c3</color>
  95 + <color name="light_gray_19">#b2b2b2</color>
  96 + <color name="light_gray_21">#a3a8ad</color>
  97 + <color name="light_gray_20">#d2d2d2</color>
  98 + <color name="light_gray_22">#b3b3b3</color>
  99 + <color name="light_gray_24">#a5a5a5</color>
  100 + <color name="light_gray_23">#929292</color>
  101 + <color name="light_gray_25">#e0e0e0</color>
  102 + <color name="red_dark">#634444</color>
  103 +
  104 + <item name="subscribe_item_text_color_normal" type="color">@color/default_text</item>
  105 +
  106 + <color name="subscribe_item_text_color_pressed">#ffb9b9b9</color>
  107 + <color name="default_text">#ff454545</color>
  108 + <color name="subscribe_item_text_color_pressed_night">#ff303030</color>
  109 + <color name="subscribe_item_focused_stroke">#ffd9d9d9</color>
  110 + <color name="subscribe_item_drag_stroke">#ffd2d2d2</color>
  111 + <color name="subscribe_item_drag_bg">#fff5f5f5</color>
  112 + <color name="subscribe_item_drag_stroke_night">#ff464646</color>
  113 + <color name="subscribe_item_drag_bg_night">#ff252525</color>
  114 + <color name="subscribe_item_selected_bg">#ffffffff</color>
  115 + <color name="subscribe_item_selected_stroke">#ffcc3131</color>
  116 + <color name="subscribe_item_disabled_bg">#ffefefef</color>
  117 + <color name="subscribe_item_disabled_stroke">#ffd9d9d9</color>
  118 + <color name="subscribe_item_pressed_bg">#fff9f9f9</color>
  119 + <color name="subscribe_item_pressed_stroke">#ffcdcdcd</color>
  120 + <color name="subscribe_item_normal_bg">#fff5f5f5</color>
  121 + <color name="subscribe_item_normal_stroke">#ffcdcdcd</color>
  122 + <color name="subscribe_item_focused_bg_night">#ff252525</color>
  123 + <color name="subscribe_item_focused_stroke_night">#ff464646</color>
  124 + <color name="subscribe_item_selected_bg_night">#ff252525</color>
  125 + <color name="subscribe_item_selected_stroke_night">#ffbc494d</color>
  126 + <color name="subscribe_item_disabled_bg_night">#ff2b2b2b</color>
  127 + <color name="project_detail_red">#ffcd2323</color>
  128 + <color name="project_detail_purple">#ff573535</color>
  129 + <color name="transparentWhite">#30ffffff</color>
  130 + <color name="transparentWhit2">#efffffff</color>
  131 + <color name="transparentGray">#e6e0e0e0</color>
  132 +
  133 + <color name="hintTextColor">#494947</color>
  134 + <color name="bottomline">#B8B8B9</color>
  135 + <color name="bg_main">#F0EFF5</color>
  136 +
  137 + <color name="textRed">#FC5B6A</color>
  138 +
  139 + <color name="blue">#2956FE</color>
  140 + <color name="green">#00CB87</color>
  141 + <color name="back_top">#6d9bff</color>
  142 + <color name="textBlue">#ACC9FC</color>
  143 + <color name="titleColor">#6d9bff</color>
  144 + <color name="bgColor">#F0EFF5</color>
  145 + <color name="textColor">#494947</color>
  146 + <color name="xueqing_blue">#ABC9FF</color>
  147 + <color name="zxlx">#1BE2E5</color>
  148 + <color name="huodong_blue">#ACD1FB</color>
  149 + <color name="text_color">#757575</color>
  150 + <color name="textGreen">#5FB762</color>
  151 + <color name="transparent">#00000000</color>
  152 + <color name="deyu_textColor">#60b3f6</color>
  153 + <color name="deyu_BlueColor">#2b71c4</color>
  154 + <color name="line_color">#80bebebe</color>
  155 +
  156 + <color name="backgroud_null">#00000000</color>
  157 +</resources>
... ...
mychartlibrary/src/main/res/values/dimens.xml 0 → 100644
... ... @@ -0,0 +1,101 @@
  1 +<resources>
  2 +
  3 + <!-- Default screen margins, per the Android Design guidelines. -->
  4 + <dimen name="activity_horizontal_margin">16dp</dimen>
  5 + <dimen name="activity_vertical_margin">16dp</dimen>
  6 +
  7 + <!-- margin -->
  8 + <dimen name="margin_tiny">4dp</dimen>
  9 + <dimen name="margin_small">8dp</dimen>
  10 + <dimen name="margin_medium">16dp</dimen>
  11 + <dimen name="margin_large">32dp</dimen>
  12 + <dimen name="margin_huge">64dp</dimen>
  13 + <dimen name="margin_only_txt">48dp</dimen>
  14 + <dimen name="detail_image_height">260dp</dimen>
  15 +
  16 + <!-- txtsize -->
  17 + <dimen name="txtsize_display1">34dp</dimen>
  18 + <dimen name="txtsize_num">36dp</dimen>
  19 + <dimen name="txtsize_headline">24dp</dimen>
  20 + <dimen name="txtsize_title">20dp</dimen>
  21 + <dimen name="txtsize_subhead">16dp</dimen>
  22 + <dimen name="txtsize_body">14dp</dimen>
  23 + <dimen name="txtsize_caption">12dp</dimen>
  24 +
  25 + <!-- other size -->
  26 + <dimen name="corner_radius">2dp</dimen>
  27 + <dimen name="banner_height">136dp</dimen>
  28 +
  29 + <dimen name="def_height">50dp</dimen>
  30 + <dimen name="avatarSize">50dp</dimen>
  31 + <dimen name="smallSpace">6dp</dimen>
  32 +
  33 + <dimen name="dp_066">0.66dp</dimen>
  34 + <dimen name="dp_2">2dp</dimen>
  35 + <dimen name="dp_4">4dp</dimen>
  36 + <dimen name="dp_5">5dp</dimen>
  37 + <dimen name="dp_8">8dp</dimen>
  38 + <dimen name="dp_10">10dp</dimen>
  39 + <dimen name="dp_14">14dp</dimen>
  40 + <dimen name="dp_16">16dp</dimen>
  41 + <dimen name="dp_22">22dp</dimen>
  42 + <dimen name="dp_24">24dp</dimen>
  43 + <dimen name="dp_26">26dp</dimen>
  44 +
  45 + <dimen name="dp_30">30dp</dimen>
  46 + <dimen name="dp_36">36dp</dimen>
  47 + <dimen name="dp_40">40dp</dimen>
  48 + <dimen name="dp_60">60dp</dimen>
  49 + <dimen name="dp_72">72dp</dimen>
  50 +
  51 + <dimen name="sp_12">12sp</dimen>
  52 + <dimen name="sp_14">14sp</dimen>
  53 + <dimen name="sp_16">16dp</dimen>
  54 + <dimen name="sp_18">18sp</dimen>
  55 +
  56 + <dimen name="textSize10">10dp</dimen>
  57 + <dimen name="textSize12">12dp</dimen>
  58 + <dimen name="textSize14">14dp</dimen>
  59 + <dimen name="textSize16">16dp</dimen>
  60 + <dimen name="textSize18">18dp</dimen>
  61 + <dimen name="textSize20">20dp</dimen>
  62 + <dimen name="textSize24">24dp</dimen>
  63 + <dimen name="textSize30">30dp</dimen>
  64 + <dimen name="size_dp_1">1dp</dimen>
  65 + <dimen name="size_dp_2">2dp</dimen>
  66 + <dimen name="size_dp_3">3dp</dimen>
  67 + <dimen name="size_dp_4">4dp</dimen>
  68 + <dimen name="size_dp_5">5dp</dimen>
  69 + <dimen name="size_dp_6">6dp</dimen>
  70 + <dimen name="size_dp_7">7dp</dimen>
  71 + <dimen name="size_dp_8">8dp</dimen>
  72 + <dimen name="size_dp_9">9dp</dimen>
  73 + <dimen name="size_dp_10">10dp</dimen>
  74 + <dimen name="size_dp_11">11dp</dimen>
  75 + <dimen name="size_dp_12">12dp</dimen>
  76 + <dimen name="size_dp_13">13dp</dimen>
  77 + <dimen name="size_dp_14">14dp</dimen>
  78 + <dimen name="size_dp_15">15dp</dimen>
  79 + <dimen name="size_dp_16">16dp</dimen>
  80 + <dimen name="size_dp_17">17.0dp</dimen>
  81 + <dimen name="size_dp_18">18.0dp</dimen>
  82 + <dimen name="size_dp_19">19dp</dimen>
  83 + <dimen name="size_dp_20">20dp</dimen>
  84 + <dimen name="size_dp_24">24dp</dimen>
  85 + <dimen name="size_dp_25">25dp</dimen>
  86 + <dimen name="size_dp_30">30dp</dimen>
  87 + <dimen name="size_dp_32">32dp</dimen>
  88 + <dimen name="size_dp_40">40dp</dimen>
  89 + <dimen name="size_dp_50">50dp</dimen>
  90 + <dimen name="size_dp_60">60dp</dimen>
  91 + <dimen name="size_dp_80">80dp</dimen>
  92 + <dimen name="size_dp_100">100dp</dimen>
  93 + <dimen name="size_dp_110">110dp</dimen>
  94 + <dimen name="size_dp_120">120dp</dimen>
  95 + <dimen name="size_dp_150">150dp</dimen>
  96 + <dimen name="size_dp_200">200dp</dimen>
  97 + <dimen name="size_dp_250">250dp</dimen>
  98 + <dimen name="size_dp_300">300dp</dimen>
  99 + <dimen name="size_dp_310">310dp</dimen>
  100 +
  101 +</resources>
0 102 \ No newline at end of file
... ...
mychartlibrary/src/main/res/values/strings.xml 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<resources>
  2 + <string name="app_name">MyChartLibrary</string>
  3 + <!-- 录音 -->
  4 + <string name="normal">按住 说话</string>
  5 + <string name="recording">松开 结束</string>
  6 + <string name="want_to_cancle">松开手指,取消发送</string>
  7 + <string name="shouzhishanghua">手指上滑,取消发送</string>
  8 + <string name="tooshort">录音时间过短</string>
  9 + <string name="toolong">录音时间过长</string>
  10 +</resources>
... ...
mychartlibrary/src/main/res/values/styles.xml 0 → 100644
... ... @@ -0,0 +1,97 @@
  1 +<resources>
  2 +
  3 + <!-- Base application theme. -->
  4 + <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  5 + <!-- Customize your theme here. -->
  6 + <item name="colorPrimary">@color/colorPrimary</item>
  7 + <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  8 + <item name="colorAccent">@color/colorAccent</item>
  9 + </style>
  10 +
  11 + <style name="dialog" parent="Theme.AppCompat.Light.Dialog.Alert">
  12 + <item name="colorPrimary">@color/colorPrimary</item>
  13 + <item name="colorAccent">@color/colorAccent</item>
  14 + <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  15 + <item name="android:windowFrame">@null</item>
  16 + <item name="android:windowIsFloating">true</item>
  17 + <item name="android:windowIsTranslucent">false</item>
  18 + <item name="android:windowNoTitle">true</item>
  19 + <item name="android:background">@android:color/transparent</item>
  20 + <item name="android:windowBackground">@android:color/transparent</item>
  21 + <item name="android:backgroundDimEnabled">true</item>
  22 + </style>
  23 +
  24 + <style name="AlertDialogCustom" parent="Theme.AppCompat.Light.Dialog.Alert">
  25 + <item name="colorPrimary">@color/colorPrimary</item>
  26 + <item name="colorAccent">@color/colorAccent</item>
  27 + <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  28 + </style>
  29 +
  30 + <style name="DialogTips" parent="Theme.AppCompat.Light.Dialog.Alert">
  31 + <item name="colorPrimary">@color/colorPrimary</item>
  32 + <item name="colorAccent">@color/colorAccent</item>
  33 + <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  34 + <item name="android:gravity">center</item>
  35 + <item name="android:windowBackground">@color/transparent</item>
  36 + <item name="android:windowCloseOnTouchOutside">false</item>
  37 + </style>
  38 +
  39 + <style name="TextView_Wrap_16">
  40 + <item name="android:layout_width">wrap_content</item>
  41 + <item name="android:layout_height">wrap_content</item>
  42 + <item name="android:textSize">@dimen/textSize16</item>
  43 + </style>
  44 +
  45 + <style name="TextView_Width_Match_16">
  46 + <item name="android:layout_width">match_parent</item>
  47 + <item name="android:layout_height">wrap_content</item>
  48 + <item name="android:textSize">@dimen/textSize16</item>
  49 + </style>
  50 +
  51 + <style name="TextView_Height_Match_16">
  52 + <item name="android:layout_width">wrap_content</item>
  53 + <item name="android:layout_height">match_parent</item>
  54 + <item name="android:textSize">@dimen/textSize16</item>
  55 + </style>
  56 +
  57 + <style name="TextView_Match_16">
  58 + <item name="android:layout_width">match_parent</item>
  59 + <item name="android:layout_height">match_parent</item>
  60 + <item name="android:textSize">@dimen/textSize16</item>
  61 + </style>
  62 + <style name="MyProgressDialog" parent="@android:style/Theme.Dialog">
  63 + <item name="android:windowBackground">@color/transparent</item>
  64 + <item name="android:windowFrame">@color/transparent</item>
  65 + <item name="android:windowNoTitle">true</item>
  66 + <item name="android:windowIsFloating">true</item>
  67 + <item name="android:windowIsTranslucent">true</item>
  68 + <item name="android:backgroundDimEnabled">true</item>
  69 + </style>
  70 +
  71 + <style name="AppTheme.ToolbarPopupOverlay" parent="ThemeOverlay.AppCompat.Light">
  72 + <item name="overlapAnchor">false</item>
  73 + </style>
  74 +
  75 + <style name="TextAppearance.ExpandedTitle" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
  76 + <item name="android:textSize">26sp</item>
  77 + </style>
  78 +
  79 + <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
  80 + <!--<item name="colorPrimary">@color/colorPrimary</item>-->
  81 + <!--<item name="colorPrimaryDark">@color/colorPrimaryDark</item>-->
  82 + <!--<item name="colorAccent">@color/colorAccent</item>-->
  83 + </style>
  84 +
  85 + <style name="AppBarTheme" parent="android:Theme.Holo.Light">
  86 + <item name="android:windowFullscreen">false</item>
  87 + <item name="android:windowIsTranslucent">true</item>
  88 + </style>
  89 +
  90 + <style name="Theme_audioDialog" parent="@android:style/Theme.Dialog">
  91 + <item name="android:windowBackground">@mipmap/tb_dialog_loading_bg</item>
  92 + <item name="android:windowFrame">@null</item>
  93 + <item name="android:windowIsFloating">true</item>
  94 + <item name="android:windowIsTranslucent">true</item>
  95 + <item name="android:backgroundDimEnabled">false</item>
  96 + </style>
  97 +</resources>
... ...
mychartlibrary/src/test/java/com/shunzhi/mychartlibrary/ExampleUnitTest.java 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +package com.shunzhi.mychartlibrary;
  2 +
  3 +import org.junit.Test;
  4 +
  5 +import static org.junit.Assert.*;
  6 +
  7 +/**
  8 + * Example local unit test, which will execute on the development machine (host).
  9 + *
  10 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  11 + */
  12 +public class ExampleUnitTest {
  13 + @Test
  14 + public void addition_isCorrect() {
  15 + assertEquals(4, 2 + 2);
  16 + }
  17 +}
0 18 \ No newline at end of file
... ...
settings.gradle
1   -include ':app', ':mvpsdk', ':roundedimageview-2.2.1', ':processor'
  1 +include ':app', ':mvpsdk', ':roundedimageview-2.2.1', ':processor', ':mychartlibrary'
... ...