package org.aisen.weibo.sina.ui.fragment.publish; import java.io.ByteArrayOutputStream; import java.io.File; import org.aisen.weibo.sina.R; import org.aisen.weibo.sina.support.bean.Emotion; import org.aisen.weibo.sina.support.bean.PublishBean; import org.aisen.weibo.sina.support.bean.PublishBean.PublishStatus; import org.aisen.weibo.sina.support.compress.TimelineBitmapCompress; import org.aisen.weibo.sina.support.db.EmotionsDB; import org.aisen.weibo.sina.support.publish.PublishDB; import org.aisen.weibo.sina.support.utils.AisenUtil; import org.aisen.weibo.sina.support.utils.AppContext; import org.aisen.weibo.sina.support.utils.AppSettings; import org.aisen.weibo.sina.sys.service.PublishService; import org.aisen.weibo.sina.ui.fragment.publish.EmotionFragment.OnEmotionSelectedListener; import org.android.loader.BitmapLoader; import org.android.loader.core.BitmapDecoder; import org.android.loader.core.ImageConfig; import org.android.loader.download.ContentProviderDownloader; import org.android.loader.download.DownloadProcess; import org.android.loader.download.SdcardDownloader; import org.sina.android.bean.WeiBoUser; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.InputFilter; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.ImageSpan; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.m.common.params.Params; import com.m.common.utils.ActivityHelper; import com.m.common.utils.BitmapUtil; import com.m.common.utils.FileUtility; import com.m.common.utils.Logger; import com.m.common.utils.SystemUtility; import com.m.common.utils.Utils; import com.m.support.Inject.ViewInject; import com.m.support.task.TaskException; import com.m.support.task.WorkTask; import com.m.ui.activity.BaseActivity; import com.m.ui.fragment.ABaseFragment; import com.m.ui.utils.PhotoChoice; import com.m.ui.utils.PhotoChoice.PhotoChoiceListener; import com.m.ui.utils.PhotoChoice.PhotoChoiceMode; public abstract class APublishFragment extends ABaseFragment implements OnEmotionSelectedListener, PhotoChoiceListener { public static final String TAG = "Publish"; public static final int MAX_STATUS_LENGTH = 140; @ViewInject(id = R.id.layBtns) View layBtns; @ViewInject(id = R.id.btnLocation, click = "loadGPSLocation") View btnLocation; @ViewInject(id = R.id.btnCamera, click = "getPicture") View btnCamera; @ViewInject(id = R.id.btnEmotion, click = "switchEmotionSoftinput") View btnEmotion; @ViewInject(id = R.id.btnMention, click = "getFriend") View btnMention; @ViewInject(id = R.id.btnTrends, click = "insertTrends") View btnTrends; @ViewInject(id = R.id.btnOverflow, click = "popOverflowMenu") View btnOverflow; @ViewInject(id = R.id.layContainer) View layContainer; @ViewInject(id = R.id.layRoot) ViewGroup layRoot; @ViewInject(id = R.id.txtErrorHint) TextView txtErrorHint; @ViewInject(id = R.id.editContent) EditText editContent; @ViewInject(id = R.id.imgBk) ImageView picShow; @ViewInject(id = R.id.layImageCover) View layImageCover; @ViewInject(id = R.id.layEmotion) View layEmotion; @ViewInject(id = R.id.txtContentSurplus) TextView txtContentSurplus; @ViewInject(id = R.id.checkbox) CheckBox checkBox; @ViewInject(id = R.id.txtContent) TextView txtContent; private final LayoutTransition transitioner = new LayoutTransition(); private EmotionFragment emotionFragment; private PhotoChoice photoChoice; private PublishBean mBean; private int emotionHeight; @Override protected void layoutInit(LayoutInflater inflater, Bundle savedInstanceState) { super.layoutInit(inflater, savedInstanceState); getActivity().getActionBar().setSubtitle(AppContext.getUser().getScreen_name()); btnLocation.setVisibility(View.GONE); if (savedInstanceState == null) { if (getArguments() != null) mBean = (PublishBean) getArguments().getSerializable("bean"); } else { mBean = (PublishBean) savedInstanceState.getSerializable("bean"); } if (mBean == null) mBean = newPublishBean(); setHasOptionsMenu(true); if (savedInstanceState == null) { emotionFragment = EmotionFragment.newInstance(); getActivity().getFragmentManager().beginTransaction().add(R.id.layEmotion, emotionFragment, "EmotionFragemnt").commit(); } else { emotionFragment = (EmotionFragment) getActivity().getFragmentManager().findFragmentByTag("EmotionFragemnt"); } emotionFragment.setOnEmotionListener(this); // 内容编辑 editContent.addTextChangedListener(editContentWatcher); // 更换表情 editContent.setFilters(new InputFilter[] { emotionFilter }); editContent.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { hideEmotionView(true); } }); ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "translationY", SystemUtility.getScreenHeight(getActivity()), emotionHeight). setDuration(transitioner.getDuration(LayoutTransition.APPEARING)); transitioner.setAnimator(LayoutTransition.APPEARING, animIn); ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "translationY", emotionHeight, SystemUtility.getScreenHeight(getActivity())). setDuration(transitioner.getDuration(LayoutTransition.DISAPPEARING)); transitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut); layRoot.setLayoutTransition(transitioner); if (!AisenUtil.isTranslucent()) layBtns.setBackgroundColor(Color.parseColor(AppSettings.getThemeColor())); refreshUI(); } /** * 2014-10-23 根据不同主题显示不同颜色 */ protected void resetEditColor() { if (AisenUtil.isTranslucent() && !configWhite()) { editContent.setTextColor(getResources().getColor(R.color.white)); editContent.setHintTextColor(getResources().getColor(R.color.edit_hint_wallpaper)); } else { editContent.setTextColor(getResources().getColor(R.color.black)); editContent.setHintTextColor(getResources().getColor(R.color.edit_hint)); } } // 如果有照片了,也显示黑色文字 protected boolean configWhite() { return getPublishBean().getExtras() != null && getPublishBean().getExtras().containsKey("images"); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putSerializable("bean", mBean); } /** * 刷新视图 */ void refreshUI() { resetEditColor(); if (getPublishBean() == null) return; PublishBean bean = getPublishBean(); // 文字内容 if (!TextUtils.isEmpty(bean.getText())) { editContent.setText(bean.getText()); // 如果是意见反馈,不默认将光标移动到最后 if (bean.getExtras() != null && bean.getExtras().containsKey("feedback")) ; else editContent.setSelection(editContent.getText().toString().length()); } // 显示图片 if (bean.getExtras() != null && bean.getExtras().containsKey("images")) { String[] images = bean.getExtras().getParameter("images").split("&"); ImageConfig config = new ImageConfig(); config.setLoadfaildBitmapRes(R.drawable.bg_timeline_loading); config.setLoadingBitmapRes(R.drawable.bg_timeline_loading); config.setMaxWidth(SystemUtility.getScreenWidth()); config.setMaxHeight(SystemUtility.getScreenHeight()); config.setBitmapCompress(TimelineBitmapCompress.class); config.setProgress(new PublishDownloadProcess()); String path = images[0]; if (path.toString().startsWith("content://")) { Logger.v(TAG, "相册图片地址, path = " + path); config.setDownloaderClass(ContentProviderDownloader.class); } else { path = path.toString().replace("file://", ""); Logger.v(TAG, "拍照图片地址, path = " + path); // 扫描文件 SystemUtility.scanPhoto(new File(path)); config.setDownloaderClass(SdcardDownloader.class); } BitmapLoader.getInstance().display(this, path, picShow, config); layImageCover.setVisibility(View.VISIBLE); picShow.setVisibility(View.VISIBLE); } else { layImageCover.setVisibility(View.GONE); picShow.setVisibility(View.GONE); } } class PublishDownloadProcess extends DownloadProcess { @Override public void receiveLength(long length) { } @Override public void receiveProgress(long progressed) { } @Override public void prepareDownload(String url) { } @Override public void finishedDownload(byte[] bytes) { } @Override public void downloadFailed(Exception e) { getPublishBean().getExtras().remove("images"); showMessage(R.string.publish_pic_none); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.publish, menu); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.send) { if (txtErrorHint.getVisibility() == View.VISIBLE) { showMessage(txtErrorHint.getText().toString()); return true; } if (checkValid(getPublishBean())) send(); } return super.onOptionsItemSelected(item); } private void send() { if (AppSettings.isSendDelay()) getPublishBean().setDelay(AppSettings.getPublishDelay()); else getPublishBean().setDelay(0); PublishService.publish(getActivity(), getPublishBean()); getActivity().finish(); } @Override public void onEmotionSelected(Emotion emotion) { Editable editAble = editContent.getEditableText(); int start = editContent.getSelectionStart(); editAble.insert(start, emotion.getKey()); }; /** * 微博内容监听,刷新提示信息 */ private TextWatcher editContentWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // 设置长度提示 String content = editContent.getText().toString() + appendContent(); txtContentSurplus.setText((MAX_STATUS_LENGTH - AisenUtil.getStrLength(content)) + ""); if (AisenUtil.getStrLength(content) > MAX_STATUS_LENGTH) { txtErrorHint.setVisibility(View.VISIBLE); txtErrorHint.setText(String.format(getString(R.string.error_length_too_long), AisenUtil.getStrLength(content) - MAX_STATUS_LENGTH)); } else { txtErrorHint.setVisibility(View.GONE); } getPublishBean().setText(content); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }; /** * 输入文本的过滤,根据输入替换库中的表情 */ private InputFilter emotionFilter = new InputFilter() { @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { // 是delete直接返回 if ("".equals(source)) { return null; } byte[] emotionBytes = EmotionsDB.getEmotion(source.toString()); // 输入的表情字符存在,则替换成表情图片 if (emotionBytes != null) { byte[] data = emotionBytes; Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); int size = BaseActivity.getRunningActivity().getResources().getDimensionPixelSize(R.dimen.emotion_size); bitmap = BitmapUtil.zoomBitmap(bitmap, size); SpannableString emotionSpanned = new SpannableString(source.toString()); ImageSpan span = new ImageSpan(getActivity(), bitmap); emotionSpanned.setSpan(span, 0, source.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return emotionSpanned; } else { return source; } } }; protected String appendContent() { return ""; } /** * 插入图片 * * @param v */ void getPicture(View v) { // 已经有图片了 if (getPublishBean().getExtras() != null && getPublishBean().getExtras().containsKey("images")) { new AlertDialog.Builder(getActivity()) .setItems(R.array.publish_pic_edit, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (which == 0) { showGetPictureDialog(); } else { getPublishBean().getExtras().remove("images"); refreshUI(); } } }) .show(); } else { showGetPictureDialog(); } } private void showGetPictureDialog() { new AlertDialog.Builder(getActivity()) .setItems(R.array.publish_pic, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (photoChoice == null) { String albumPath = SystemUtility.getSdcardPath() + java.io.File.separator + "/DCIM/Camera/"; File albumFile = new File(albumPath); if (!albumFile.exists()) albumFile.mkdirs(); photoChoice = new PhotoChoice(getActivity(), APublishFragment.this, albumPath); photoChoice.setFileName(String.format("%s.jpg", String.valueOf(System.currentTimeMillis() / 1000))); } photoChoice.setMode(PhotoChoiceMode.uriType); switch (which) { // 相册 case 0: photoChoice.start(APublishFragment.this, 0); break; // 拍照 case 1: photoChoice.start(APublishFragment.this, 1); break; // 最后一次拍照 case 2: getLastPhoto(); break; default: break; } } }) .show(); } /** * 插入话题 * * @param v */ void insertTrends(View v) { Editable editAble = editContent.getEditableText(); int start = editContent.getSelectionStart(); editAble.insert(start, "##"); editContent.setSelection(editContent.getSelectionStart() - 1); } /** * 切换表情跟键盘 * * @param v */ void switchEmotionSoftinput(View v) { if (layEmotion.isShown()) { hideEmotionView(true); } else { showEmotionView(SystemUtility.isKeyBoardShow(getActivity())); } } private void hideEmotionView(boolean showKeyBoard) { if (layEmotion.isShown()) { if (showKeyBoard) { LinearLayout.LayoutParams localLayoutParams = (LinearLayout.LayoutParams) layContainer.getLayoutParams(); localLayoutParams.height = layEmotion.getTop(); localLayoutParams.weight = 0.0F; layEmotion.setVisibility(View.GONE); getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); SystemUtility.showKeyBoard(editContent); editContent.postDelayed(new Runnable() { @Override public void run() { unlockContainerHeightDelayed(); } }, 200L); } else { layEmotion.setVisibility(View.GONE); getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); unlockContainerHeightDelayed(); } } } private void showEmotionView(boolean showAnimation) { if (showAnimation) { transitioner.setDuration(200); } else { transitioner.setDuration(0); } emotionHeight = SystemUtility.getKeyboardHeight(getActivity()); SystemUtility.hideSoftInput(editContent); layEmotion.getLayoutParams().height = emotionHeight; layEmotion.setVisibility(View.VISIBLE); getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); lockContainerHeight(SystemUtility.getAppContentHeight(getActivity())); } private void lockContainerHeight(int paramInt) { LinearLayout.LayoutParams localLayoutParams = (LinearLayout.LayoutParams) layContainer.getLayoutParams(); localLayoutParams.height = paramInt; localLayoutParams.weight = 0.0F; } public void unlockContainerHeightDelayed() { ((LinearLayout.LayoutParams) layContainer.getLayoutParams()).weight = 1.0F; } void getFriend(View v) { AddFriendMentionFragment.launch(this, 1000); } @Override public boolean onHomeClick() { if (!TextUtils.isEmpty(getPublishBean().getText()) || getPublishBean().getExtras().containsKey("images")) { askSaveToDraft(); return true; } return super.onBackClick(); } @Override public boolean onBackClick() { if (layEmotion.isShown()) { hideEmotionView(false); return true; } else if (!TextUtils.isEmpty(getPublishBean().getText()) || getPublishBean().getExtras().containsKey("images")) { askSaveToDraft(); return true; } return super.onBackClick(); } private void askSaveToDraft() { new AlertDialog.Builder(getActivity()).setMessage(R.string.publish_draft_title) .setNegativeButton(R.string.no, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { getActivity().finish(); } }) .setPositiveButton(R.string.yes, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { getPublishBean().setStatus(PublishStatus.draft); PublishDB.addPublish(getPublishBean(), AppContext.getUser()); getActivity().finish(); } }) .show(); } @Override public void choiceByte(byte[] datas) { } @Override public void choiceBitmap(Bitmap bitmap) { } @Override public void choieUri(Uri uri, int requestCode) { // 当拍摄照片时,提示是否设置旋转90度 if (!AppSettings.isRotatePic() && !ActivityHelper.getInstance().getBooleanShareData("RotatePicNoRemind", false)) { new AlertDialog.Builder(getActivity()).setTitle(R.string.remind) .setMessage(R.string.publish_rotate_remind) .setNegativeButton(R.string.donnot_remind, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityHelper.getInstance().putBooleanShareData("RotatePicNoRemind", true); } }) .setPositiveButton(R.string.i_know, null) .show(); } // 拍摄照片时,顺时针旋转90度 if (requestCode == PhotoChoice.CAMERA_IMAGE_REQUEST_CODE && AppSettings.isRotatePic()) { final String path = uri.toString().replace("file://", ""); new WorkTask<Void, Void, String>() { @Override public String workInBackground(Void... params) throws TaskException { try { Bitmap bitmap = BitmapDecoder.decodeSampledBitmapFromFile(path, SystemUtility.getScreenHeight(), SystemUtility.getScreenHeight()); bitmap = BitmapUtil.rotateBitmap(bitmap, 90); ByteArrayOutputStream outArray = new ByteArrayOutputStream(); bitmap.compress(CompressFormat.JPEG, 100, outArray); FileUtility.writeFile(new File(path), outArray.toByteArray()); } catch (OutOfMemoryError e) { e.printStackTrace(); } return path; } protected void onSuccess(String result) { setPicUri(result); }; }.execute(); } else { setPicUri(uri.toString()); } } private void setPicUri(String image) { Params extraParams = getPublishBean().getExtras(); if (extraParams == null) { extraParams = new Params(); getPublishBean().setExtras(extraParams); } extraParams.addParameter("images", image); if (TextUtils.isEmpty(editContent.getText().toString())) getPublishBean().setText(getString(R.string.publish_share_pic)); // 刷新视图 refreshUI(); } @Override public void unChoice() { } private void getLastPhoto() { new WorkTask<Void, Void, String> () { @Override public String workInBackground(Void... params) throws TaskException { String path = ""; // ContentResolver mResolver = getActivity().getContentResolver(); // String[] projection = new String[]{ MediaStore.Images.Media.DATA, // MediaStore.Images.Media.DATE_ADDED, // "MAX(" + MediaStore.Images.Media.DATE_ADDED + ")" }; // Cursor cursor = mResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // projection, null, null, MediaStore.Images.Media.DEFAULT_SORT_ORDER); // cursor.moveToFirst(); // while(!cursor.isAfterLast()){ // path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); // cursor.moveToNext(); // } // cursor.close(); if (getActivity() != null) path = Utils.getLatestCameraPicture(getActivity()); return path; } @Override protected void onSuccess(String result) { super.onSuccess(result); if (!TextUtils.isEmpty(result)) { Logger.v(TAG, "最近拍摄照片, path = " + result); File file = new File(result); if (file.exists() && file.length() == 0) { showMessage(R.string.publish_get_recent_pic_faild); } else { choieUri(Uri.parse(result), PhotoChoice.PHONE_IMAGE_REQUEST_CODE); } } else { showMessage(R.string.publish_recent_pic_none); } }; }.execute(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1000 && resultCode == Activity.RESULT_OK) { WeiBoUser user = (WeiBoUser) data.getSerializableExtra("bean"); Editable editAble = editContent.getEditableText(); int start = editContent.getSelectionStart(); editAble.insert(start, String.format("@%s ", user.getScreen_name())); } else { if (photoChoice != null) photoChoice.onActivityResult(requestCode, resultCode, data); } } public PublishBean getPublishBean() { return mBean; } @Override public void onResume() { super.onResume(); if (AisenUtil.isTranslucent()) { if (txtContent != null) txtContent.setTextColor(getResources().getColor(R.color.edit_hint_wallpaper)); if (checkBox != null) checkBox.setTextColor(getResources().getColor(R.color.edit_hint_wallpaper)); layEmotion.setBackgroundColor(getResources().getColor(R.color.transparent)); } } /** * 空创建时,初始化Bean * * @return */ abstract PublishBean newPublishBean(); abstract void popOverflowMenu(View v); abstract boolean checkValid(PublishBean bean); }