huangxinbao

add whitebroard and emoji icon

正在显示 100 个修改的文件 包含 4213 行增加161 行删除

要显示太多修改。

为保证性能只显示 100 of 100+ 个文件。

... ... @@ -36,8 +36,10 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
compile project(':xdy')
compile 'com.android.support:design:23.4.0'
compile 'com.squareup.picasso:picasso:2.3.2'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile project(':xdy')
compile 'com.rockerhieu.emojicon:library:1.3.1'
compile 'org.kymjs.kjframe:kjframe:2.6'
}
... ...
... ... @@ -21,6 +21,7 @@ import android.widget.TextView;
import com.eventhandle.SmartEventCallback;
import com.google.gson.Gson;
import com.mang.xdy.common.Constants;
import com.mang.xdy.core.XdySdk;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.adapter.SimpleFragmentPagerAdapter;
... ... @@ -81,7 +82,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
break;
case -1:
//退出
XdySdk.setAsyncApi("leaveClass", "");
XdySdk.api("leaveClass", "");
break;
case 0:
parseJoinClass((String) msg.obj,true);
... ... @@ -175,7 +176,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
public void init() {
initClass = getIntent().getStringExtra("init");
XdySdk.setAsyncApi("init", initClass);
XdySdk.api("init", initClass);
}
//判断解析是否有密码
... ... @@ -210,14 +211,14 @@ public class AudioPublisherActivity extends AppCompatActivity {
String temp=new Gson().toJson(joinClass);
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e("加入课堂", jsonParmp);
XdySdk.setAsyncApi("joinClass", jsonParmp);
XdySdk.api("joinClass", jsonParmp);
}
public void playVideo(String response) {
VideoPlayBean videoPlayBean = JsonUtil.parseJsonToBean(response, VideoPlayBean.class);
if (videoPlayBean != null && videoPlayBean.getRtmpUrl() != null)
XdyLogUtil.e(TAG, "执行了ss" + videoPlayBean.getRtmpUrl());
XdySdk.setAsyncApi("playVideo", videoPlayBean.getRtmpUrl(), surfaceviewPlayVideo, AudioPublisherActivity.this, new EventHande_Video());
XdySdk.api("playVideo", videoPlayBean.getRtmpUrl(), surfaceviewPlayVideo, AudioPublisherActivity.this, new EventHande_Video());
// img_playVideo_novideo.setVisibility(View.GONE);
ToastUtil.showToastshort("视频播放初始化",AudioPublisherActivity.this);
}
... ... @@ -226,7 +227,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
AudioPlayBean audioPlayBean = JsonUtil.parseJsonToBean(response, AudioPlayBean.class);
if (audioPlayBean != null && audioPlayBean.getRtmpUrl() != null) {
XdyLogUtil.e(TAG, "执行了" + audioPlayBean.getRtmpUrl());
XdySdk.setAsyncApi("playAudio", audioPlayBean.getRtmpUrl(), null, AudioPublisherActivity.this, new EventHande_Video());
XdySdk.api("playAudio", audioPlayBean.getRtmpUrl(), null, AudioPublisherActivity.this, new EventHande_Video());
// img_playVideo_novideo.setVisibility(View.GONE);
ToastUtil.showToastshort("音频播放初始化",AudioPublisherActivity.this);
}
... ... @@ -251,7 +252,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e(TAG, "文档" + jsonParmp);
XdySdk.setAsyncApi("getDocImageFullPath", jsonParmp);
XdySdk.api("getDocImageFullPath", jsonParmp);
}
}
... ... @@ -262,7 +263,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
"}";
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e(TAG, "聊天" + jsonParmp);
XdySdk.setAsyncApi("sendChatMsg", jsonParmp);
XdySdk.api("sendChatMsg", jsonParmp);
}
... ... @@ -280,7 +281,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
String ids_new = "getVideoPublishPath";
String tem = "{ \"type\": \"live\"}";
String s = XdyStringUtils.stringToJson(tem, true);
XdySdk.setAsyncApi(ids_new, s);
XdySdk.api(ids_new, s);
}
public void publisherVideo(String response) {
... ... @@ -294,10 +295,10 @@ public class AudioPublisherActivity extends AppCompatActivity {
// String url_text="rtmp://123.56.205.116:6000/live/h5dev_1999957388_980_983041_1491813919";
publisherSuccess=liveBean.getPublishUrl();
if(isPusherAudio){
XdySdk.setAsyncApi("publishAudio", liveBean.getPublishUrl(), surfaceview_pubisherVideo, AudioPublisherActivity.this,new EventHande());
XdySdk.api("publishAudio", liveBean.getPublishUrl(), surfaceview_pubisherVideo, AudioPublisherActivity.this,new EventHande());
ToastUtil.showToastshort("推送纯音频初始化中",AudioPublisherActivity.this);
}else{
XdySdk.setAsyncApi("publishVideo", liveBean.getPublishUrl(), surfaceview_pubisherVideo, AudioPublisherActivity.this,new EventHande());
XdySdk.api("publishVideo", liveBean.getPublishUrl(), surfaceview_pubisherVideo, AudioPublisherActivity.this,new EventHande());
ToastUtil.showToastshort("推送视频初始化中",AudioPublisherActivity.this);
}
... ... @@ -307,7 +308,7 @@ public class AudioPublisherActivity extends AppCompatActivity {
publisherEntity.setPublishUrl(publisherSuccess);
String pamp= new Gson().toJson(publisherEntity);
XdyLogUtil.e("推流成功",""+pamp);
XdySdk.setAsyncApi("publishVideo",pamp);
XdySdk.api("publishVideo",pamp);
}
}
... ... @@ -317,11 +318,18 @@ public class AudioPublisherActivity extends AppCompatActivity {
}
}
/**
* 测试Audio
*/
public void publisherAudioText(){
XdySdk.api(Constants.PUBLISH_AUDIO, "", surfaceview_pubisherVideo, AudioPublisherActivity.this,"");
}
@Override
public void onBackPressed() {
XdySdk.setAsyncApi("unPublishVideo","");
XdySdk.api("unPublishVideo","");
super.onBackPressed();
}
... ... @@ -347,15 +355,16 @@ public class AudioPublisherActivity extends AppCompatActivity {
break;
case R.id.btn_videoPlay_publisherAudio:
//获取推流地址推送音频
getPublish();
isPusherAudio=true;
XdySdk.onPublisherStop();
ToastUtil.showToastshort("推送音频",AudioPublisherActivity.this);
btn_videoPlay_publisherAudio.setClickable(false);
// getPublish();
// isPusherAudio=true;
// XdySdk.onPublisherStop();
// ToastUtil.showToastshort("推送音频",AudioPublisherActivity.this);
// btn_videoPlay_publisherAudio.setClickable(false);
publisherAudioText();
break;
case R.id.btn_videoPlay_stop:
ToastUtil.showToastshort("正在退出,请稍等",this);
XdySdk.setAsyncApi("unPublishVideo","");
XdySdk.api("unPublishVideo","");
finish();
break;
}
... ...
... ... @@ -4,6 +4,8 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Image;
import android.os.Bundle;
import android.os.Handler;
... ... @@ -24,6 +26,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.eventhandle.SmartEventCallback;
import com.google.gson.Gson;
import com.mang.xdy.core.XdySdk;
... ... @@ -37,12 +40,17 @@ import com.mang.xdy.demo.bean.InitClassSuccessEntity;
import com.mang.xdy.demo.bean.JoinClass;
import com.mang.xdy.demo.bean.LiveBean;
import com.mang.xdy.demo.bean.VideoPlayBean;
import com.mang.xdy.demo.bean.WhiteboardUpdateEntity;
import com.mang.xdy.demo.utils.JsonUtil;
import com.mang.xdy.demo.utils.ToastUtil;
import com.mang.xdy.demo.widget.CanvasView;
import com.mang.xdy.utils.XdyLogUtil;
import com.mang.xdy.utils.XdyStringUtils;
import com.squareup.picasso.Picasso;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
... ... @@ -73,7 +81,16 @@ public class VideoPlayActivity extends AppCompatActivity {
private TabLayout tabLayout;
@BindView(R.id.surfaceview_playVideo)
SurfaceView surfaceviewPlayVideo;
@BindView(R.id.canvas_playVideo_showWhiteBroad)
CanvasView mCanvasView;
private String initClass = "";
public OnAcceptFromCoreToFragmentListener mOnAcceptFromCoreToFragmentListener;
public interface OnAcceptFromCoreToFragmentListener{
void onAcceptInfo(String type,String response);
}
public void setmOnAcceptFromCoreToFragmentListener(OnAcceptFromCoreToFragmentListener mOnAcceptFromCoreToFragmentListener){
this.mOnAcceptFromCoreToFragmentListener=mOnAcceptFromCoreToFragmentListener;
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
... ... @@ -85,7 +102,7 @@ public class VideoPlayActivity extends AppCompatActivity {
break;
case -1:
//退出
XdySdk.setAsyncApi("leaveClass", "");
XdySdk.api("leaveClass", "");
break;
case 0:
parseJoinClass((String) msg.obj,true);
... ... @@ -114,7 +131,7 @@ public class VideoPlayActivity extends AppCompatActivity {
getMsg((String) msg.obj);
break;
case 6:
//推流video
//图片
setDocImage((String) msg.obj);
break;
case 7:
... ... @@ -134,8 +151,9 @@ public class VideoPlayActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_play);
ButterKnife.bind(this);
// setTablayout();
init();
setTablayout();
XdyLogUtil.e(TAG,"当前线程 main:"+android.os.Process.myPid()+"线程:"+Thread.currentThread().getId()+"");
XdySdk.setOnXdyAsyncMessageLitener(new XdySdk.OnXdyAsyncMessageLitener() {
@Override
... ... @@ -191,8 +209,9 @@ public class VideoPlayActivity extends AppCompatActivity {
break;
case "whiteboard_annotation_update":
ToastUtil.showToastshort("白板信息更新" + response, VideoPlayActivity.this);
showDoc(type,response);
break;
case "live":
case "getDocImageFullPath":
// String urls= "rtmp://player.daniulive.com:1935/hls/stream";;
//推流直播
Message message6=Message.obtain();
... ... @@ -206,18 +225,21 @@ public class VideoPlayActivity extends AppCompatActivity {
break;
case "audio_stop":
break;
break;
default:{
XdyLogUtil.e("xuedianyunlog",response);
}
}
if(mOnAcceptFromCoreToFragmentListener!=null){
mOnAcceptFromCoreToFragmentListener.onAcceptInfo(type,response);
}
}
});
}
public void init() {
initClass = getIntent().getStringExtra("init");
XdySdk.setAsyncApi("init", initClass);
XdySdk.api("init", initClass);
}
... ... @@ -261,7 +283,7 @@ public class VideoPlayActivity extends AppCompatActivity {
String temp=new Gson().toJson(joinClass);
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e("加入课堂", jsonParmp);
XdySdk.setAsyncApi("joinClass", jsonParmp);
XdySdk.api("joinClass", jsonParmp);
}
VideoPlayBean videoPlayBean;
public void playVideo(String response) {
... ... @@ -270,7 +292,7 @@ public class VideoPlayActivity extends AppCompatActivity {
// XdyLogUtil.e(TAG, "执行了ss" + videoPlayBean.getRtmpUrl());
bt_stop.setEnabled(true);
// XdySdk.setAsyncApi("playVideo", videoPlayBean.getRtmpUrl(), surfaceviewPlayVideo, VideoPlayActivity.this, new EventHande_Video());
XdySdk.setAsyncApi("playVideo", response+"", surfaceviewPlayVideo, VideoPlayActivity.this,"");
XdySdk.api("playVideo", response+"", surfaceviewPlayVideo, VideoPlayActivity.this,"");
img_playVideo_novideo.setVisibility(View.GONE);
// }else{
// bt_stop.setEnabled(false);
... ... @@ -283,7 +305,7 @@ public class VideoPlayActivity extends AppCompatActivity {
// if (audioPlayBean != null && audioPlayBean.getRtmpUrl() != null) {
// XdyLogUtil.e(TAG, "执行了" + audioPlayBean.getRtmpUrl());
// XdySdk.setAsyncApi("playAudio", audioPlayBean.getRtmpUrl(), null, VideoPlayActivity.this, new EventHande_Video());
XdySdk.setAsyncApi("playAudio", response, null, VideoPlayActivity.this, "");
XdySdk.api("playAudio", response, null, VideoPlayActivity.this, "");
img_playVideo_novideo.setVisibility(View.GONE);
ToastUtil.showToastshort("音频播放初始化",VideoPlayActivity.this);
// }
... ... @@ -312,7 +334,7 @@ public class VideoPlayActivity extends AppCompatActivity {
getDocImageEntity.setType("jpg");
String jsonParmp = new Gson().toJson(getDocImageEntity);
XdyLogUtil.e(TAG, "文档" + jsonParmp);
XdySdk.setAsyncApi("getDocImageFullPath", jsonParmp);
XdySdk.api("getDocImageFullPath", jsonParmp);
}
}
... ... @@ -323,7 +345,7 @@ public class VideoPlayActivity extends AppCompatActivity {
"}";
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e(TAG, "聊天" + jsonParmp);
XdySdk.setAsyncApi("sendChatMsg", jsonParmp);
XdySdk.api("sendChatMsg", jsonParmp);
}
... ... @@ -338,35 +360,9 @@ public class VideoPlayActivity extends AppCompatActivity {
//获取推流地址
public void getPublish() {
// String ids_new = "getVideoPublishPath";
// String tem = "{ \"type\": \"live\"}";
// String s = XdyStringUtils.stringToJson(tem, true);
// XdySdk.setAsyncApi(ids_new, s);
}
public void publisherVideo(String response) {
// XdySdk.onPlayStop();
// String url = XdyStringUtils.stringToJson(response);
// XdyLogUtil.e("调用任务了播视频了url:", "" + url);
// String us = response.substring(1, response.length() - 1);
// XdyLogUtil.e("调用任务了播视频了ursfdfl:", "" + us);
// try {
// LiveBean liveBean = new Gson().fromJson(url, LiveBean.class);
//
// if (liveBean != null&&liveBean.getCode()==0) {
// String url_text="rtmp://player.daniulive.com:1935/hls/stream";
//// XdySdk.setAsyncApi("publishVideo", liveBean.getPublishUrl(), surfaceviewPlayVideo, VideoPlayActivity.this,new EventHande());
//// tv_videoPlay_url.setText("推流地址:"+liveBean.getPublishUrl());
// tv_videoPlay_url.setText("推流地址:"+url_text);
// XdyLogUtil.e(TAG,liveBean.getPublishUrl());
// XdySdk.setAsyncApi("publishVideo", url_text, surfaceview_pubisherVideo, VideoPlayActivity.this,new EventHande());
// ToastUtil.showToastshort("推流初始化中",VideoPlayActivity.this);
// }
// } catch (Exception e) {
// XdyLogUtil.e("调用任务了播视频了e", "" + e.getMessage());
//
// }
}
@Override
... ... @@ -390,78 +386,11 @@ public class VideoPlayActivity extends AppCompatActivity {
case R.id.bt_stop:
//停止视频
if(videoPlayBean!=null) {
XdySdk.setAsyncApi("stopVideo", videoPlayBean.getMediaId() + "");
XdySdk.api("stopVideo", videoPlayBean.getMediaId() + "");
}
break;
}
}
class EventHande implements SmartEventCallback {
@Override
public void onCallback(int code, long param1, long param2, String param3, String param4, Object param5) {
switch (code) {
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STARTED:
Log.i(TAG, "开始。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTING:
Log.i(TAG, "连接中。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTION_FAILED:
Log.i(TAG, "连接失败。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTED:
Log.i(TAG, "连接成功。。");
//TODO
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DISCONNECTED:
Log.i(TAG, "连接断开。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP:
Log.i(TAG, "关闭。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RESOLUTION_INFO:
Log.i(TAG, "分辨率信息: width: " + param1 + ", height: " + param2);
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_NO_MEDIADATA_RECEIVED:
Log.i(TAG, "收不到媒体数据,可能是url错误。。");
}
}
}
class EventHande_Video implements SmartEventCallback {
@Override
public void onCallback(int code, long param1, long param2, String param3, String param4, Object param5) {
switch (code) {
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STARTED:
Log.i(TAG, "开始。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTING:
Log.i(TAG, "连接中。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTION_FAILED:
Log.i(TAG, "连接失败。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTED:
Log.i(TAG, "连接成功。。");
//TODO
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DISCONNECTED:
Log.i(TAG, "连接断开。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP:
Log.i(TAG, "关闭。。");
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RESOLUTION_INFO:
Log.i(TAG, "分辨率信息: width: " + param1 + ", height: " + param2);
break;
case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_NO_MEDIADATA_RECEIVED:
Log.i(TAG, "收不到媒体数据,可能是url错误。。");
}
}
}
class PersonDialog extends Dialog {
public PersonDialog(Context context) {
this(context, false);
... ... @@ -528,9 +457,54 @@ public class VideoPlayActivity extends AppCompatActivity {
if(resonse.length()>10){
String temp=XdyStringUtils.stringToJson(resonse);
String url=temp.substring(2,temp.length()-2);
urlsss=url;
XdyLogUtil.e(TAG,"截取后的"+url);
Picasso.with(this).load(url).placeholder(R.mipmap.novideo).into(mDocImage);
Picasso.with(this).load(url).placeholder(R.mipmap.novideo).into(mDocImage);
getBitmap(url);
}
}
String urlsss="";
Bitmap bitmap;
public void showDoc(String type,String response){
mCanvasView.setZOrderMediaOverlay(true);
mCanvasView.setBitmap(bitmap,false);
WhiteboardUpdateEntity whiteboardUpdateEntity= JsonUtil.parseJsonToBean(response,WhiteboardUpdateEntity.class);
if(whiteboardUpdateEntity!=null){
drawline(whiteboardUpdateEntity);
}
}
private void drawline(WhiteboardUpdateEntity o) {
if (o != null) {
if (o.isFresh) {
if (mCanvasView != null) {
mCanvasView.clear();
}
}
if (o.annotaionItems != null) {
if (mCanvasView != null) {
mCanvasView.drawLine(o.annotaionItems);
}
}
}
}
public void getBitmap(final String url){
new Thread(){
@Override
public void run() {
super.run();
try {
bitmap= Glide.with(VideoPlayActivity.this).load(url).asBitmap().into(480,480).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}.start();
}
}
... ...
... ... @@ -93,7 +93,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
break;
case -1:
//退出
XdySdk.setAsyncApi("leaveClass", "");
XdySdk.api("leaveClass", "");
break;
case 0:
parseJoinClass((String) msg.obj,true);
... ... @@ -191,7 +191,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
public void init() {
initClass = getIntent().getStringExtra("init");
XdySdk.setAsyncApi("init", initClass);
XdySdk.api("init", initClass);
}
//判断解析是否有密码
... ... @@ -226,14 +226,14 @@ public class VideoPublisherActivity extends AppCompatActivity {
String temp=new Gson().toJson(joinClass);
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e("加入课堂", jsonParmp);
XdySdk.setAsyncApi("joinClass", jsonParmp);
XdySdk.api("joinClass", jsonParmp);
}
public void playVideo(String response) {
VideoPlayBean videoPlayBean = JsonUtil.parseJsonToBean(response, VideoPlayBean.class);
if (videoPlayBean != null && videoPlayBean.getRtmpUrl() != null)
XdyLogUtil.e(TAG, "执行了ss" + videoPlayBean.getRtmpUrl());
XdySdk.setAsyncApi("playVideo", videoPlayBean.getRtmpUrl(), surfaceviewPlayVideo, VideoPublisherActivity.this, new EventHande_Video());
XdySdk.api("playVideo", videoPlayBean.getRtmpUrl(), surfaceviewPlayVideo, VideoPublisherActivity.this, new EventHande_Video());
// img_playVideo_novideo.setVisibility(View.GONE);
ToastUtil.showToastshort("视频播放初始化",VideoPublisherActivity.this);
}
... ... @@ -242,7 +242,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
AudioPlayBean audioPlayBean = JsonUtil.parseJsonToBean(response, AudioPlayBean.class);
if (audioPlayBean != null && audioPlayBean.getRtmpUrl() != null) {
XdyLogUtil.e(TAG, "执行了" + audioPlayBean.getRtmpUrl());
XdySdk.setAsyncApi("playAudio", audioPlayBean.getRtmpUrl(), null, VideoPublisherActivity.this, new EventHande_Video());
XdySdk.api("playAudio", audioPlayBean.getRtmpUrl(), null, VideoPublisherActivity.this, new EventHande_Video());
// img_playVideo_novideo.setVisibility(View.GONE);
ToastUtil.showToastshort("音频播放初始化",VideoPublisherActivity.this);
}
... ... @@ -267,7 +267,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e(TAG, "文档" + jsonParmp);
XdySdk.setAsyncApi("getDocImageFullPath", jsonParmp);
XdySdk.api("getDocImageFullPath", jsonParmp);
}
}
... ... @@ -278,7 +278,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
"}";
String jsonParmp = XdyStringUtils.stringToJson(temp, true);
XdyLogUtil.e(TAG, "聊天" + jsonParmp);
XdySdk.setAsyncApi("sendChatMsg", jsonParmp);
XdySdk.api("sendChatMsg", jsonParmp);
}
... ... @@ -296,14 +296,14 @@ public class VideoPublisherActivity extends AppCompatActivity {
String ids_new = "getVideoPublishPath";
String tem = "{ \"type\": \"live\"}";
String s = XdyStringUtils.stringToJson(tem, true);
XdySdk.setAsyncApi(ids_new, s);
XdySdk.api(ids_new, s);
}
/**
* 获取封装的推流地址
*/
public void publisherVideoText(){
// XdySdk.setAsyncApi("publishVideo", "", surfaceview_pubisherVideo, VideoPublisherActivity.this,"");
XdySdk.api("publishVideo", "", surfaceview_pubisherVideo, VideoPublisherActivity.this,"");
}
... ... @@ -311,7 +311,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
* 测试Audio
*/
public void publisherAudioText(){
XdySdk.setAsyncApi(Constants.PUBLISH_AUDIO, "", surfaceview_pubisherVideo, VideoPublisherActivity.this,"");
// XdySdk.setAsyncApi(Constants.PUBLISH_AUDIO, "", surfaceview_pubisherVideo, VideoPublisherActivity.this,"");
}
public void publisherVideo(String response) {
... ... @@ -325,10 +325,10 @@ public class VideoPublisherActivity extends AppCompatActivity {
// String url_text="rtmp://123.56.205.116:6000/live/h5dev_1999957388_980_983041_1491813919";
publisherSuccess=liveBean.getPublishUrl();
if(isPusherAudio){
XdySdk.setAsyncApi("publishAudio", liveBean.getPublishUrl(), surfaceview_pubisherVideo, VideoPublisherActivity.this,new EventHande());
XdySdk.api("publishAudio", liveBean.getPublishUrl(), surfaceview_pubisherVideo, VideoPublisherActivity.this,new EventHande());
ToastUtil.showToastshort("推送纯音频初始化中",VideoPublisherActivity.this);
}else{
XdySdk.setAsyncApi("publishVideo", liveBean.getPublishUrl(), surfaceview_pubisherVideo, VideoPublisherActivity.this,new EventHande());
XdySdk.api("publishVideo", liveBean.getPublishUrl(), surfaceview_pubisherVideo, VideoPublisherActivity.this,new EventHande());
ToastUtil.showToastshort("推送视频初始化中",VideoPublisherActivity.this);
}
isAbleback=true;
... ... @@ -338,7 +338,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
publisherEntity.setPublishUrl(publisherSuccess);
String pamp= new Gson().toJson(publisherEntity);
XdyLogUtil.e("推流成功",""+pamp);
XdySdk.setAsyncApi("publishVideo",pamp);
XdySdk.api("publishVideo",pamp);
}
}
... ... @@ -352,12 +352,7 @@ public class VideoPublisherActivity extends AppCompatActivity {
@Override
public void onBackPressed() {
//退出课堂
//
//// ToastUtil.showToastshort("正在退出,请稍等",this);
// PublisherVideoExitBean publisherVideoExitBean = new PublisherVideoExitBean();
// publisherVideoExitBean.setMediaId(publisherVideoExitBean.getMediaId());
XdySdk.setAsyncApi("unPublishVideo","");
XdySdk.api("unPublishVideo","");
super.onBackPressed();
... ... @@ -379,22 +374,15 @@ public class VideoPublisherActivity extends AppCompatActivity {
break;
case R.id.btn_videoPlay_pubsherVideo:
// getPublish();
// publisherVideoText();
publisherAudioText();
publisherVideoText();
// publisherAudioText();
ToastUtil.showToastshort("推送视频",VideoPublisherActivity.this);
btnVideoPlayPubsherVideo.setClickable(false);
break;
case R.id.btn_videoPlay_publisherAudio:
//获取推流地址推送音频
// getPublish();
// isPusherAudio=true;
// XdySdk.onPublisherStop();
// ToastUtil.showToastshort("推送音频",VideoPublisherActivity.this);
// btn_videoPlay_publisherAudio.setClickable(false);
break;
case R.id.btn_videoPlay_stop:
ToastUtil.showToastshort("正在退出,请稍等",this);
XdySdk.setAsyncApi("unPublishVideo","");
XdySdk.api("unPublishVideo","");
finish();
break;
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.adapter;
import android.widget.AbsListView;
import android.widget.ImageView;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.bean.Faceicon;
import org.kymjs.kjframe.KJBitmap;
import org.kymjs.kjframe.widget.AdapterHolder;
import org.kymjs.kjframe.widget.KJAdapter;
import java.util.Collection;
/**
* 表情区域GridView的适配器
*
* @author kymjs (http://www.kymjs.com/)
*/
public class FaceAdapter extends KJAdapter<Faceicon> {
private KJBitmap kjb = new KJBitmap();
public FaceAdapter(AbsListView view, Collection<Faceicon> mDatas) {
super(view, mDatas, R.layout.home_chat_item_face);
}
@Override
public void convert(AdapterHolder adapterHolder, Faceicon data, boolean b) {
ImageView view = adapterHolder.getView(R.id.itemImage);
// int id = view.getResources().getIdentifier(s,
// "drawable", view.getContext().getPackageName());
// view.setImageResource(id);
kjb.display(view, data.getPath());
}
}
\ No newline at end of file
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.adapter;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.widget.ImageView;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.widget.chat.ChatFunctionFragment;
import com.mang.xdy.demo.widget.chat.FacePageFragment;
import com.mang.xdy.demo.widget.chat.KJChatKeyboard;
import com.mang.xdy.demo.widget.chat.OnOperationListener;
import com.mang.xdy.demo.widget.chat.PagerSlidingTabStrip;
import com.mang.xdy.demo.widget.emoji.EmojiPageFragment;
import org.kymjs.kjframe.bitmap.BitmapCreate;
import java.io.File;
import java.util.List;
/**
* 控件分类的viewpager适配器
*
* @author kymjs (http://www.kymjs.com/)
*/
public class FaceCategroyAdapter extends FragmentStatePagerAdapter implements
PagerSlidingTabStrip.IconTabProvider {
private final int sMode;
//每个item表示一个folder绝对路径,每个folder中存放的是一套face图片
private List<String> datas;
private OnOperationListener listener;
public FaceCategroyAdapter(FragmentManager fm, int mode) {
super(fm);
sMode = mode;
}
@Override
public void setPageIcon(int position, ImageView image) {
if (position == 0) {
image.setImageResource(R.mipmap.emoji_normal);
return;
}
File file = new File(datas.get(position - 1));
String path = null;
for (int i = 0; i < file.list().length; i++) {
path = file.list()[i];
if (path.endsWith(".png") || path.endsWith(".jpg") || path.endsWith(".jpeg")) {
break;
}
}
Bitmap bitmap = BitmapCreate.bitmapFromFile(file.getAbsolutePath() + "/" + path, 40, 40);
image.setImageBitmap(bitmap);
}
@Override
public int getCount() {
if (sMode == KJChatKeyboard.LAYOUT_TYPE_FACE) {
int count = datas == null ? 0 : datas.size();
//加1是因为有默认的emoji表情分类
return (count + 1);
} else {
return 1;
}
}
@Override
public Fragment getItem(int position) {
Fragment f = null;
if (sMode == KJChatKeyboard.LAYOUT_TYPE_FACE) {
if (position == 0) {
f = new EmojiPageFragment();
((EmojiPageFragment) f).setOnOperationListener(listener);
} else {
position--;
f = new FacePageFragment();
((FacePageFragment) f).setOnOperationListener(listener);
Bundle bundle = new Bundle();
bundle.putString(FacePageFragment.FACE_FOLDER_PATH, datas.get(position));
f.setArguments(bundle);
}
} else {
f = new ChatFunctionFragment();
((ChatFunctionFragment) f).setOnOperationListener(listener);
}
return f;
}
public void setOnOperationListener(OnOperationListener onOperationListener) {
this.listener = onOperationListener;
}
public void refresh(List<String> datas) {
this.datas = datas;
notifyDataSetChanged();
}
}
\ No newline at end of file
... ...
... ... @@ -9,27 +9,37 @@ import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.mang.xdy.demo.fragment.ChatFragment;
import com.mang.xdy.demo.fragment.DocFragment;
import com.mang.xdy.demo.fragment.PageFragment;
import java.util.ArrayList;
import java.util.List;
public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[]{"tab1","tab2","tab3"};
final int PAGE_COUNT = 1;
private String tabTitles[] = new String[]{"tab1","tab2"};
private Context context;
private DocFragment docFragment=new DocFragment();
private ChatFragment chatFragment=new ChatFragment();
private List<Fragment> fragmentList=new ArrayList<>();
public SimpleFragmentPagerAdapter(FragmentManager fm,Context context) {
super(fm);
this.context = context;
fragmentList.add(docFragment);
fragmentList.add(chatFragment);
}
@Override
public Fragment getItem(int position) {
return PageFragment.newInstance(position + 1);
// return PageFragment.newInstance(position + 1);
return fragmentList.get(position);
}
@Override
public int getCount() {
return PAGE_COUNT;
return fragmentList.size();
}
@Override
... ...
... ... @@ -5,6 +5,7 @@ import android.app.Application;
import android.content.Context;
import com.mang.xdy.core.XdySdk;
import com.mang.xdy.demo.utils.ResUtil;
/**
* Created by abao on 2017/3/30.
... ... @@ -18,6 +19,7 @@ public class XdyApplicaiton extends Application {
super.onCreate();
context=this;
XdySdk.init(this);
ResUtil.init(this);
}
public static Activity getActivity(){
return activityList;
... ...
package com.mang.xdy.demo.bean;
import java.util.List;
import java.util.List;
/**
* Created by Admin on 2017/3/27.
*/
public class AnnotaionEntity {
public String type;
public String itemIdx;
public String initiator;
public String parentId;
public String curPageNo;
public List<PointGroupEntity> pointGroup;
public String color;
public int thickness;
public String radius;
public String fontSize;
public String fontName;
public String text;
public String data;
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.bean;
import java.io.Serializable;
/**
* 表情javabean
* @author kymjs (http://www.kymjs.com/) on 6/9/15.
*/
public class Faceicon implements Serializable {
private String name; //网络传输中的值
private String path; //在系统中的绝对路径
private String fileName; //图片文件名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
... ...
package com.mang.xdy.demo.bean;
/**
* Created by Admin on 2017/3/27.
*/
public class PointGroupEntity {
public float w;
public float h;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
... ...
package com.mang.xdy.demo.bean;
/**
* Created by Admin on 2017/3/26.
*/
public class PointXY {
public float x;
public float y;
}
... ...
package com.mang.xdy.demo.bean;
import java.util.List;
/** 书写板更新事件entity
* Created by Admin on 2017/3/27.
*/
public class WhiteboardUpdateEntity {
public boolean isFresh; //是否先清除,true(先清除再绘制),false(在现有的基础上添加绘制)
public List<AnnotaionEntity> annotaionItems; //需要显示的标注标注内容数组(包含不同的type类型)
}
... ...
package com.mang.xdy.demo.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.bean.Faceicon;
import com.mang.xdy.demo.widget.chat.KJChatKeyboard;
import com.mang.xdy.demo.widget.chat.OnOperationListener;
import java.io.File;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by abao on 2017/4/17.
*/
public class ChatFragment extends Fragment {
@BindView(R.id.chat_msg_input_box)
KJChatKeyboard box;
private Context mContext;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_chat,container,false);
ButterKnife.bind(this,view);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mContext=this.getContext();
init();
}
public void init(){
box.setToolBoxIsClick(false);
box.setOnOperationListener(new OnOperationListener() {
@Override
public void send(String content) {
if (!TextUtils.isEmpty(content)) {
// LogUtil.i("聊天内容===" + content);
// mPresenter.sendChatMsg(content, 0);
}
}
@Override
public void selectedFace(Faceicon content) {
/* Message message = new Message(Message.MSG_TYPE_FACE, Message.MSG_STATE_SUCCESS,
"Tom", "avatar", "Jerry", "avatar", content.getPath(), true, true, new
Date());
datas.add(message);
adapter.refresh(datas);*/
}
@Override
public void selectedEmoji(String emoji) {
if (!TextUtils.isEmpty(emoji)) {
int start = box.getEditTextBox().getSelectionStart();
CharSequence content = box.getEditTextBox().getText().insert(start, emoji);
box.getEditTextBox().setText(content);
// 定位光标位置
CharSequence info = box.getEditTextBox().getText();
if (info instanceof Spannable) {
Spannable spanText = (Spannable) info;
Selection.setSelection(spanText, start + emoji.length());
}
box.setEditTextFocus();
}
}
@Override
public void selectedBackSpace(String back) {
// DisplayRules.backspace(box.getEditTextBox());
}
@Override
public void selectedFunction(int index) {
switch (index) {
case 0:
// goToAlbum();
break;
case 1:
// ViewInject.toast("跳转相机");
break;
}
}
});
List<String> faceCagegory = new ArrayList<>();
// File faceList = FileUtils.getSaveFolder("chat");
File faceList = new File("");
if (faceList.isDirectory()) {
File[] faceFolderArray = faceList.listFiles();
for (File folder : faceFolderArray) {
if (!folder.isHidden()) {
faceCagegory.add(folder.getAbsolutePath());
}
}
}
box.setFaceData(faceCagegory);
// mRealListView.setOnTouchListener(getOnTouchListener());
}
/**
* 若软键盘或表情键盘弹起,点击上端空白处应该隐藏输入法键盘
*
* @return 会隐藏输入法键盘的触摸事件监听器
*/
private View.OnTouchListener getOnTouchListener() {
return new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
box.hideLayout();
box.hideKeyboard(mContext);
return false;
}
};
}
}
... ...
package com.mang.xdy.demo.fragment;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import com.google.gson.Gson;
import com.mang.xdy.common.Constants;
import com.mang.xdy.core.XdySdk;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.activity.VideoPlayActivity;
import com.mang.xdy.demo.bean.DocEntity;
import com.mang.xdy.demo.bean.GetDocImageEntity;
import com.mang.xdy.demo.bean.WhiteboardUpdateEntity;
import com.mang.xdy.demo.utils.JsonUtil;
import com.mang.xdy.demo.widget.CanvasView;
import com.mang.xdy.utils.XdyLogUtil;
import com.mang.xdy.utils.XdyStringUtils;
import com.squareup.picasso.Picasso;
import java.util.concurrent.ExecutionException;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by abao on 2017/4/14.
*/
public class DocFragment extends Fragment implements VideoPlayActivity.OnAcceptFromCoreToFragmentListener{
private static String TAG="DocFragment";
@BindView(R.id.canvas_doc_show)
CanvasView mCanvasView;
private Bitmap bitmap;
private Context mContext;
private String whritebroad="";
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
mContext=this.getContext();
}
private static Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_doc,container,false);
ButterKnife.bind(this,view);
return view;
}
public void init(){
VideoPlayActivity videoPlayActivity= (VideoPlayActivity) this.getActivity();
mCanvasView.setBitmap(getEmptyBitmap(),false);
videoPlayActivity.setmOnAcceptFromCoreToFragmentListener(this);
}
public void getDoc(String response) {
DocEntity docEntity = JsonUtil.parseJsonToBean(response, DocEntity.class);
if (docEntity != null && docEntity.getRelativeUrl() != null) {
String url = docEntity.getRelativeUrl();
GetDocImageEntity getDocImageEntity=new GetDocImageEntity();
getDocImageEntity.setPageNum(1);
// getDocImageEntity.setRelativeUrl("/DocSharing/data/1087553281/20170409-204600041/d32594763768243bddc64934be5088a0.swf");
getDocImageEntity.setRelativeUrl(url);
getDocImageEntity.setType("jpg");
String jsonParmp = new Gson().toJson(getDocImageEntity);
XdyLogUtil.e(TAG, "文档" + jsonParmp);
XdySdk.api("getDocImageFullPath", jsonParmp);
}
}
public void setDocImage(String resonse){
if(resonse.length()>10){
String temp= XdyStringUtils.stringToJson(resonse);
String url=temp.substring(2,temp.length()-2);
XdyLogUtil.e(TAG,"截取后的"+url);
getBitmap(url);
}
}
public void getBitmap(final String url){
new Thread(){
@Override
public void run() {
super.run();
try {
bitmap= Glide.with(mContext).load(url).asBitmap().into(480,480).get();
if(bitmap!=null) {
mHandler.post(new Runnable() {
@Override
public void run() {
mCanvasView.setBitmap(bitmap,false);
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}.start();
}
/**
* 展示文档
* @param type
* @param response
*/
public void showDoc(String type,String response){
mCanvasView.setZOrderMediaOverlay(true);
if(bitmap!=null) {
mCanvasView.setBitmap(bitmap,false);
}
// else{
// mCanvasView.setBitmap(getEmptyBitmap(),false);
// }
WhiteboardUpdateEntity whiteboardUpdateEntity= JsonUtil.parseJsonToBean(response,WhiteboardUpdateEntity.class);
if(whiteboardUpdateEntity!=null){
drawline(whiteboardUpdateEntity);
}
}
public Bitmap getEmptyBitmap(){
Bitmap bitmap_empty= BitmapFactory.decodeResource(getResources(),R.mipmap.no_doc);
return bitmap_empty;
}
private void drawline(WhiteboardUpdateEntity o) {
if (o != null) {
if (o.isFresh) {
if (mCanvasView != null) {
mCanvasView.clear();
}
}
if (o.annotaionItems != null) {
if (mCanvasView != null) {
mCanvasView.drawLine(o.annotaionItems);
}
}
}
}
@Override
public void onAcceptInfo(String type, String response) {
XdyLogUtil.e(TAG,"type:"+type+" response:"+response);
switch (type){
case Constants.DOCUMENT_UPDATE:
getDoc(response);
break;
case "getDocImageFullPath":
setDocImage(response);
break;
case Constants.WHITEBOARD_ANNOTATION_UPDATE:
showDoc(type,response);
break;
case Constants.DOCUMENT_DELETE:
bitmap=null;
mCanvasView.setBitmap(getEmptyBitmap(),false);
break;
}
}
}
... ...
package com.mang.xdy.demo.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @version 1.0
* @file DisplayUtil.java
* @brief 获得当前手机一些屏幕信息
* @date 2017/9/22
* Copyright (c) 2017, 学点云
* All rights reserved.
*/
public class DisplayUtil {
/**
* 获得不同手机状态栏高度
* @param ctx
* @return
*/
public static int getStatusBarHeight(Context ctx) {
Class<?> c = null;
Object obj = null;
Field field = null;
int x = 0, statusBarHeight = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
statusBarHeight = ctx.getResources().getDimensionPixelOffset(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return statusBarHeight;
}
/**
* 魅族手机判断是否有SmartBar 并隐藏SmartBar
* @return
*/
@SuppressWarnings("unused")
public static boolean judgeBar() {
boolean isHasBar = false;
try {
try {
Method method = Class.forName("android.os.Build").getMethod(
"hasSmartBar");
isHasBar = ((Boolean) method.invoke(null)).booleanValue();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return isHasBar;
}
/**
* 全屏显示。。
*/
@SuppressLint("NewApi")
public static void getFullScrean(Activity ctx) {
Window mWindow = ctx.getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
mWindow.setAttributes(params);
}
/**
* @param ctx
* @brief 获得屏幕像素密度
*/
public static float getScreenDensity(Context ctx) {
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.density;
}
/**
* @param context
* @param dipValue
* @return
* @brief DP转像素
*/
public static int dip2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
/**
* @param context
* @param
* @return
* @brief 像素转DP
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 是否有导航栏
* @param context
* @return
*/
private static boolean checkDeviceHasNavigationBar(Context context) {
boolean hasNavigationBar = false;
Resources rs = context.getResources();
int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
if (id > 0) {
hasNavigationBar = rs.getBoolean(id);
}
try {
Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
Method m = systemPropertiesClass.getMethod("get", String.class);
String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
if ("1".equals(navBarOverride)) {
hasNavigationBar = false;
} else if ("0".equals(navBarOverride)) {
hasNavigationBar = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return hasNavigationBar;
}
/**
* @param context
* @return
* @brief 获取导航栏(虚拟按键高度)
*/
public static int getNavigationBarHeight(Context context) {
int navigationBarHeight = 0;
Resources rs = context.getResources();
int id = rs.getIdentifier("navigation_bar_height", "dimen", "android");
if (id > 0 && checkDeviceHasNavigationBar(context)) {
navigationBarHeight = rs.getDimensionPixelSize(id);
}
return navigationBarHeight;
}
private static DisplayMetrics dm = null;
public static int getScreenWidth(Context context) {
return getScreenWidthInPx(context);
}
public static int getScreenHeight(Context context) {
return getScreenHeightInPx(context);
}
static public DisplayMetrics getDisplayMetrics(Context context) {
if (dm == null) {
dm = context.getResources().getDisplayMetrics();
}
return dm;
}
static public int px2dp(Context context, int px) {
if (context == null) {
return px;
}
getDisplayMetrics(context);
final float density = dm.density;
return (int) (px / density + 0.5f);
}
static public int dp2px(Context context, float dp) {
if (context == null) {
return (int) dp;
}
getDisplayMetrics(context);
final float density = dm.density;
return (int) (dp * density + 0.5f);
}
static public int px2sp(Context context, float px) {
if (context == null) {
return (int) px;
}
getDisplayMetrics(context);
return (int) (px / dm.scaledDensity + 0.5f);
}
static public int sp2px(Context context, float sp) {
if (context == null) {
return (int) sp;
}
getDisplayMetrics(context);
return (int) (sp * dm.scaledDensity + 0.5f);
}
static public int getScreenWidthInPx(Context context) {
getDisplayMetrics(context);
return dm.widthPixels;
}
static public int getScreenHeightInPx(Context context) {
getDisplayMetrics(context);
return dm.heightPixels;
}
static public int getScreenWidthInDp(Context context) {
getDisplayMetrics(context);
return (int) ((float) dm.widthPixels * (160 / dm.xdpi));
}
static public int getScreenHeightInDp(Context context) {
getDisplayMetrics(context);
int screenHeight = dm.heightPixels;
return (int) ((float) screenHeight / dm.density);
}
static public float getDensity(Context context) {
getDisplayMetrics(context);
return dm.density;
}
public static int getScreenTitleBarHeight(Context context) {
Rect rect = new Rect();
((Activity) context).getWindow().getDecorView()
.getWindowVisibleDisplayFrame(rect);
return rect.top;
}
}
... ...
package com.mang.xdy.demo.utils;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.StringRes;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import android.content.Context;
import android.content.res.Resources;
import android.support.annotation.StringRes;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @version 1.0
* @file ResUtil.java
* @brief 封装了获取资源的一些方法,方便的获得字符串,颜色等资源
* @date 2017/6/4
* Copyright (c) 2017
* All rights reserved.
*/
public class ResUtil {
private static Context ctx;
private ResUtil() {
}
public static void init(Context cc) {
ctx = cc;
}
public static ResUtil get() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final ResUtil INSTANCE = new ResUtil();
}
/**
* @return Resources
* @brief 获得当前APP的Resource的方法
*/
public static Resources getResource() {
return ctx.getResources();
}
/**
* 获取字符串
* @param stringId
* @return
*/
public String getString(@StringRes int stringId) {
return getResource().getString(stringId);
}
/**
* 获取字符串,带格式化方法
* @param stringId
* @param formatArgs
* @return
*/
public String getString(int stringId, Object... formatArgs) {
return getResource().getString(stringId, formatArgs);
}
/**
* 获取Dimen值对应的像素值
* @param dimenId
* @return
*/
public int getDimenPixel(int dimenId) {
return getResource().getDimensionPixelOffset(dimenId);
}
/**
* 获取颜色
* @param colorId
* @return
*/
public int getColor(int colorId) {
return getResource().getColor(colorId);
}
/**
* 获取资产中的字符串
* @param fileName
* @return
*/
public String getStringFromAssert(String fileName) {
InputStream in = null;
try {
in = getResource().getAssets().open(fileName);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
String line = null;
StringBuilder sb = new StringBuilder();
do {
line = bufferedReader.readLine();
if (line != null) {
sb.append(line);
}
} while (line != null);
bufferedReader.close();
in.close();
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
return null;
}
}
... ...
package com.mang.xdy.demo.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.bean.AnnotaionEntity;
import com.mang.xdy.demo.bean.PointGroupEntity;
import com.mang.xdy.demo.bean.PointXY;
import com.mang.xdy.demo.utils.DisplayUtil;
import com.mang.xdy.demo.utils.ResUtil;
import com.mang.xdy.utils.XdyLogUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Created by Admin on 2017/3/25.
*/
public class CanvasView extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener {
private static final int NONE = 0;// 原始
private static final int DRAG = 1;// 拖动
private static final int ZOOM = 2;// 放大
private int mStatus = NONE;
private static final float MAX_ZOOM_SCALE = 4.0f;
private static final float MIN_ZOOM_SCALE = 1.0f;
private static final float FLOAT_TYPE = 1.0f;
private float mCurrentMaxScale = MAX_ZOOM_SCALE;
private float mCurrentScale = 1.0f;
// 第一个Rect 代表要绘制的bitmap 区域,第二个 Rect 代表的是要将bitmap 绘制在屏幕的什么地方
private Rect mRectSrc = new Rect(); // used for render image.
private Rect mRectDes = new Rect(); // used for store size of monitor.
private int mCenterX, mCenterY;
int mSurfaceHeight, mSurfaceWidth, mImageHeight, mImageWidth;
private PointF mStartPoint = new PointF();
private float mStartDistance = 0f;
private Bitmap mBitmap;
private int screenWidth;
private int currentTop;
private boolean adjust;
/**
* 图片在拖动后的偏移量
*/
private int currentOffsetY;
private void initRect() {
mCurrentMaxScale = Math.max(
MIN_ZOOM_SCALE,
4 * Math.min(FLOAT_TYPE * mImageHeight / mSurfaceHeight, 1.0f
* mImageWidth / mSurfaceWidth));
mCurrentScale = MIN_ZOOM_SCALE;
//最大的缩放比例为图片宽度与屏幕宽度的比例,就是不能缩放
mCurrentScale = mCurrentMaxScale = (FLOAT_TYPE * screenWidth) / (FLOAT_TYPE * mImageWidth);
mCenterX = mImageWidth / 2;
mCenterY = mImageHeight / 2;
calcRect();
}
private void adjustCenter() {
int w = mRectSrc.right - mRectSrc.left;
int h = mRectSrc.bottom - mRectSrc.top;
if (mCenterX - w / 2 < 0) {
mCenterX = w / 2;
mRectSrc.left = 0;
mRectSrc.right = w;
} else if (mCenterX + w / 2 >= mImageWidth) {
mCenterX = mImageWidth - w / 2;
mRectSrc.right = mImageWidth;
mRectSrc.left = mRectSrc.right - w;
} else {
mRectSrc.left = mCenterX - w / 2;
mRectSrc.right = mRectSrc.left + w;
}
if (mCenterY - h / 2 < 0) {
mCenterY = h / 2;
mRectSrc.top = 0;
mRectSrc.bottom = h;
} else if (mCenterY + h / 2 >= mImageHeight) {
mCenterY = mImageHeight - h / 2;
mRectSrc.bottom = mImageHeight;
mRectSrc.top = mRectSrc.bottom - h;
} else {
mRectSrc.top = mCenterY - h / 2;
mRectSrc.bottom = mRectSrc.top + h;
}
}
private int finalWidth;
private int finalHeight;
private void calcRect() {
int w, h;
float scaleRatio = ((FLOAT_TYPE * mSurfaceWidth) / (FLOAT_TYPE * mImageWidth));
finalWidth = w = mSurfaceWidth;
finalHeight = h = (int) (mImageHeight * scaleRatio);
if (adjust) {
if (finalHeight < mSurfaceHeight && mImageHeight != 0) {
//比surfaceview高度要小,则放到中间显示
int top = 0;
if ((top = (int) ((mSurfaceHeight - finalHeight) / 2 + 0.5f)) != currentTop) {//重新设置path坐标
currentTop = top;
pathLists.clear();
this.historyPointer = 0;
for (List<PointGroupEntity> pointGroupEntities : originPoint) {
// Path path = new Path();
// path.addCircle(pointGroupEntities.get(0).w / 100 * finalWidth, pointGroupEntities.get(0).h / 100 * finalWidth + currentTop, annotations.get(0).thickness, Path.Direction.CW);
// pathLists.add(path);
pathLists.add(createPath(pointGroupEntities.get(0).w / 100 * finalWidth, pointGroupEntities.get(0).h / 100 * finalWidth + currentTop));
this.historyPointer++;
for (int j = 0; j < pointGroupEntities.size(); j++) {
PointGroupEntity pointGroupEntity = pointGroupEntities.get(j);
Path p = this.getCurrentPath();
// p.addCircle(pointGroupEntity.w / 100 * finalWidth, pointGroupEntity.h / 100 * finalWidth + currentTop, annotations.get(0).thickness, Path.Direction.CW);
p.lineTo(pointGroupEntity.w / 100 * finalWidth, pointGroupEntity.h / 100 * finalWidth + currentTop);
}
}
}
mRectDes.left = 0;
mRectDes.top = currentTop;
mRectDes.right = w;
mRectDes.bottom = h + currentTop;
} else {
mRectDes.left = 0;
mRectDes.top = 0;
mRectDes.right = w;
mRectDes.bottom = h;
}
mCenterX = w / 2;
mCenterY = h / 2;
mRectSrc.left = 0;
mRectSrc.top = 0;
mRectSrc.right = mImageWidth;
mRectSrc.bottom = mImageHeight;
} else {
mRectSrc.left = 0;
mRectSrc.top = 0;
mRectSrc.right = mImageWidth;
mRectSrc.bottom = mImageHeight;
mRectDes.left = (mSurfaceWidth - mImageWidth) / 2;
mRectDes.top = (mSurfaceHeight - mImageHeight) / 2;
mRectDes.right = (mSurfaceWidth - mImageWidth) / 2 + mImageWidth;
mRectDes.bottom = (mSurfaceHeight - mImageHeight) / 2 + mImageHeight;
}
}
public void setMaxZoom(float value) {
mCurrentMaxScale = value;
}
public void setBitmap(Bitmap b, boolean adjust) {
//重置数据
finalHeight = 0;
finalWidth = 0;
currentTop = 0;
currentOffsetY = 0;
this.adjust = adjust;
if (b == null) {
return;
}
synchronized (CanvasView.class) {
mBitmap = b;
if (mImageHeight != mBitmap.getHeight()
|| mImageWidth != mBitmap.getWidth()) {
mImageWidth = mBitmap.getWidth();
mImageHeight = mBitmap.getHeight();
}
calcRect();
drawSurface();
}
}
private void dragAction(MotionEvent event) {
synchronized (CanvasView.class) {
PointF currentPoint = new PointF();
currentPoint.set(event.getX(), event.getY());
int offsetX = (int) currentPoint.x - (int) mStartPoint.x;
int offsetY = (int) currentPoint.y - (int) mStartPoint.y;
mStartPoint = currentPoint;
mCenterX -= offsetX;
mCenterY -= offsetY;
if (adjust) {
if (finalHeight > mSurfaceHeight) {
int tempTop = mRectDes.top + offsetY;
int deltaTop = 0;
if (tempTop < mSurfaceHeight - finalHeight) {//过头了
deltaTop = Math.abs(tempTop) - Math.abs(mSurfaceHeight - finalHeight);//超过的范围,用正整数表达易于理解
mRectDes.top += (offsetY + deltaTop);
mRectDes.bottom += (offsetY + deltaTop);
adjustPath(offsetY + deltaTop);
} else if (tempTop > 0) {
mRectDes.top += (offsetY - tempTop);
mRectDes.bottom += (offsetY - tempTop);
adjustPath(offsetY - tempTop);
} else {
mRectDes.top += offsetY;
mRectDes.bottom += offsetY;
adjustPath(offsetY);
}
}
drawSurface();
}
}
}
private void zoomAcition(MotionEvent event) {
synchronized (CanvasView.class) {
float newDist = spacing(event);
float scale = newDist / mStartDistance;
mStartDistance = newDist;
mCurrentScale *= scale;
mCurrentScale = Math.max(FLOAT_TYPE,
Math.min(mCurrentScale, mCurrentMaxScale));
calcRect();
adjustCenter();
drawSurface();
}
}
private void adjustPath(int offsetY) {
currentOffsetY += offsetY;
pathLists.clear();
historyPointer = 0;
//提取原始坐标点
for (int i = 0; i < operatePoints.size(); i++) {
List<PointGroupEntity> pointGroupEntities = operatePoints.get(i);
//创建一个path并且重新设置七点
float w = pointGroupEntities.get(0).w;
float h = pointGroupEntities.get(0).h + (FLOAT_TYPE * offsetY) / (FLOAT_TYPE * finalWidth) * 100f;
pointGroupEntities.get(0).h = h;
// Path p = new Path();
// p.addCircle(w / 100f * finalWidth, h / 100f * finalWidth, annotations.get(0).thickness, Path.Direction.CW);
// pathLists.add(p);
pathLists.add(createPath(w / 100f * finalWidth, h / 100f * finalWidth));
historyPointer++;
for (int j = 1; j < pointGroupEntities.size(); j++) {
PointGroupEntity pointGroupEntity = pointGroupEntities.get(j);
Path path = this.getCurrentPath();
float w2 = pointGroupEntity.w;
float h2 = pointGroupEntity.h + (FLOAT_TYPE * offsetY) / (FLOAT_TYPE * finalWidth) * 100f;
pointGroupEntity.h = h2;
path.lineTo(w2 / 100 * finalWidth, h2 / 100 * finalWidth);
// path.addCircle(w2 / 100 * finalWidth, h2 / 100 * finalWidth, annotations.get(0).thickness, Path.Direction.CW);
}
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mStartPoint.set(event.getX(), event.getY());
mStatus = DRAG;
break;
// case MotionEvent.ACTION_POINTER_DOWN:
// float distance = spacing(event);
// if (distance > 10f) {
//
// mStatus = ZOOM;
// mStartDistance = distance;
// }
//
// break;
case MotionEvent.ACTION_MOVE:
if (mStatus == DRAG) {
dragAction(event);
} else {
if (event.getPointerCount() == 1)
return true;
zoomAcition(event);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mStatus = NONE;
break;
default:
break;
}
return true;
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
///=================END=================
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
boolean isFirst = true;
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i("surfaceview", "change" + "width:" + width + "height:" + height);
synchronized (CanvasView.class) {
mSurfaceHeight = height;
mSurfaceWidth = width;
currentOffsetY = 0;
calcRect();
operatePoints.clear();
//重置为最原始坐标
for (List<PointGroupEntity> pointGroupEntities : originPoint) {
List<PointGroupEntity> lists = new ArrayList<>();
for (PointGroupEntity pointXy : pointGroupEntities) {
PointGroupEntity pointGroupEntity = new PointGroupEntity();
pointGroupEntity.w = pointXy.w;
pointGroupEntity.h = pointXy.h;
lists.add(pointGroupEntity);
}
operatePoints.add(lists);
}
pathLists.clear();
historyPointer = 0;
for (List<PointGroupEntity> pointGroupEntities : operatePoints) {
// Path p = new Path();
// p.addCircle(pointGroupEntities.get(0).w / 100f * finalWidth, pointGroupEntities.get(0).h / 100f * finalWidth, annotations.get(0).thickness, Path.Direction.CW);
// pathLists.add(p);
pathLists.add(createPath(pointGroupEntities.get(0).w / 100 * finalWidth, pointGroupEntities.get(0).h / 100 * finalWidth + currentTop));
historyPointer++;
for (int i = 1; i < pointGroupEntities.size(); i++) {
PointGroupEntity pointGroupEntity = pointGroupEntities.get(i);
Path path = this.getCurrentPath();
path.lineTo(pointGroupEntity.w / 100 * finalWidth, pointGroupEntity.h / 100 * finalWidth + currentTop);
// path.addCircle(pointGroupEntity.w / 100 * finalWidth, pointGroupEntity.h / 100 * finalWidth, annotations.get(0).thickness, Path.Direction.CW);
}
}
if (mBitmap != null) {
drawSurface();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
// Enumeration for Drawer
public enum Drawer {
PEN,
LINE,
RECTANGLE,
CIRCLE,
ELLIPSE,
QUADRATIC_BEZIER,
QUBIC_BEZIER;
}
private SurfaceHolder holder = null; //控制对象
/**
* 记录最原始的数据
*/
private List<AnnotaionEntity> annotations = new ArrayList<>();
private List<List<PointGroupEntity>> originPoint = new ArrayList<>();
private List<List<PointGroupEntity>> operatePoints = new ArrayList<>();
private List<Path> pathLists = new ArrayList<Path>();
private List<Paint> paintLists = new ArrayList<Paint>();
private final Paint emptyPaint = new Paint();
// for Eraser
private int baseColor = Color.TRANSPARENT;
// for Undo, Redo
private int historyPointer = 0;
private Drawer drawer = Drawer.PEN;
// for Paint
private Paint.Style paintStyle = Paint.Style.STROKE;
private int paintStrokeColor = Color.BLACK;
private int paintFillColor = Color.BLACK;
private float paintStrokeWidth = 3F;///设置线宽
private int opacity = 255;
private float blur = 0F;
private Paint.Cap lineCap = Paint.Cap.ROUND;//笔触风格
private PathEffect drawPathEffect = null;
// for Drawer
private float startX = 0F;
private float startY = 0F;
public CanvasView(Context context) {
super(context);
init();
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* Common initialization.
*/
private void init() {
holder = getHolder();
holder.addCallback(this);
this.setOnTouchListener(this);
// 设置背景为透明 否则是黑色
this.setZOrderOnTop(true);
// this.setZOrderMediaOverlay(true);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
screenWidth = DisplayUtil.getScreenWidth(getContext());
}
/**
* This method creates the instance of Paint.
* In addition, this method sets styles for Paint.
* @param color
* @return paint This is returned as the instance of Paint
*/
private Paint createPaint(int color, int thickness) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(this.paintStyle);
paint.setStrokeWidth(thickness);///设置线宽
paint.setStrokeCap(this.lineCap);
paint.setStrokeJoin(Paint.Join.ROUND); // fixed
// Otherwise
paint.setColor(color);
paint.setShadowLayer(this.blur, 0F, 0F, this.paintStrokeColor);
paint.setAlpha(this.opacity);
paint.setPathEffect(this.drawPathEffect);
return paint;
}
/**
* This method initialize Path.
* Namely, this method creates the instance of Path,
* and moves current position.
* @return path This is returned as the instance of Path
*/
private Path createPath(float x, float y) {
Path path = new Path();
// Save for ACTION_MOVE
this.startX = x;
this.startY = y;
path.rMoveTo(this.startX, this.startY); // 移动的起点坐标
return path;
}
/**
* This method gets the instance of Path that pointer indicates.
* @return the instance of Path
*/
private Path getCurrentPath() {
return this.pathLists.get(this.historyPointer - 1);
}
/**
* This method is setter for drawer.
* @param drawer
*/
public void setDrawer(Drawer drawer) {
this.drawer = drawer;
}
/**
* 知道想x,yd的坐标绘制线
* @param annotations
*/
public void drawLine(List<AnnotaionEntity> annotations) {
this.annotations.addAll(annotations);
for (AnnotaionEntity annotation : annotations) {
List<PointGroupEntity> pointXies = annotation.pointGroup;
int color = Color.parseColor(annotation.color);
setPaintFillColor(color);
copyArr(pointXies);
for (PointGroupEntity pointXy : pointXies) {
float w = pointXy.w;
float h = pointXy.h + (FLOAT_TYPE * currentOffsetY) / (FLOAT_TYPE * finalWidth) * 100f;
pointXy.h = h;
}
//操作一下這個點
operatePoints.add(pointXies);
// Path path = new Path();
// path.addCircle(pointXies.get(0).w / 100 * finalWidth, pointXies.get(0).h / 100 * finalWidth + currentTop, annotations.get(0).thickness, Path.Direction.CW);
// pathLists.add(path);
pathLists.add(createPath(pointXies.get(0).w / 100 * finalWidth, pointXies.get(0).h / 100 * finalWidth + currentTop));
paintLists.add(this.createPaint(color, annotation.thickness * 2));
this.historyPointer++;
for (int i = 0; i < pointXies.size(); i++) {
Path path = this.getCurrentPath();
// p.addCircle(pointXies.get(i).w / 100 * finalWidth, pointXies.get(i).h / 100 * finalWidth + currentTop, annotation.thickness, Path.Direction.CW);
path.lineTo(pointXies.get(i).w / 100 * finalWidth, pointXies.get(i).h / 100 * finalWidth + currentTop);
}
}
drawSurface();//获取到一个坐标就刷新下界面
}
private void copyArr(List<PointGroupEntity> pointXies) {
List<PointGroupEntity> lists = new ArrayList<>();
for (PointGroupEntity pointXy : pointXies) {
PointGroupEntity pointGroupEntity = new PointGroupEntity();
pointGroupEntity.w = pointXy.w;
pointGroupEntity.h = pointXy.h;
lists.add(pointGroupEntity);
}
originPoint.add(lists);
}
public void drawRect(List<PointXY> pointXies) {
Path path = this.getCurrentPath();
path.reset();
float startX = pointXies.get(0).x;
float startY = pointXies.get(0).y;
for (int i = 0; i < pointXies.size(); i++) {
float left = Math.min(startX, pointXies.get(i).x);
float right = Math.max(startX, pointXies.get(i).x);
float top = Math.min(startY, pointXies.get(i).y);
float bottom = Math.max(startY, pointXies.get(i).y);
path.addRect(left, top, right, bottom, Path.Direction.CCW);
invalidate();
}
}
//刷新界面 相当于View里面的 invalidate();
protected void drawSurface() {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
//draw bitmap
if (canvas != null && mBitmap != null) {
canvas.drawColor(ResUtil.get().getColor(R.color.home_background));
canvas.drawBitmap(mBitmap, mRectSrc, mRectDes, null);
for (int i = 0; i < this.historyPointer; i++) {
Path path = this.pathLists.get(i);
Paint paint = this.paintLists.get(i);
canvas.drawPath(path, paint);
}
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
/**
* 设置画笔的颜色
* @param color
*/
public void setPaintFillColor(int color) {
this.paintFillColor = color;
}
/**
* This method initializes canvas.
* @return
*/
public void clear() {
originPoint.clear();
operatePoints.clear();
this.pathLists.clear();
this.paintLists.clear();
historyPointer = 0;
}
/**
* 撤销
*/
public void redo() {
if (pathLists.size() > 0) {
Iterator<List<PointGroupEntity>> pointiterator = operatePoints.iterator();
while (pointiterator.hasNext()) {
List<PointGroupEntity> next = pointiterator.next();
if (next == operatePoints.get(operatePoints.size() - 1)) {
pointiterator.remove();
}
}
Iterator<Path> pathiterator = pathLists.iterator();
while (pathiterator.hasNext()) {
Path next = pathiterator.next();
if (next == pathLists.get(pathLists.size() - 1)) {
historyPointer--;
pathiterator.remove();
}
}
Iterator<Paint> paintiterator = paintLists.iterator();
while (paintiterator.hasNext()) {
Paint next = paintiterator.next();
if (next == paintLists.get(paintLists.size() - 1)) {
paintiterator.remove();
}
}
drawSurface();
}
}
public List<PointGroupEntity> getData() {
List<PointGroupEntity> pointXies = new ArrayList<>();
PointGroupEntity xy = new PointGroupEntity();
xy.w = 127.0f;
xy.h = 377.0f;
pointXies.add(xy);
PointGroupEntity wh1 = new PointGroupEntity();
wh1.w = 145.40204f;
wh1.h = 386.0f;
pointXies.add(wh1);
PointGroupEntity wh2 = new PointGroupEntity();
wh2.w = 148.0f;
wh2.h = 386.0f;
pointXies.add(wh2);
PointGroupEntity wh3 = new PointGroupEntity();
wh3.w = 151.875f;
wh3.h = 386.0f;
pointXies.add(wh3);
PointGroupEntity wh4 = new PointGroupEntity();
wh4.w = 156.41933f;
wh4.h = 386.0f;
pointXies.add(wh4);
PointGroupEntity wh5 = new PointGroupEntity();
wh5.w = 163.03827f;
wh5.h = 386.0f;
pointXies.add(wh5);
PointGroupEntity wh6 = new PointGroupEntity();
wh6.w = 171.26802f;
wh6.h = 378.28864f;
pointXies.add(wh6);
PointGroupEntity wh7 = new PointGroupEntity();
wh7.w = 178.50021f;
wh7.h = 375.79993f;
pointXies.add(wh7);
PointGroupEntity wh8 = new PointGroupEntity();
wh8.w = 186.9014f;
wh8.h = 374.51642f;
pointXies.add(wh8);
PointGroupEntity wh9 = new PointGroupEntity();
wh9.w = 191.49982f;
wh9.h = 373.12506f;
pointXies.add(wh9);
PointGroupEntity wh0 = new PointGroupEntity();
wh0.w = 194.86517f;
wh0.h = 372.04492f;
pointXies.add(wh0);
PointGroupEntity wh11 = new PointGroupEntity();
wh11.w = 197.6098f;
wh11.h = 372.0f;
pointXies.add(wh11);
return pointXies;
}
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.chat;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.mang.xdy.demo.R;
import org.kymjs.kjframe.ui.SupportFragment;
/**
* 聊天键盘功能界面
*
* @author kymjs (http://www.kymjs.com/) on 7/6/15.
*/
public class ChatFunctionFragment extends SupportFragment {
private LinearLayout layout1;
private LinearLayout layout2;
private OnOperationListener listener;
@Override
protected View inflaterView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle) {
View view = View.inflate(getActivity(), R.layout.home_chat_item_menu, null);
return view;
}
@Override
protected void initWidget(View parentView) {
super.initWidget(parentView);
layout1 = (LinearLayout) parentView.findViewById(R.id.chat_menu_images);
layout2 = (LinearLayout) parentView.findViewById(R.id.chat_menu_photo);
layout1.setOnClickListener(this);
layout2.setOnClickListener(this);
}
public void setOnOperationListener(OnOperationListener onOperationListener) {
this.listener = onOperationListener;
}
@Override
protected void widgetClick(View v) {
super.widgetClick(v);
if (v == layout1) {
clickMenu(0);
} else if (v == layout2) {
clickMenu(1);
}
}
private void clickMenu(int i) {
if (listener != null) {
listener.selectedFunction(i);
}
}
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.chat;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.FrameLayout.LayoutParams;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.adapter.FaceAdapter;
import com.mang.xdy.demo.bean.Faceicon;
import org.kymjs.kjframe.ui.SupportFragment;
import org.kymjs.kjframe.utils.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 表情分类中每个分类的具体显示
*
* @author kymjs (http://www.kymjs.com/)
*/
public class FacePageFragment extends SupportFragment {
public static final String FACE_FOLDER_PATH = "face_folder_path";
private static final int ITEM_PAGE_COUNT = 12;
private ViewPager mPagerFace;
private LinearLayout pagePointLayout;
private Activity aty;
private GridView[] allPageViews;
private RadioButton[] pointViews;
private OnOperationListener listener;
//当前fragment(一个表情分类)所包含的全部表情
private List<Faceicon> datas;
@Override
protected View inflaterView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle) {
aty = getActivity();
View rootView = layoutInflater.inflate(R.layout.home_chat_frag_face, null);
return rootView;
}
@Override
protected void initData() {
super.initData();
String folderPath = getArguments().getString(FACE_FOLDER_PATH);
if (StringUtils.isEmpty(folderPath)) {
folderPath = "";
Log.e("kymjs", getClass().getSimpleName() + " line 69, folder path is empty");
}
File folder = new File(folderPath);
if (folder.isDirectory()) {
File[] faceFiles = folder.listFiles();
datas = new ArrayList<>(faceFiles.length);
for (File faceFile : faceFiles) {
if (!faceFile.isHidden()) {
Faceicon data = new Faceicon();
data.setName("http://www.oschina.net/image/" + faceFile.getName());
data.setFileName(faceFile.getName());
data.setPath(faceFile.getAbsolutePath());
datas.add(data);
}
}
} else {
datas = new ArrayList<>(0);
}
}
@Override
protected void initWidget(View rootView) {
super.initWidget(rootView);
mPagerFace = (ViewPager) rootView.findViewById(R.id.frag_pager_face);
pagePointLayout = (LinearLayout) rootView.findViewById(R.id.frag_point);
int total = datas.size();
int pages = total / ITEM_PAGE_COUNT
+ (total % ITEM_PAGE_COUNT == 0 ? 0 : 1);
allPageViews = new GridView[pages];
pointViews = new RadioButton[pages];
for (int x = 0; x < pages; x++) {
int start = x * ITEM_PAGE_COUNT;
int end = (start + ITEM_PAGE_COUNT) > total ? total
: (start + ITEM_PAGE_COUNT);
final List<Faceicon> itemDatas = datas.subList(start, end);
GridView view = new GridView(aty);
FaceAdapter faceAdapter = new FaceAdapter(view, itemDatas);
view.setAdapter(faceAdapter);
view.setNumColumns(4);
view.setBackgroundColor(Color.TRANSPARENT);
view.setHorizontalSpacing(1);
view.setVerticalSpacing(1);
view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
view.setCacheColorHint(0);
view.setVerticalScrollBarEnabled(false);
view.setPadding(5, 0, 5, 0);
view.setSelector(new ColorDrawable(Color.TRANSPARENT));
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
view.setGravity(Gravity.CENTER);
view.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (listener != null) {
listener.selectedFace(itemDatas.get(position));
}
}
});
allPageViews[x] = view;
RadioButton tip = new RadioButton(aty);
tip.setBackgroundResource(R.drawable.home_selector_chat_emoji_btn);
RadioGroup.LayoutParams layoutParams = new RadioGroup.LayoutParams(
8, 8);
layoutParams.leftMargin = 10;
pagePointLayout.addView(tip, layoutParams);
if (x == 0) {
tip.setChecked(true);
}
pointViews[x] = tip;
}
PagerAdapter facePagerAdapter = new FacePagerAdapter(allPageViews);
mPagerFace.setAdapter(facePagerAdapter);
mPagerFace.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
pointViews[index].setChecked(true);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
public class FacePagerAdapter extends PagerAdapter {
private final GridView[] gridViewList;
public FacePagerAdapter(GridView[] gridViewList) {
this.gridViewList = gridViewList;
}
@Override
public int getCount() {
return gridViewList.length;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView(gridViewList[arg1]);
}
@Override
public Object instantiateItem(View arg0, int arg1) {
((ViewPager) arg0).addView(gridViewList[arg1]);
return gridViewList[arg1];
}
}
public void setOnOperationListener(OnOperationListener onOperationListener) {
this.listener = onOperationListener;
}
}
\ No newline at end of file
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.chat;
import android.app.Activity;
import android.content.Context;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.adapter.FaceCategroyAdapter;
import java.util.List;
/**
* 控件主界面
*
* @author kymjs (http://www.kymjs.com/)
*/
public class KJChatKeyboard extends RelativeLayout implements
SoftKeyboardStateHelper.SoftKeyboardStateListener {
private LinearLayout mToolsBoxCover;
public interface OnToolBoxListener {
void onShowFace();
}
public static final int LAYOUT_TYPE_HIDE = 0;
public static final int LAYOUT_TYPE_FACE = 1;
public static final int LAYOUT_TYPE_MORE = 2;
/**
* 最上层输入框
*/
private EditText mEtMsg;
private CheckBox mBtnFace;
private CheckBox mBtnMore;
private ImageView mBtnSend;
/**
* 表情
*/
private ViewPager mPagerFaceCagetory;
private RelativeLayout mRlFace;
private PagerSlidingTabStrip mFaceTabs;
private int layoutType = LAYOUT_TYPE_HIDE;
private FaceCategroyAdapter adapter; //点击表情按钮时的适配器
private List<String> mFaceData;
private Context context;
private OnOperationListener listener;
private OnToolBoxListener mFaceListener;
private SoftKeyboardStateHelper mKeyboardHelper;
public KJChatKeyboard(Context context) {
super(context);
init(context);
}
public KJChatKeyboard(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public KJChatKeyboard(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
this.context = context;
View root = View.inflate(context, R.layout.home_chat_tool_box, null);
this.addView(root);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
initData();
this.initWidget();
}
private void initData() {
mKeyboardHelper = new SoftKeyboardStateHelper(((Activity) getContext())
.getWindow().getDecorView());
mKeyboardHelper.addSoftKeyboardStateListener(this);
}
private void initWidget() {
mEtMsg = (EditText) findViewById(R.id.toolbox_et_message);
mBtnSend = (ImageView) findViewById(R.id.toolbox_btn_send);
mBtnFace = (CheckBox) findViewById(R.id.toolbox_btn_face);
mBtnMore = (CheckBox) findViewById(R.id.toolbox_btn_more);
mRlFace = (RelativeLayout) findViewById(R.id.toolbox_layout_face);
mPagerFaceCagetory = (ViewPager) findViewById(R.id.toolbox_pagers_face);
mFaceTabs = (PagerSlidingTabStrip) findViewById(R.id.toolbox_tabs);
mToolsBoxCover = (LinearLayout) findViewById(R.id.ll_cover);
adapter = new FaceCategroyAdapter(((FragmentActivity) getContext())
.getSupportFragmentManager(), LAYOUT_TYPE_FACE);
mBtnSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
String content = mEtMsg.getText().toString();
listener.send(content);
mEtMsg.setText(null);
}
}
});
// 点击表情按钮
mBtnFace.setOnClickListener(getFunctionBtnListener(LAYOUT_TYPE_FACE));
// 点击表情按钮旁边的加号
mBtnMore.setOnClickListener(getFunctionBtnListener(LAYOUT_TYPE_MORE));
// 点击消息输入框
mEtMsg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hideLayout();
}
});
}
/*************************
* 内部方法 start
************************/
private OnClickListener getFunctionBtnListener(final int which) {
return new OnClickListener() {
@Override
public void onClick(View v) {
setEditTextFocus();
if (isShow() && which == layoutType) {
hideLayout();
showKeyboard(context);
} else {
changeLayout(which);
showLayout();
mBtnFace.setChecked(layoutType == LAYOUT_TYPE_FACE);
mBtnMore.setChecked(layoutType == LAYOUT_TYPE_MORE);
}
}
};
}
public void setEditTextFocus(){
if (mEtMsg!=null){
mEtMsg.setFocusable(true);
mEtMsg.setFocusableInTouchMode(true);
mEtMsg.requestFocus();
mEtMsg.findFocus();
mEtMsg.invalidate();
}
}
private void changeLayout(int mode) {
adapter = new FaceCategroyAdapter(((FragmentActivity) getContext())
.getSupportFragmentManager(), mode);
adapter.setOnOperationListener(listener);
layoutType = mode;
setFaceData(mFaceData);
}
@Override
public void onSoftKeyboardOpened(int keyboardHeightInPx) {
hideLayout();
}
@Override
public void onSoftKeyboardClosed() {
}
/***************************** 内部方法 end ******************************/
/**************************
* 可选调用的方法 start
**************************/
public void setFaceData(List<String> faceData) {
mFaceData = faceData;
adapter.refresh(faceData);
mPagerFaceCagetory.setAdapter(adapter);
mFaceTabs.setViewPager(mPagerFaceCagetory);
if (layoutType == LAYOUT_TYPE_MORE) {
mFaceTabs.setVisibility(GONE);
} else {
//加1是表示第一个分类为默认的emoji表情分类,这个分类是固定不可更改的
if (faceData.size() + 1 < 2) {
mFaceTabs.setVisibility(GONE);
} else {
mFaceTabs.setVisibility(VISIBLE);
}
}
}
public EditText getEditTextBox() {
return mEtMsg;
}
public void showLayout() {
hideKeyboard(this.context);
// 延迟一会,让键盘先隐藏再显示表情键盘,否则会有一瞬间表情键盘和软键盘同时显示
postDelayed(new Runnable() {
@Override
public void run() {
mRlFace.setVisibility(View.VISIBLE);
if (mFaceListener != null) {
mFaceListener.onShowFace();
}
}
}, 50);
}
public boolean isShow() {
return mRlFace.getVisibility() == VISIBLE;
}
public void hideLayout() {
mRlFace.setVisibility(View.GONE);
if (mBtnFace.isChecked()) {
mBtnFace.setChecked(false);
}
if (mBtnMore.isChecked()) {
mBtnMore.setChecked(false);
}
}
/**
* 隐藏软键盘
*/
public void hideKeyboard(Context context) {
Activity activity = (Activity) context;
if (activity != null) {
InputMethodManager imm = (InputMethodManager) activity
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive() && activity.getCurrentFocus() != null) {
imm.hideSoftInputFromWindow(activity.getCurrentFocus()
.getWindowToken(), 0);
}
}
}
/**
* 显示软键盘
*/
public static void showKeyboard(Context context) {
Activity activity = (Activity) context;
if (activity != null) {
InputMethodManager imm = (InputMethodManager) activity
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInputFromInputMethod(activity.getCurrentFocus()
.getWindowToken(), 0);
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
public OnOperationListener getOnOperationListener() {
return listener;
}
public void setOnOperationListener(OnOperationListener onOperationListener) {
this.listener = onOperationListener;
adapter.setOnOperationListener(onOperationListener);
}
public void setOnToolBoxListener(OnToolBoxListener mFaceListener) {
this.mFaceListener = mFaceListener;
}
public void setToolBoxIsClick(boolean b){
if (b){
if (isShow()){
hideLayout();
}
mToolsBoxCover.setVisibility(View.VISIBLE);
mToolsBoxCover.setOnClickListener(null);
}else {
mToolsBoxCover.setVisibility(View.GONE);
}
}
/*********************** 可选调用的方法 end ******************************/
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.chat;
import com.mang.xdy.demo.bean.Faceicon;
/**
* 表情栏顶部按钮的监听器
*
* @author kymjs (http://www.kymjs.com/)
*/
public interface OnOperationListener {
void send(String content);
void selectedFace(Faceicon content);
void selectedEmoji(String content);
void selectedBackSpace(String back);
void selectedFunction(int index);
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.chat;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.mang.xdy.demo.R;
import java.util.Locale;
/**
* 表情栏底部表情分类
*
* @author kymjs (http://www.kymjs.com/)
*/
public class PagerSlidingTabStrip extends HorizontalScrollView {
public interface IconTabProvider {
void setPageIcon(int position, ImageView image);
}
// @formatter:off
private static final int[] ATTRS = new int[]{android.R.attr.textSize,
android.R.attr.textColor};
// @formatter:on
private final LinearLayout.LayoutParams defaultTabLayoutParams;
private final LinearLayout.LayoutParams expandedTabLayoutParams;
private final PageListener pageListener = new PageListener();
public OnPageChangeListener delegatePageListener;
private final LinearLayout tabsContainer;
private ViewPager pager;
private int tabCount;
private int currentPosition = 0;
private float currentPositionOffset = 0f;
private final Paint rectPaint;
private final Paint dividerPaint;
private int indicatorColor = 0xFF666666;
private int underlineColor = 0x1A000000;
private int dividerColor = 0x1A000000;
private boolean shouldExpand = false;
private boolean textAllCaps = true;
private int scrollOffset = 52;
private int indicatorHeight = 8;
private int underlineHeight = 2;
private int dividerPadding = 12;
private int tabPadding = 24;
private int dividerWidth = 1;
private int tabTextSize = 12;
private int tabTextColor = 0xFF666666;
private Typeface tabTypeface = null;
private int tabTypefaceStyle = Typeface.BOLD;
private int lastScrollX = 0;
private int tabBackgroundResId = R.drawable.home_selector_tab_bg;
private Locale locale;
public PagerSlidingTabStrip(Context context) {
this(context, null);
}
public PagerSlidingTabStrip(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PagerSlidingTabStrip(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
setFillViewport(true);
setWillNotDraw(false);
tabsContainer = new LinearLayout(context);
tabsContainer.setOrientation(LinearLayout.HORIZONTAL);
tabsContainer.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(tabsContainer);
DisplayMetrics dm = getResources().getDisplayMetrics();
scrollOffset = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm);
indicatorHeight = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm);
underlineHeight = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm);
dividerPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm);
tabPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm);
dividerWidth = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm);
tabTextSize = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm);
// get system attrs (android:textSize and android:textColor)
TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
tabTextSize = a.getDimensionPixelSize(0, tabTextSize);
tabTextColor = a.getColor(1, tabTextColor);
a.recycle();
// get custom attrs
a = context.obtainStyledAttributes(attrs,
R.styleable.home_PagerSlidingTabStrip);
indicatorColor = a.getColor(
R.styleable.home_PagerSlidingTabStrip_home_pstsIndicatorColor,
indicatorColor);
underlineColor = a.getColor(
R.styleable.home_PagerSlidingTabStrip_home_pstsUnderlineColor,
underlineColor);
dividerColor = a
.getColor(R.styleable.home_PagerSlidingTabStrip_home_pstsDividerColor,
dividerColor);
indicatorHeight = a.getDimensionPixelSize(
R.styleable.home_PagerSlidingTabStrip_home_pstsIndicatorHeight,
indicatorHeight);
underlineHeight = a.getDimensionPixelSize(
R.styleable.home_PagerSlidingTabStrip_home_pstsUnderlineHeight,
underlineHeight);
dividerPadding = a.getDimensionPixelSize(
R.styleable.home_PagerSlidingTabStrip_home_pstsDividerPadding,
dividerPadding);
tabPadding = a.getDimensionPixelSize(
R.styleable.home_PagerSlidingTabStrip_home_pstsTabPaddingLeftRight,
tabPadding);
tabBackgroundResId = a.getResourceId(
R.styleable.home_PagerSlidingTabStrip_home_pstsTabBackground,
tabBackgroundResId);
shouldExpand = a
.getBoolean(R.styleable.home_PagerSlidingTabStrip_home_pstsShouldExpand,
shouldExpand);
scrollOffset = a
.getDimensionPixelSize(
R.styleable.home_PagerSlidingTabStrip_home_pstsScrollOffset,
scrollOffset);
textAllCaps = a.getBoolean(
R.styleable.home_PagerSlidingTabStrip_home_pstsTextAllCaps, textAllCaps);
a.recycle();
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStyle(Style.FILL);
dividerPaint = new Paint();
dividerPaint.setAntiAlias(true);
dividerPaint.setStrokeWidth(dividerWidth);
defaultTabLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
expandedTabLayoutParams = new LinearLayout.LayoutParams(0,
LayoutParams.MATCH_PARENT, 1.0f);
if (locale == null) {
locale = getResources().getConfiguration().locale;
}
}
public void setViewPager(ViewPager pager) {
this.pager = pager;
if (pager.getAdapter() == null) {
throw new IllegalStateException(
"ViewPager does not have adapter instance.");
}
pager.setOnPageChangeListener(pageListener);
notifyDataSetChanged();
}
public void setOnPageChangeListener(OnPageChangeListener listener) {
this.delegatePageListener = listener;
}
public void notifyDataSetChanged() {
tabsContainer.removeAllViews();
tabCount = pager.getAdapter().getCount();
for (int i = 0; i < tabCount; i++) {
if (pager.getAdapter() instanceof IconTabProvider) {
ImageView image = new ImageView(getContext());
((IconTabProvider) pager.getAdapter()).setPageIcon(i, image);
addTab(i, image);
} else {
addTextTab(i, pager.getAdapter().getPageTitle(i).toString());
}
}
updateTabStyles();
getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
getViewTreeObserver().removeGlobalOnLayoutListener(
this);
} else {
getViewTreeObserver().removeOnGlobalLayoutListener(
this);
}
currentPosition = pager.getCurrentItem();
scrollToChild(currentPosition, 0);
}
});
}
private void addTextTab(final int position, String title) {
TextView tab = new TextView(getContext());
tab.setText(title);
tab.setGravity(Gravity.CENTER);
tab.setSingleLine();
addTab(position, tab);
}
private void addTab(final int position, View tab) {
tab.setFocusable(true);
tab.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pager.setCurrentItem(position);
}
});
tab.setPadding(tabPadding, 0, tabPadding, 0);
tabsContainer
.addView(tab, position, shouldExpand ? expandedTabLayoutParams
: defaultTabLayoutParams);
}
private void updateTabStyles() {
for (int i = 0; i < tabCount; i++) {
View v = tabsContainer.getChildAt(i);
v.setBackgroundResource(tabBackgroundResId);
if (v instanceof TextView) {
TextView tab = (TextView) v;
tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
tab.setTypeface(tabTypeface, tabTypefaceStyle);
tab.setTextColor(tabTextColor);
// setAllCaps() is only available from API 14, so the upper case
// is made manually if we are on a
// pre-ICS-build
if (textAllCaps) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
tab.setAllCaps(true);
} else {
tab.setText(tab.getText().toString()
.toUpperCase(locale));
}
}
}
}
}
private void scrollToChild(int position, int offset) {
if (tabCount == 0) {
return;
}
int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset;
if (position > 0 || offset > 0) {
newScrollX -= scrollOffset;
}
if (newScrollX != lastScrollX) {
lastScrollX = newScrollX;
scrollTo(newScrollX, 0);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode() || tabCount == 0) {
return;
}
final int height = getHeight();
// draw indicator line
rectPaint.setColor(indicatorColor);
// default: line below current tab
View currentTab = tabsContainer.getChildAt(currentPosition);
float lineLeft = currentTab.getLeft();
float lineRight = currentTab.getRight();
// if there is an offset, start interpolating left and right coordinates
// between current and next tab
if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {
View nextTab = tabsContainer.getChildAt(currentPosition + 1);
final float nextTabLeft = nextTab.getLeft();
final float nextTabRight = nextTab.getRight();
lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
* lineLeft);
lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset)
* lineRight);
}
canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height,
rectPaint);
// draw underline
rectPaint.setColor(underlineColor);
canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(),
height, rectPaint);
// draw divider
dividerPaint.setColor(dividerColor);
for (int i = 0; i < tabCount - 1; i++) {
View tab = tabsContainer.getChildAt(i);
canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(),
height - dividerPadding, dividerPaint);
}
}
private class PageListener implements OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
currentPosition = position;
currentPositionOffset = positionOffset;
scrollToChild(position, (int) (positionOffset * tabsContainer
.getChildAt(position).getWidth()));
invalidate();
if (delegatePageListener != null) {
delegatePageListener.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
scrollToChild(pager.getCurrentItem(), 0);
}
if (delegatePageListener != null) {
delegatePageListener.onPageScrollStateChanged(state);
}
}
@Override
public void onPageSelected(int position) {
if (delegatePageListener != null) {
delegatePageListener.onPageSelected(position);
}
}
}
public void setIndicatorColor(int indicatorColor) {
this.indicatorColor = indicatorColor;
invalidate();
}
public void setIndicatorColorResource(int resId) {
this.indicatorColor = getResources().getColor(resId);
invalidate();
}
public int getIndicatorColor() {
return this.indicatorColor;
}
public void setIndicatorHeight(int indicatorLineHeightPx) {
this.indicatorHeight = indicatorLineHeightPx;
invalidate();
}
public int getIndicatorHeight() {
return indicatorHeight;
}
public void setUnderlineColor(int underlineColor) {
this.underlineColor = underlineColor;
invalidate();
}
public void setUnderlineColorResource(int resId) {
this.underlineColor = getResources().getColor(resId);
invalidate();
}
public int getUnderlineColor() {
return underlineColor;
}
public void setDividerColor(int dividerColor) {
this.dividerColor = dividerColor;
invalidate();
}
public void setDividerColorResource(int resId) {
this.dividerColor = getResources().getColor(resId);
invalidate();
}
public int getDividerColor() {
return dividerColor;
}
public void setUnderlineHeight(int underlineHeightPx) {
this.underlineHeight = underlineHeightPx;
invalidate();
}
public int getUnderlineHeight() {
return underlineHeight;
}
public void setDividerPadding(int dividerPaddingPx) {
this.dividerPadding = dividerPaddingPx;
invalidate();
}
public int getDividerPadding() {
return dividerPadding;
}
public void setScrollOffset(int scrollOffsetPx) {
this.scrollOffset = scrollOffsetPx;
invalidate();
}
public int getScrollOffset() {
return scrollOffset;
}
public void setShouldExpand(boolean shouldExpand) {
this.shouldExpand = shouldExpand;
requestLayout();
}
public boolean getShouldExpand() {
return shouldExpand;
}
public boolean isTextAllCaps() {
return textAllCaps;
}
public void setAllCaps(boolean textAllCaps) {
this.textAllCaps = textAllCaps;
}
public void setTextSize(int textSizePx) {
this.tabTextSize = textSizePx;
updateTabStyles();
}
public int getTextSize() {
return tabTextSize;
}
public void setTextColor(int textColor) {
this.tabTextColor = textColor;
updateTabStyles();
}
public void setTextColorResource(int resId) {
this.tabTextColor = getResources().getColor(resId);
updateTabStyles();
}
public int getTextColor() {
return tabTextColor;
}
public void setTypeface(Typeface typeface, int style) {
this.tabTypeface = typeface;
this.tabTypefaceStyle = style;
updateTabStyles();
}
public void setTabBackground(int resId) {
this.tabBackgroundResId = resId;
}
public int getTabBackground() {
return tabBackgroundResId;
}
public void setTabPaddingLeftRight(int paddingPx) {
this.tabPadding = paddingPx;
updateTabStyles();
}
public int getTabPaddingLeftRight() {
return tabPadding;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
currentPosition = savedState.currentPosition;
requestLayout();
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPosition = currentPosition;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPosition;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPosition = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPosition);
}
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.chat;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import java.util.LinkedList;
import java.util.List;
/**
* 软键盘监听器助手
*
* @author kymjs (http://www.kymjs.com)
*/
public class SoftKeyboardStateHelper implements
ViewTreeObserver.OnGlobalLayoutListener {
public interface SoftKeyboardStateListener {
void onSoftKeyboardOpened(int keyboardHeightInPx);
void onSoftKeyboardClosed();
}
private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
private final View activityRootView;
private int lastSoftKeyboardHeightInPx;
private boolean isSoftKeyboardOpened;
public SoftKeyboardStateHelper(View activityRootView) {
this(activityRootView, false);
}
public SoftKeyboardStateHelper(View activityRootView,
boolean isSoftKeyboardOpened) {
this.activityRootView = activityRootView;
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override
public void onGlobalLayout() {
final Rect r = new Rect();
// r will be populated with the coordinates of your view that area still
// visible.
activityRootView.getWindowVisibleDisplayFrame(r);
final int heightDiff = activityRootView.getRootView().getHeight()
- (r.bottom - r.top);
if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100
// pixels, its probably
// a keyboard...
isSoftKeyboardOpened = true;
notifyOnSoftKeyboardOpened(heightDiff);
} else if (isSoftKeyboardOpened && heightDiff < 100) {
isSoftKeyboardOpened = false;
notifyOnSoftKeyboardClosed();
}
}
public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
}
public boolean isSoftKeyboardOpened() {
return isSoftKeyboardOpened;
}
/**
* Default value is zero (0)
*
* @return last saved keyboard height in px
*/
public int getLastSoftKeyboardHeightInPx() {
return lastSoftKeyboardHeightInPx;
}
public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.add(listener);
}
public void removeSoftKeyboardStateListener(
SoftKeyboardStateListener listener) {
listeners.remove(listener);
}
private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardOpened(keyboardHeightInPx);
}
}
}
private void notifyOnSoftKeyboardClosed() {
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardClosed();
}
}
}
}
... ...
package com.mang.xdy.demo.widget.chat;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.provider.Browser;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.view.View;
import android.widget.TextView;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 各种链接跳转样式
*
* @author kymjs (http://www.kymjs.com/) on 8/10/15.
*/
public class UrlUtils {
/**
* 让TextView自动解析URL并高亮设置点击链接(链接不支持中文)
* Note:深深的体会到,写一个正则不容易啊,Android居然还不支持POSIX字符
* <p/>
* Created by kymjs(www.kymjs.com) on 8/5/15.
*
* @param tv TextView
* @param content 要高亮的内容
* @return 已经解析之后的TextView
*/
public static TextView handleText(TextView tv, String content) {
SpannableStringBuilder sp = new SpannableStringBuilder(content);
//又碰上一个坑,在Android中的\p{Alnum}和Java中的\p{Alnum}不是同一个值,非得要我换成[a-zA-Z0-9]才行
Pattern pattern = Pattern.compile("(http|https|ftp|svn)://([a-zA-Z0-9]+[/?.?])" +
"+[a-zA-Z0-9]*\\??([a-zA-Z0-9]*=[a-zA-Z0-9]*&?)*");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
String url = matcher.group();
int start = content.indexOf(url);
if (start >= 0) {
int end = start + url.length();
sp.setSpan(new URLSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sp.setSpan(getClickableSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
tv.setText(sp);
tv.setMovementMethod(LinkMovementMethod.getInstance());
return tv;
}
/**
* 处理html数据的高亮与响应
*
* @param tv
* @param content
* @return
*/
public static TextView handleHtmlText(TextView tv, String content) {
SpannableStringBuilder sp = new SpannableStringBuilder(Html.fromHtml(content));
URLSpan[] urlSpans = sp.getSpans(0, sp.length(), URLSpan.class);
for (final URLSpan span : urlSpans) {
int start = sp.getSpanStart(span);
int end = sp.getSpanEnd(span);
sp.setSpan(getClickableSpan(span.getURL()), start, end, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
}
tv.setText(sp);
tv.setMovementMethod(LinkMovementMethod.getInstance());
return tv;
}
/**
* 设置链接跳转与高亮样式
*
* @param url
* @return
*/
private static ClickableSpan getClickableSpan(final String url) {
return new ClickableSpan() {
@Override
public void onClick(View widget) {
Uri uri = Uri.parse(url);
Context context = widget.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
context.startActivity(intent);
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(Color.BLUE);
ds.setUnderlineText(false);
}
};
}
}
... ...
package com.mang.xdy.demo.widget.emoji;
import android.view.KeyEvent;
import android.widget.EditText;
import java.util.ArrayList;
import java.util.List;
/**
* emoji显示规则
*
* @author kymjs (http://www.kymjs.com/) on 6/8/15.
*/
public enum DisplayRules {
KJEMOJI0("[微笑]", 0xF0, 0x9F, 0x98, 0x81),
KJEMOJI1("[微笑]", 0xF0, 0x9F, 0x98, 0x82),
KJEMOJI2("[微笑]", 0xF0, 0x9F, 0x98, 0x83),
KJEMOJI3("[微笑]", 0xF0, 0x9F, 0x98, 0x84),
KJEMOJI4("[微笑]", 0xF0, 0x9F, 0x98, 0x85),
KJEMOJI5("[微笑]", 0xF0, 0x9F, 0x98, 0x86),
KJEMOJI6("[微笑]", 0xF0, 0x9F, 0x98, 0x89),
KJEMOJI7("[微笑]", 0xF0, 0x9F, 0x98, 0x8A),
KJEMOJI8("[微笑]", 0xF0, 0x9F, 0x98, 0x8B),
KJEMOJI9("[微笑]", 0xF0, 0x9F, 0x98, 0x8C),
KJEMOJI10("[微笑]", 0xF0, 0x9F, 0x98, 0x8D),
KJEMOJI11("[微笑]", 0xF0, 0x9F, 0x98, 0x8F),
KJEMOJI12("[微笑]", 0xF0, 0x9F, 0x98, 0x92),
KJEMOJI13("[微笑]", 0xF0, 0x9F, 0x98, 0x93),
KJEMOJI14("[微笑]", 0xF0, 0x9F, 0x98, 0x94),
KJEMOJI15("[微笑]", 0xF0, 0x9F, 0x98, 0x96),
KJEMOJI16("[微笑]", 0xF0, 0x9F, 0x98, 0x98),
KJEMOJI17("[微笑]", 0xF0, 0x9F, 0x98, 0x9A),
KJEMOJI18("[微笑]", 0xF0, 0x9F, 0x98, 0x9C),
KJEMOJI19("[微笑]", 0xF0, 0x9F, 0x98, 0x9D),
KJEMOJI20("[微笑]", 0xF0, 0x9F, 0x98, 0x9E),
KJEMOJI21("[微笑]", 0xF0, 0x9F, 0x98, 0xA0),
KJEMOJI22("[微笑]", 0xF0, 0x9F, 0x98, 0xA1),
KJEMOJI23("[微笑]", 0xF0, 0x9F, 0x98, 0xA2),
KJEMOJI24("[微笑]", 0xF0, 0x9F, 0x98, 0xA3),
KJEMOJI25("[微笑]", 0xF0, 0x9F, 0x98, 0xA4),
KJEMOJI26("[微笑]", 0xF0, 0x9F, 0x98, 0xA5),
BACK1("[删除]", 0xf0, 0x9f, 0x94, 0x99),
KJEMOJI27("[微笑]", 0xF0, 0x9F, 0x98, 0xA8),
KJEMOJI31("[微笑]", 0xF0, 0x9F, 0x98, 0xAD),
KJEMOJI32("[微笑]", 0xF0, 0x9F, 0x98, 0xB0),
KJEMOJI28("[微笑]", 0xF0, 0x9F, 0x98, 0xA9),
KJEMOJI29("[微笑]", 0xF0, 0x9F, 0x98, 0xAA),
KJEMOJI30("[微笑]", 0xF0, 0x9F, 0x98, 0xAB),
KJEMOJI33("[微笑]", 0xF0, 0x9F, 0x98, 0xB1),
KJEMOJI34("[微笑]", 0xF0, 0x9F, 0x98, 0xB2),
KJEMOJI35("[微笑]", 0xF0, 0x9F, 0x98, 0xB3),
KJEMOJI36("[微笑]", 0xF0, 0x9F, 0x98, 0xB5),
KJEMOJI37("[微笑]", 0xF0, 0x9F, 0x98, 0xB7),
KJEMOJI38("[微笑]", 0xF0, 0x9F, 0x98, 0x80),
KJEMOJI39("[微笑]", 0xF0, 0x9F, 0x98, 0x87),
KJEMOJI41("[微笑]", 0xF0, 0x9F, 0x98, 0x8E),
KJEMOJI42("[微笑]", 0xF0, 0x9F, 0x98, 0x90),
KJEMOJI43("[微笑]", 0xF0, 0x9F, 0x98, 0x91),
KJEMOJI44("[微笑]", 0xF0, 0x9F, 0x98, 0x95),
KJEMOJI45("[微笑]", 0xF0, 0x9F, 0x98, 0x97),
KJEMOJI46("[微笑]", 0xF0, 0x9F, 0x98, 0x99),
KJEMOJI47("[微笑]", 0xF0, 0x9F, 0x98, 0x9B),
KJEMOJI48("[微笑]", 0xF0, 0x9F, 0x98, 0x9F),
KJEMOJI49("[微笑]", 0xF0, 0x9F, 0x98, 0xA6),
KJEMOJI50("[微笑]", 0xF0, 0x9F, 0x98, 0xA7),
KJEMOJI51("[微笑]", 0xF0, 0x9F, 0x98, 0xAC),
KJEMOJI52("[微笑]", 0xF0, 0x9F, 0x98, 0xAE),
KJEMOJI53("[微笑]", 0xF0, 0x9F, 0x98, 0xAF),
KJEMOJI54("[微笑]", 0xF0, 0x9F, 0x98, 0xB4),
BACK2("[删除]", 0xf0, 0x9f, 0x94, 0x99),
KJEMOJI55("[微笑]", 0xF0, 0x9F, 0x98, 0xB6),
CAT1("[微笑]", 0xF0, 0x9F, 0x98, 0xB8),
CAT2("[微笑]", 0xF0, 0x9F, 0x98, 0xB9),
CAT3("[微笑]", 0xF0, 0x9F, 0x98, 0xBA),
CAT4("[微笑]", 0xF0, 0x9F, 0x98, 0xBB),
CAT5("[微笑]", 0xF0, 0x9F, 0x98, 0xBC),
CAT6("[微笑]", 0xF0, 0x9F, 0x98, 0xBD),
CAT7("[微笑]", 0xF0, 0x9F, 0x98, 0xBE),
CAT8("[微笑]", 0xF0, 0x9F, 0x98, 0xBF),
CAT9("[微笑]", 0xF0, 0x9F, 0x99, 0x80),
BACK3("[删除]", 0xf0, 0x9f, 0x94, 0x99);
private String emojiStr;
private byte value1;
private byte value2;
private byte value3;
private byte value4;
private byte[] value;
DisplayRules(String emojiStr, int value1, int value2, int value3, int value4) {
this.emojiStr = emojiStr;
this.value1 = (byte) value1;
this.value2 = (byte) value2;
this.value3 = (byte) value3;
this.value4 = (byte) value4;
this.value = new byte[]{
this.value1, this.value2, this.value3, this.value4
};
}
public static boolean isDeleteEmojicon(Emojicon emoji) {
if (emoji != null && emoji.getCode() != null) {
byte[] codes = emoji.getCode();
return (codes[0] == (byte) 0xf0 && codes[1] == (byte) 0x9f && codes[2] == (byte) 0x94
&& codes[3] == (byte) 0x99);
} else {
return false;
}
}
public static boolean isCustomDeleteEmojicon(String emoji) {
if (emoji != null) {
return (emoji.equals("[img:shanchu]"));
} else {
return false;
}
}
public static List<Emojicon> getAllByType() {
List<Emojicon> datas = new ArrayList<Emojicon>(values().length);
for (DisplayRules data : values()) {
Emojicon emoji = new Emojicon();
emoji.setCode(data.value);
emoji.setName(data.emojiStr);
datas.add(emoji);
}
return datas;
}
public static void backspace(EditText editText) {
if (editText == null) {
return;
}
KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0,
0, KeyEvent.KEYCODE_ENDCALL);
editText.dispatchKeyEvent(event);
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.requestFocus();
editText.findFocus();
editText.invalidate();
}
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.emoji;
import android.widget.AbsListView;
import android.widget.TextView;
import com.mang.xdy.demo.R;
import org.kymjs.kjframe.widget.AdapterHolder;
import org.kymjs.kjframe.widget.KJAdapter;
import java.util.Collection;
/**
* emoji表情界面gridview适配器
*
* @author kymjs (http://www.kymjs.com/) on 6/8/15.
*/
public class EmojiAdapter extends KJAdapter<String> {
public EmojiAdapter(AbsListView view, Collection<String> mDatas) {
super(view, mDatas, R.layout.home_chat_item_emoji);
}
@Override
public void convert(AdapterHolder adapterHolder, String emojicon, boolean b) {
TextView itemTvEmoji = adapterHolder.getView(R.id.itemEmoji);
itemTvEmoji.setText(emojicon);
}
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.emoji;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.mang.xdy.demo.R;
import com.mang.xdy.demo.widget.chat.OnOperationListener;
import org.kymjs.kjframe.ui.SupportFragment;
import java.util.List;
/**
* Emoji表情分类的显示
*
* @author kymjs (http://www.kymjs.com/) on 6/8/15.
*/
public class EmojiPageFragment extends SupportFragment {
private static final int ITEM_PAGE_COUNT = 28;
private ViewPager mPagerFace;
private LinearLayout pagePointLayout;
private Activity aty;
private GridView[] allPageViews;
private RadioButton[] pointViews;
private OnOperationListener listener;
private List<String> datas;
@Override
protected View inflaterView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle) {
aty = getActivity();
View rootView = layoutInflater.inflate(R.layout.home_chat_frag_face, null);
return rootView;
}
@Override
protected void initData() {
super.initData();
datas=EmojiconHandler.mEmoticons;
// datas = DisplayRules.getAllByType();
}
@Override
protected void initWidget(View rootView) {
mPagerFace = (ViewPager) rootView.findViewById(R.id.frag_pager_face);
pagePointLayout = (LinearLayout) rootView.findViewById(R.id.frag_point);
int total = datas.size();
int pages = total / ITEM_PAGE_COUNT
+ (total % ITEM_PAGE_COUNT == 0 ? 0 : 1);
allPageViews = new GridView[pages];
pointViews = new RadioButton[pages];
for (int x = 0; x < pages; x++) {
int start = x * ITEM_PAGE_COUNT;
int end = (start + ITEM_PAGE_COUNT) > total ? total
: (start + ITEM_PAGE_COUNT);
final List<String> itemDatas = datas.subList(start, end);
GridView view = new GridView(aty);
EmojiAdapter faceAdapter = new EmojiAdapter(view, itemDatas);
view.setNumColumns(7);
view.setHorizontalSpacing(1);
view.setVerticalSpacing(1);
view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
view.setCacheColorHint(0);
view.setPadding(2, 0, 2, 0);
view.setBackgroundResource(android.R.color.transparent);
view.setSelector(android.R.color.transparent);
view.setVerticalScrollBarEnabled(false);
view.setGravity(Gravity.CENTER);
view.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
view.setAdapter(faceAdapter);
view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (listener != null) {
String emoji = itemDatas.get(position);
if (EmojiconHandler.isCustomDeleteEmojicon(emoji)) {
listener.selectedBackSpace(emoji);
} else {
listener.selectedEmoji(emoji);
}
}
}
});
allPageViews[x] = view;
RadioButton tip = new RadioButton(aty);
tip.setBackgroundResource(R.drawable.home_selector_chat_emoji_btn);
RadioGroup.LayoutParams layoutParams = new RadioGroup.LayoutParams(
8, 8);
layoutParams.leftMargin = 10;
pagePointLayout.addView(tip, layoutParams);
if (x == 0) {
tip.setChecked(true);
}
pointViews[x] = tip;
}
PagerAdapter facePagerAdapter = new FacePagerAdapter(allPageViews);
mPagerFace.setAdapter(facePagerAdapter);
mPagerFace.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
pointViews[index].setChecked(true);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
public class FacePagerAdapter extends PagerAdapter {
private final GridView[] gridViewList;
public FacePagerAdapter(GridView[] gridViewList) {
this.gridViewList = gridViewList;
}
@Override
public int getCount() {
return gridViewList.length;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getItemPosition(Object object) {
return super.getItemPosition(object);
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView(gridViewList[arg1]);
}
@Override
public Object instantiateItem(View arg0, int arg1) {
((ViewPager) arg0).addView(gridViewList[arg1]);
return gridViewList[arg1];
}
}
public void setOnOperationListener(OnOperationListener onOperationListener) {
this.listener = onOperationListener;
}
}
... ...
/*
* Copyright (c) 2015, 张涛.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mang.xdy.demo.widget.emoji;
/**
* emoji表情的javabean
*
* @author kymjs (http://www.kymjs.com/) on 6/8/15.
*/
public class Emojicon {
private String name; //在网络传递中的值
private byte[] code; //在系统中所代表的值
private String value; //code转换为String的值
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getCode() {
return code;
}
public void setCode(byte[] code) {
this.code = code;
}
public void setValue(String value) {
this.value = value;
}
/**
* @return code转换为String的值
*/
public String getValue() {
if (code == null) {
return null;
} else {
return new String(code);
}
}
}
... ...
package com.mang.xdy.demo.widget.emoji;
import com.mang.xdy.demo.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Admin on 2017/3/29.
*/
public class EmojiconHandler {
public static List<String> mEmoticons = new ArrayList<String>();
public static Map<String, Integer> mEmoticonsId = new HashMap<String, Integer>();
static {
mEmoticonsId.put("[img:weixiao]", R.drawable.weixiao);
mEmoticons.add("[img:weixiao]");
mEmoticonsId.put("[img:piezui]", R.drawable.piezui);
mEmoticons.add("[img:piezui]");
mEmoticonsId.put("[img:aimu]", R.drawable.aimu);
mEmoticons.add("[img:aimu]");
mEmoticonsId.put("[img:fadai]", R.drawable.fadai);
mEmoticons.add("[img:fadai]");
mEmoticonsId.put("[img:fanu]", R.drawable.fanu);
mEmoticons.add("[img:fanu]");
mEmoticonsId.put("[img:mojing]", R.drawable.mojing);
mEmoticons.add("[img:mojing]");
mEmoticonsId.put("[img:liulei]", R.drawable.liulei);
mEmoticons.add("[img:liulei]");
mEmoticonsId.put("[img:jingya]", R.drawable.jingya);
mEmoticons.add("[img:jingya]");
mEmoticonsId.put("[img:daxiao]", R.drawable.daxiao);
mEmoticons.add("[img:daxiao]");
mEmoticonsId.put("[img:ganga]", R.drawable.ganga);
mEmoticons.add("[img:ganga]");
mEmoticonsId.put("[img:daku]", R.drawable.daku);
mEmoticons.add("[img:daku]");
mEmoticonsId.put("[img:shuijiao]", R.drawable.shuijiao);
mEmoticons.add("[img:shuijiao]");
mEmoticonsId.put("[img:bizui]", R.drawable.bizui);
mEmoticons.add("[img:bizui]");
mEmoticonsId.put("[img:meiyan]", R.drawable.meiyan);
mEmoticons.add("[img:meiyan]");
mEmoticonsId.put("[img:yumen]", R.drawable.yumen);
mEmoticons.add("[img:yumen]");
mEmoticonsId.put("[img:cool]", R.drawable.cool);
mEmoticons.add("[img:cool]");
mEmoticonsId.put("[img:zhemo]", R.drawable.zhemo);
mEmoticons.add("[img:zhemo]");
mEmoticonsId.put("[img:tu]", R.drawable.tu);
mEmoticons.add("[img:tu]");
mEmoticonsId.put("[img:touxiao]", R.drawable.touxiao);
mEmoticons.add("[img:touxiao]");
mEmoticonsId.put("[img:guai]", R.drawable.guai);
mEmoticons.add("[img:guai]");
mEmoticonsId.put("[img:baiyan]", R.drawable.baiyan);
mEmoticons.add("[img:baiyan]");
mEmoticonsId.put("[img:aoman]", R.drawable.aoman);
mEmoticons.add("[img:aoman]");
mEmoticonsId.put("[img:jiew]", R.drawable.jiew);
mEmoticons.add("[img:jiew]");
mEmoticonsId.put("[img:kun]", R.drawable.kun);
mEmoticons.add("[img:kun]");
mEmoticonsId.put("[img:jingkong]", R.drawable.jingkong);
mEmoticons.add("[img:jingkong]");
mEmoticonsId.put("[img:liuhan]", R.drawable.liuhan);
mEmoticons.add("[img:liuhan]");
mEmoticonsId.put("[img:hanxiao]", R.drawable.hanxiao);
mEmoticons.add("[img:hanxiao]");
mEmoticonsId.put("[img:shanchu]", R.drawable.orca_emoji_backspace_back_normal);
mEmoticons.add("[img:shanchu]");
mEmoticonsId.put("[img:hanxiao]", R.drawable.hanxiao);
mEmoticons.add("[img:hanxiao]");
//orca_emoji_backspace_back_normal
mEmoticonsId.put("[img:dabing]", R.drawable.dabing);
mEmoticons.add("[img:dabing]");
mEmoticonsId.put("[img:fendou]", R.drawable.fendou);
mEmoticons.add("[img:fendou]");
mEmoticonsId.put("[img:zhouma]", R.drawable.zhouma);
mEmoticons.add("[img:zhouma]");
mEmoticonsId.put("[img:yiwen]", R.drawable.yiwen);
mEmoticons.add("[img:yiwen]");
mEmoticonsId.put("[img:yun]", R.drawable.yun);
mEmoticons.add("[img:yun]");
mEmoticonsId.put("[img:shuai]", R.drawable.shuai);
mEmoticons.add("[img:shuai]");
mEmoticonsId.put("[img:kulou]", R.drawable.kulou);
mEmoticons.add("[img:kulou]");
mEmoticonsId.put("[img:zaijian]", R.drawable.zaijian);
mEmoticons.add("[img:zaijian]");
mEmoticonsId.put("[img:cahan]", R.drawable.cahan);
mEmoticons.add("[img:cahan]");
mEmoticonsId.put("[img:koubi]", R.drawable.koubi);
mEmoticons.add("[img:koubi]");
mEmoticonsId.put("[img:guzhang]", R.drawable.guzhang);
mEmoticons.add("[img:guzhang]");
mEmoticonsId.put("[img:qiu]", R.drawable.qiu);
mEmoticons.add("[img:qiu]");
mEmoticonsId.put("[img:huaixiao]", R.drawable.huaixiao);
mEmoticons.add("[img:huaixiao]");
mEmoticonsId.put("[img:zuohh]", R.drawable.zuohh);
mEmoticons.add("[img:zuohh]");
mEmoticonsId.put("[img:youhh]", R.drawable.youhh);
mEmoticons.add("[img:youhh]");
mEmoticonsId.put("[img:haqi]", R.drawable.haqi);
mEmoticons.add("[img:haqi]");
mEmoticonsId.put("[img:bishi]", R.drawable.bishi);
mEmoticons.add("[img:bishi]");
mEmoticonsId.put("[img:weiqu]", R.drawable.weiqu);
mEmoticons.add("[img:weiqu]");
mEmoticonsId.put("[img:kuaikl]", R.drawable.kuaikl);
mEmoticons.add("[img:kuaikl]");
mEmoticonsId.put("[img:yinxian]", R.drawable.yinxian);
mEmoticons.add("[img:yinxian]");
mEmoticonsId.put("[img:qinqin]", R.drawable.qinqin);
mEmoticons.add("[img:qinqin]");
mEmoticonsId.put("[img:kelian]", R.drawable.kelian);
mEmoticons.add("[img:kelian]");
mEmoticonsId.put("[img:xigua]", R.drawable.xigua);
mEmoticons.add("[img:xigua]");
mEmoticonsId.put("[img:pijiu]", R.drawable.pijiu);
mEmoticons.add("[img:pijiu]");
mEmoticonsId.put("[img:kafei]", R.drawable.kafei);
mEmoticons.add("[img:kafei]");
mEmoticonsId.put("[img:hua]", R.drawable.hua);
mEmoticons.add("[img:hua]");
mEmoticonsId.put("[img:shanchu]", R.drawable.orca_emoji_backspace_back_normal);
mEmoticons.add("[img:shanchu]");
mEmoticonsId.put("[img:tiaoxie]", R.drawable.tiaoxie);
mEmoticons.add("[img:tiaoxie]");
mEmoticonsId.put("[img:xin]", R.drawable.xin);
mEmoticons.add("[img:xin]");
mEmoticonsId.put("[img:dangao]", R.drawable.dangao);
mEmoticons.add("[img:dangao]");
mEmoticonsId.put("[img:yue]", R.drawable.yue);
mEmoticons.add("[img:yue]");
mEmoticonsId.put("[img:sun]", R.drawable.sun);
mEmoticons.add("[img:sun]");
mEmoticonsId.put("[img:qiang]", R.drawable.qiang);
mEmoticons.add("[img:qiang]");
mEmoticonsId.put("[img:ruo]", R.drawable.ruo);
mEmoticons.add("[img:ruo]");
mEmoticonsId.put("[img:woshou]", R.drawable.woshou);
mEmoticons.add("[img:woshou]");
mEmoticonsId.put("[img:baoquan]", R.drawable.baoquan);
mEmoticons.add("[img:baoquan]");
mEmoticonsId.put("[img:zancheng]", R.drawable.zancheng);
mEmoticons.add("[img:zancheng]");
mEmoticonsId.put("[img:shanchu]", R.drawable.orca_emoji_backspace_back_normal);
mEmoticons.add("[img:shanchu]");
}
public static boolean isCustomDeleteEmojicon(String emoji) {
if (emoji != null) {
return (emoji.equals("[img:shanchu]"));
} else {
return false;
}
}
}
... ...
package com.mang.xdy.demo.widget.emoji;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.widget.EditText;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EmoticonsEditText extends EditText {
private int mEmojiconSize;
private int mEmojiconTextSize;
private boolean mUseSystemDefault = false;
public EmoticonsEditText(Context context) {
super(context);
mEmojiconSize = (int) getTextSize();
mEmojiconTextSize = (int) getTextSize();
}
public EmoticonsEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public EmoticonsEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
private void init(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, com.rockerhieu.emojicon.R.styleable.Emojicon);
mEmojiconSize = (int) a.getDimension(com.rockerhieu.emojicon.R.styleable.Emojicon_emojiconSize, getTextSize());
mUseSystemDefault = a.getBoolean(com.rockerhieu.emojicon.R.styleable.Emojicon_emojiconUseSystemDefault, false);
a.recycle();
mEmojiconTextSize = (int) getTextSize();
//setText(getText());
}
@Override
public void setText(CharSequence text, BufferType type) {
if (!TextUtils.isEmpty(text)) {
super.setText(replace(text), type);
/*setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
findFocus();
invalidate();*/
} else {
super.setText(text, type);
}
}
private Pattern buildPattern() {
StringBuilder patternString = new StringBuilder(EmojiconHandler.mEmoticons.size() * 3);
patternString.append('(');
for (int i = 0; i < EmojiconHandler.mEmoticons.size(); i++) {
String s = EmojiconHandler.mEmoticons.get(i);
patternString.append(Pattern.quote(s));
patternString.append('|');
}
patternString.replace(patternString.length() - 1,
patternString.length(), ")");
return Pattern.compile(patternString.toString());
}
private CharSequence replace(CharSequence text) {
try {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
Pattern pattern = buildPattern();
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
if (EmojiconHandler.mEmoticonsId.containsKey(matcher.group())) {
int id = EmojiconHandler.mEmoticonsId.get(matcher.group());
Bitmap bitmap = BitmapFactory.decodeResource(
getResources(), id);
if (bitmap != null) {
ImageSpan span = new ImageSpan(getContext(), bitmap);
builder.setSpan(span, matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
return builder;
} catch (Exception e) {
return text;
}
}
}
... ...
package com.mang.xdy.demo.widget.emoji;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.widget.TextView;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EmoticonsTextView extends TextView {
private int mEmojiconSize;
private int mEmojiconTextSize;
private int mTextStart = 0;
private int mTextLength = -1;
private boolean mUseSystemDefault = false;
public EmoticonsTextView(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
mEmojiconTextSize = (int) getTextSize();
if (attrs == null) {
mEmojiconSize = (int) getTextSize();
} else {
TypedArray a = getContext().obtainStyledAttributes(attrs, com.rockerhieu.emojicon.R.styleable.Emojicon);
mEmojiconSize = (int) a.getDimension(com.rockerhieu.emojicon.R.styleable.Emojicon_emojiconSize, getTextSize());
mTextStart = a.getInteger(com.rockerhieu.emojicon.R.styleable.Emojicon_emojiconTextStart, 0);
mTextLength = a.getInteger(com.rockerhieu.emojicon.R.styleable.Emojicon_emojiconTextLength, -1);
mUseSystemDefault = a.getBoolean(com.rockerhieu.emojicon.R.styleable.Emojicon_emojiconUseSystemDefault, false);
a.recycle();
}
setText(getText());
}
public EmoticonsTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public EmoticonsTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
@Override
public void setText(CharSequence text, BufferType type) {
if (!TextUtils.isEmpty(text)) {
// SpannableStringBuilder builder = new SpannableStringBuilder(text);
// com.rockerhieu.emojicon.EmojiconHandler.addEmojis(getContext(), builder, mEmojiconSize, mEmojiconTextSize, mTextStart, mTextLength, mUseSystemDefault);
// text = builder;
super.setText(replace(text), type);
} else {
super.setText(text, type);
}
}
private Pattern buildPattern() {
StringBuilder patternString = new StringBuilder(
EmojiconHandler.mEmoticons.size() * 3);
patternString.append('(');
for (int i = 0; i < EmojiconHandler.mEmoticons.size(); i++) {
String s = EmojiconHandler.mEmoticons.get(i);
patternString.append(Pattern.quote(s));
patternString.append('|');
}
patternString.replace(patternString.length() - 1,
patternString.length(), ")");
return Pattern.compile(patternString.toString());
}
private CharSequence replace(CharSequence text) {
try {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
Pattern pattern = buildPattern();
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
if (EmojiconHandler.mEmoticonsId.containsKey(matcher.group())) {
int id = EmojiconHandler.mEmoticonsId.get(matcher.group());
Bitmap bitmap = BitmapFactory.decodeResource(
getResources(), id);
if (bitmap != null) {
ImageSpan span = new ImageSpan(getContext(), bitmap);
builder.setSpan(span, matcher.start(), matcher.end(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
return builder;
} catch (Exception e) {
return text;
}
}
/**
* Set the size of emojicon in pixels.
*/
public void setEmojiconSize(int pixels) {
mEmojiconSize = pixels;
super.setText(getText());
}
/**
* Set whether to use system default emojicon
*/
public void setUseSystemDefault(boolean useSystemDefault) {
mUseSystemDefault = useSystemDefault;
}
}
... ...