From 0a13476751c01ae346c30a4c4dd266bad700d2c3 Mon Sep 17 00:00:00 2001 From: mac <user@users-MacBook-Pro.local> Date: 星期四, 07 三月 2024 13:28:45 +0800 Subject: [PATCH] 2024年03月07日13:28:38 --- app/src/main/res/values/styles.xml | 2 app/src/main/res/drawable/del_house.png | 0 app/src/main/java/com/hdl/photovoltaic/other/HdlResidenceLogic.java | 43 + app/src/main/res/values/values.xml | 20 app/src/main/java/com/hdl/photovoltaic/HDLApp.java | 3 app/src/main/java/com/hdl/photovoltaic/widget/SwipeLayout.java | 1557 +++++++++++++++++++++++++++++++++++++++ app/src/main/java/com/hdl/photovoltaic/other/HdlOtaLogic.java | 25 app/src/main/res/layout/frgment_house_list_line.xml | 147 ++- app/src/main/res/drawable/editor_house.png | 0 app/src/main/java/com/hdl/photovoltaic/ui/bean/HouseIdBean.java | 11 app/src/main/res/layout/swipe_right_layout.xml | 31 app/src/main/res/layout/toolbar_top_view_52.xml | 8 app/src/main/java/com/hdl/photovoltaic/widget/DelayedConfirmationCancelDialog.java | 241 ++++++ app/src/main/java/com/hdl/photovoltaic/ui/adapter/HouseInfoAdapter.java | 80 + app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java | 141 ++ app/src/main/res/drawable/move_house.png | 0 16 files changed, 2,193 insertions(+), 116 deletions(-) diff --git a/app/src/main/java/com/hdl/photovoltaic/HDLApp.java b/app/src/main/java/com/hdl/photovoltaic/HDLApp.java index 5265042..4c71607 100644 --- a/app/src/main/java/com/hdl/photovoltaic/HDLApp.java +++ b/app/src/main/java/com/hdl/photovoltaic/HDLApp.java @@ -61,14 +61,13 @@ @Override public void onCreate() { - super.onCreate(); + mHDLApp = this; SharedPreUtils.init(this); getAppLanguage(); initThirdSDK(); // appLocationInfo(); - } public void getAppLanguage() { diff --git a/app/src/main/java/com/hdl/photovoltaic/other/HdlOtaLogic.java b/app/src/main/java/com/hdl/photovoltaic/other/HdlOtaLogic.java index 4408849..da664cc 100644 --- a/app/src/main/java/com/hdl/photovoltaic/other/HdlOtaLogic.java +++ b/app/src/main/java/com/hdl/photovoltaic/other/HdlOtaLogic.java @@ -536,12 +536,12 @@ //-100:娌℃湁鏁版嵁;-101:娌℃湁md5绉橀挜;-102:md5绉橀挜涓嶅;-103:鏈夊紓甯�; if (zipData == null) { this.eventBusPost(fileFullPath, driver, -100, HDLApp.getInstance().getString(R.string.exception_unable_to_pull_up_the_cloud_upgrade_file_data)); - HdlLogLogic.print("鎷変笉鍒颁簯绔崌绾ф枃浠舵暟鎹�(-100)", true); +// HdlLogLogic.print("鎷変笉鍒颁簯绔崌绾ф枃浠舵暟鎹�(-100)", true); return false; } if (TextUtils.isEmpty(md5)) { this.eventBusPost(fileFullPath, driver, -101, HDLApp.getInstance().getString(R.string.exception_failed_to_obtain_the_md5_key_of_the_upgrade_file_on_the_cloud)); - HdlLogLogic.print("鎷夸笉鍒颁簯绔笂鍗囩骇鏂囦欢md5绉橀挜(-101)", true); +// HdlLogLogic.print("鎷夸笉鍒颁簯绔笂鍗囩骇鏂囦欢md5绉橀挜(-101)", true); return false; } InputStream is = null; @@ -555,7 +555,7 @@ long total = zipData.contentLength(); if (total == 0) { this.eventBusPost(fileFullPath, driver, -102, HDLApp.getInstance().getString(R.string.exception_unable_to_pull_up_the_cloud_upgrade_file_data)); - HdlLogLogic.print("鎷変笉鍒颁簯绔崌绾ф枃浠舵暟鎹�(-102)", true); +// HdlLogLogic.print("鎷変笉鍒颁簯绔崌绾ф枃浠舵暟鎹�(-102)", true); return false; } fos = new FileOutputStream(file); @@ -563,7 +563,7 @@ while ((len = is.read(buf)) != -1) { if (this.stopDownload) { this.eventBusPost(fileFullPath, driver, -108, HDLApp.getInstance().getString(R.string.exception_the_user_cancels_downloading_the_upgrade_file)); - HdlLogLogic.print("鐢ㄦ埛鍙栨秷涓嬭浇鍗囩骇鏂囦欢(-108)", true); +// HdlLogLogic.print("鐢ㄦ埛鍙栨秷涓嬭浇鍗囩骇鏂囦欢(-108)", true); fos.flush(); fos.close(); is.close(); @@ -576,36 +576,37 @@ int progress = (int) (100 * sum * 1.0f / total); if (sum != total) { //涓嶇瓑浜�100閮借鎶�,绛変簬100澶勭悊鏁村潡閫昏緫瀹屼箣鍚庡啀鎶�100; - this.eventBusPost(fileFullPath, driver, progress, "姝e父涓婃姤杩涘害鍊�->" + progress); - HdlLogLogic.print("姝e父涓婃姤杩涘害鍊�->" + progress, true); + this.eventBusPost(fileFullPath, driver, progress, "姝e父涓婃姤杩涘害鍊�--->" + progress); +// HdlLogLogic.print("姝e父涓婃姤杩涘害鍊�--->" + progress, true); } } fos.flush(); fos.close(); is.close(); - byte[] bytes = FileUtils.readFileToByteArray(file); + byte[] bytes = HdlFileLogic.getInstance().readFileByte(fileFullPath); +// byte[] bytes = FileUtils.readFileToByteArray(file);//杩欎釜鏂规硶涓嶅吋鐢╝ndroid 6.0 //todo 涓嬭浇鏂囦欢闇�瑕佽В瀵嗕箣鍚庡啀杩涜md5鍘诲仛姣斿 byte[] decrypt = AesUtils.decrypt(bytes); if (decrypt == null) { this.eventBusPost(fileFullPath, driver, -105, HDLApp.getInstance().getString(R.string.exception_failed_to_decrypt_the_upgrade_aes_file)); - HdlLogLogic.print("鍗囩骇鏂囦欢aes瑙e瘑澶辫触(-105)", true); +// HdlLogLogic.print("鍗囩骇鏂囦欢aes瑙e瘑澶辫触(-105)", true); return false; } String fileMD5 = Md5Utils.encodeMD5(decrypt); if (TextUtils.isEmpty(fileMD5)) { this.eventBusPost(fileFullPath, driver, -106, HDLApp.getInstance().getString(R.string.exception_failed_to_generate_md5_for_the_upgrade_file)); - HdlLogLogic.print("鍗囩骇鏂囦欢鐢熸垚md5澶辫触澶辫触(-106)", true); +// HdlLogLogic.print("鍗囩骇鏂囦欢鐢熸垚md5澶辫触澶辫触(-106)", true); return false; } if (!md5.equals(fileMD5)) { this.eventBusPost(fileFullPath, driver, -107, HDLApp.getInstance().getString(R.string.exception_description_failed_to_compare_the_md5_of_the_upgrade_file)); - HdlLogLogic.print("鍗囩骇鏂囦欢md5姣斿澶辫触(-107)", true); +// HdlLogLogic.print("鍗囩骇鏂囦欢md5姣斿澶辫触(-107)", true); return false; } //todo 娉ㄦ剰:瑙e瘑涔嬪悗锛岃閲嶆柊鍐欐暟鎹�; - FileUtils.writeByteArrayToFile(file, decrypt, false); + HdlFileLogic.getInstance().writeFile(fileFullPath, decrypt); +// FileUtils.writeByteArrayToFile(file, decrypt, false);//杩欎釜鏂规硶涓嶅吋鐢╝ndroid 6.0 this.eventBusPost(fileFullPath, driver, 100, HDLApp.getInstance().getString(R.string.exception_the_upgrade_file_is_downloaded)); - HdlLogLogic.print("鍗囩骇鏂囦欢涓嬭浇瀹屾垚.", true); return true; } catch (Exception e) { this.eventBusPost(fileFullPath, driver, -103, e.getMessage()); diff --git a/app/src/main/java/com/hdl/photovoltaic/other/HdlResidenceLogic.java b/app/src/main/java/com/hdl/photovoltaic/other/HdlResidenceLogic.java index 304fac9..e3ca3cd 100644 --- a/app/src/main/java/com/hdl/photovoltaic/other/HdlResidenceLogic.java +++ b/app/src/main/java/com/hdl/photovoltaic/other/HdlResidenceLogic.java @@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -89,6 +90,48 @@ this.houseIdList = houseIdList; } + /** + * 鍒犻櫎鐢电珯 + * + * @param houseId 鐢电珯id + */ + public void delHouseId(String houseId) { + if (TextUtils.isEmpty(houseId)) { + return; + } + for (int i = 0; i < houseIdList.size(); i++) { + if (houseIdList.get(i).getHomeId().equals(houseId)) { + houseIdList.remove(i); + break; + } + } + } + + /** + * 绉诲姩鐢电珯浣嶇疆 + * + * @param houseId 鐢电珯id + */ + public void moveHouseId(String houseId) { + if (TextUtils.isEmpty(houseId)) { + return; + } + int index = -1; + for (int i = 0; i < houseIdList.size(); i++) { + if (houseIdList.get(i).getHomeId().equals(houseId)) { + index = i; + break; + } + } + if (index == -1) { + return; + } + //index==0琛ㄧず鍙湁涓�涓厓绱犳垨鑰呭湪棣栦綅,涓嶉渶瑕佺Щ鍔ㄤ綅缃� + if (index > 0) { + Collections.swap(houseIdList, index - 1, index); + } + } + //浣忓畢ID鍒楄〃 private List<HouseIdBean> houseIdList = new ArrayList<>(); //浣忓畢璇︽儏鍒楄〃 diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/adapter/HouseInfoAdapter.java b/app/src/main/java/com/hdl/photovoltaic/ui/adapter/HouseInfoAdapter.java index b22812f..4c5455a 100644 --- a/app/src/main/java/com/hdl/photovoltaic/ui/adapter/HouseInfoAdapter.java +++ b/app/src/main/java/com/hdl/photovoltaic/ui/adapter/HouseInfoAdapter.java @@ -1,12 +1,12 @@ package com.hdl.photovoltaic.ui.adapter; import android.content.Context; -import android.content.Intent; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -15,8 +15,10 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.hdl.photovoltaic.R; +import com.hdl.photovoltaic.other.HdlLogLogic; import com.hdl.photovoltaic.ui.bean.HouseIdBean; import com.hdl.photovoltaic.utils.GlideUtils; +import com.hdl.photovoltaic.widget.SwipeLayout; import java.util.ArrayList; import java.util.List; @@ -26,6 +28,11 @@ private List<HouseIdBean> mList; private final Context mContext; private OnclickListener noOnclickListener;//鐐瑰嚮浜嗙殑鐩戝惉鍣� + + /** + * 鏀堕泦SwipeLayout鏁扮粍,瑕佷竴閿叏閮ㄦ墦寮�; + */ + private List<SwipeLayout> swipeLayoutList = new ArrayList<>(); public HouseInfoAdapter(Context context) { @@ -41,6 +48,7 @@ @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { + HouseIdBean houseIdBean = this.mList.get(position); holder.homeNameTv.setText(houseIdBean.getHomeName().trim()); @@ -63,15 +71,57 @@ //鍙戠數鍔熺巼 String power = mContext.getString(R.string.power_station_generated_power) + kw + "kW"; holder.powerTv.setText(power); - holder.itemView.setTag(position); + holder.item_parent_rl.setTag(position); setTextViewStyle(holder.stateTv, houseIdBean.getPowerStationStatus()); GlideUtils.getRoundedCornersImage(mContext, houseIdBean.getPowerStationImage(), holder.homeIconIv, new RoundedCorners(4)); - holder.itemView.setOnClickListener(new View.OnClickListener() { + if (houseIdBean.isEdit()) { + holder.item_parent_swipeLayout.postDelayed(new Runnable() { + @Override + public void run() { + holder.item_parent_swipeLayout.open(); + } + }, 200); + + } else { + holder.item_parent_swipeLayout.postDelayed(new Runnable() { + @Override + public void run() { + holder.item_parent_swipeLayout.close(); + } + }, 200); + } + + HdlLogLogic.print("鐢电珯鍚嶇О--->" + houseIdBean.getHomeName() + "--->" + houseIdBean.isEdit() + "--->" + holder.item_parent_swipeLayout.toString()); + holder.item_parent_rl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { if (noOnclickListener != null) { - noOnclickListener.onClick((int) holder.itemView.getTag(), houseIdBean); + noOnclickListener.onClick((int) holder.item_parent_rl.getTag(), houseIdBean); + } + } catch (Exception ignored) { + } + } + }); + //绉诲姩鐢电珯浣嶇疆 + holder.move_home_iv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + if (noOnclickListener != null) { + noOnclickListener.onMoveClick((int) holder.item_parent_rl.getTag(), houseIdBean); + } + } catch (Exception ignored) { + } + } + }); + //鍒犻櫎鐢电珯 + holder.del_home_iv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + if (noOnclickListener != null) { + noOnclickListener.onDelClick((int) holder.item_parent_rl.getTag(), houseIdBean); } } catch (Exception ignored) { } @@ -97,8 +147,16 @@ notifyDataSetChanged(); } + public void setNoOnclickListener(OnclickListener onclickListener) { this.noOnclickListener = onclickListener; + } + + public List<SwipeLayout> getSwipeLayoutList() { + if (this.swipeLayoutList == null) { + this.swipeLayoutList = new ArrayList<>(); + } + return this.swipeLayoutList; } /** @@ -152,6 +210,10 @@ public TextView capacityTv;//瑁呮満瀹归噺 public TextView powerTv;//鍙戠數鍔熺巼 public TextView stateTv;//鐢电珯鐘舵��(杩炴帴涓�,杩愯,绂荤嚎,鏁呴殰); + public RelativeLayout item_parent_rl;//鏉$洰鐖跺鍣� + public ImageView move_home_iv;//绉诲姩鐢电珯浣嶇疆 + public ImageView del_home_iv;//鍒犻櫎鐢电珯 + public SwipeLayout item_parent_swipeLayout;//鐖跺鍣� public MyViewHolder(@NonNull View itemView) { super(itemView); @@ -160,10 +222,20 @@ capacityTv = itemView.findViewById(R.id.fragment_house_list_line_capacity_tv); powerTv = itemView.findViewById(R.id.fragment_house_list_line_power_tv); stateTv = itemView.findViewById(R.id.fragment_house_list_line_state_tv); + item_parent_rl = itemView.findViewById(R.id.item_parent_rl); + move_home_iv = itemView.findViewById(R.id.move_home_iv); + del_home_iv = itemView.findViewById(R.id.del_home_iv); + item_parent_swipeLayout = itemView.findViewById(R.id.item_parent_swipeLayout); } } public interface OnclickListener { void onClick(int position, HouseIdBean houseIdBean); + + void onMoveClick(int position, HouseIdBean houseIdBean); + + void onDelClick(int position, HouseIdBean houseIdBean); + } + } diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/bean/HouseIdBean.java b/app/src/main/java/com/hdl/photovoltaic/ui/bean/HouseIdBean.java index 358c394..e9103d3 100644 --- a/app/src/main/java/com/hdl/photovoltaic/ui/bean/HouseIdBean.java +++ b/app/src/main/java/com/hdl/photovoltaic/ui/bean/HouseIdBean.java @@ -14,9 +14,20 @@ private String installedCapacity;//瑁呮満瀹归噺 private String power;//鍙戠數鍔熺巼 private String todayElectricity;//浠婂ぉ鍙戠數閲� + private int powerStationStatus;//鐢电珯鐘舵��(鐢电珯鐘舵�� 1:姝e父(杩愯),2:绂荤嚎,3:杩炴帴涓�,4:鏁呴殰) private String localSecret;//鏈湴閫氳绉橀挜 + private boolean isEdit = false;//鏄惁绉婚櫎鐢电珯浣嶇疆(true琛ㄧず绉婚櫎) + + public boolean isEdit() { + return isEdit; + } + + public void setEdit(boolean edit) { + isEdit = edit; + } + public String getHomeId() { return homeId == null ? "" : homeId; } diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java b/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java index cd222e3..957a31c 100644 --- a/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java +++ b/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java @@ -1,32 +1,20 @@ package com.hdl.photovoltaic.ui.powerstation; import android.Manifest; -import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; -import android.graphics.Movie; import android.hardware.camera2.CameraManager; import android.os.Bundle; import android.view.View; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.load.engine.GlideException; -import com.bumptech.glide.load.resource.gif.GifDrawable; -import com.bumptech.glide.request.RequestListener; -import com.bumptech.glide.request.target.Target; import com.google.gson.Gson; import com.hdl.linkpm.sdk.core.exception.HDLException; import com.hdl.photovoltaic.R; -import com.hdl.photovoltaic.config.AppConfigManage; import com.hdl.photovoltaic.config.ConstantManage; -import com.hdl.photovoltaic.config.UserConfigManage; import com.hdl.photovoltaic.databinding.FragmentHouseListBinding; import com.hdl.photovoltaic.base.CustomBaseFragment; import com.hdl.photovoltaic.enums.HomepageTitleTabSwitch; @@ -40,9 +28,7 @@ import com.hdl.photovoltaic.ui.adapter.HouseInfoAdapter; import com.hdl.photovoltaic.ui.bean.HouseIdBean; import com.hdl.photovoltaic.uni.HDLUniMP; -import com.hdl.photovoltaic.utils.GlideUtils; import com.hdl.photovoltaic.utils.PermissionUtils; -import com.hdl.photovoltaic.widget.MovieDrawable; import com.hdl.sdk.link.core.bean.eventbus.BaseEventBus; import com.hdl.sdk.link.core.utils.mqtt.MqttRecvClient; @@ -53,15 +39,7 @@ * (浣忓畢)鐢电珯鍒楄〃-鐣岄潰 */ public class HouseListFragment extends CustomBaseFragment { - - public static final String SORT_TYPE_1 = "powerSort";//鍙戠數鍔熺巼鎺掑簭 - public static final String SORT_TYPE_2 = "todayElectricitySort";//浠婃棩鍙戠數閲忔帓搴� - public static final String SORT_TYPE_3 = "createTimeSort";//鍒涘缓鏃堕棿鎺掑簭 - public static final String DESCENDING = "descending";//闄嶅簭 - public static final String ASCENDING = "ascending";//鍗囧簭 - public static final String SELECTED_SORT_TYPE = SORT_TYPE_1; - public static final String SELECTED_SORT = DESCENDING; - + private boolean is_edit = false; private FragmentHouseListBinding viewBinding; private HouseInfoAdapter houseInfoAdapter; private CameraManager manager; @@ -87,14 +65,23 @@ private void initEvent() { - + viewBinding.toolbarTopFragmentHouseListRl.topBackBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (is_edit) { + is_edit = false; + } + viewBinding.toolbarTopFragmentHouseListRl.topBackBtn.setVisibility(View.GONE); + initData();//鍒濆鍖栫紦瀛樻暟鎹� + setAllItemEdit(false); + houseInfoAdapter.setList(houseListBeanIDList);//閲嶆柊鍒锋柊鍒楄〃 + } + }); //娣诲姞鐢电珯 viewBinding.toolbarTopFragmentHouseListRl.topMoreIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - HdlUniLogic.getInstance().openUniMP(HDLUniMP.UNI_EVENT_OPEN_HOME_CREATION, null); - // requestPermissions(new PermissionsResultCallback() { // @Override // public void succeed() { @@ -119,10 +106,11 @@ viewBinding.fragmentHouseSrl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { - updateUIData(true); + downReadData(true); HdlLogLogic.print("HouseListFragment涓嬫媺鍒锋柊", false); } }); + //杩涘叆鐢电珯璇︽儏,鍒犻櫎鐢电珯,绉诲姩鐢电珯浣嶇疆 houseInfoAdapter.setNoOnclickListener(new HouseInfoAdapter.OnclickListener() { @Override public void onClick(int position, HouseIdBean houseIdBean) { @@ -136,11 +124,88 @@ HdlUniLogic.getInstance().openUniMP(path, null); } + + @Override + public void onMoveClick(int position, HouseIdBean houseIdBean) { + if (position > 0) { + houseInfoAdapter.notifyItemMoved(position - 1, position); + } +// //绉诲姩鐢电珯浣嶇疆 +// HdlResidenceLogic.getInstance().moveHouseId(houseIdBean.getHomeId()); +// initData();//鍒濆鍖栫紦瀛樻暟鎹� +// houseInfoAdapter.setList(houseListBeanIDList);//閲嶆柊鍒锋柊鍒楄〃 +// nullDataUpdateUi(houseListBeanIDList);//妫�娴嬫暟鎹槸鍚︿负绌� + + } + + @Override + public void onDelClick(int position, HouseIdBean houseIdBean) { + + HdlResidenceLogic.getInstance().delHouseId(houseIdBean.getHomeId()); + initData();//鍒濆鍖栫紦瀛樻暟鎹� + houseInfoAdapter.notifyItemRemoved(position); + +// DelayedConfirmationCancelDialog delayedConfirmationCancelDialog = new DelayedConfirmationCancelDialog(_mActivity); +// delayedConfirmationCancelDialog.setTitle(R.string.loading_title_tip); +// delayedConfirmationCancelDialog.setContent("鏄惁纭鍒犻櫎鐢电珯?"); +// delayedConfirmationCancelDialog.show(); +// delayedConfirmationCancelDialog.startCountdown(3); +// delayedConfirmationCancelDialog.setYesOnclickListener(new ConfirmationCancelDialog.onYesOnclickListener() { +// @Override +// public void Confirm() { +// //鍒犻櫎浣忓畢 +// HdlResidenceLogic.getInstance().delResidence(houseIdBean.getHomeId(), new CloudCallBeak<Boolean>() { +// @Override +// public void onSuccess(Boolean obj) { +// HdlResidenceLogic.getInstance().delHouseId(houseIdBean.getHomeId()); +// initData();//鍒濆鍖栫紦瀛樻暟鎹� +// setAllItemEdit(is_edit); +// houseInfoAdapter.setList(houseListBeanIDList);//閲嶆柊鍒锋柊鍒楄〃 +// nullDataUpdateUi(houseListBeanIDList);//妫�娴嬫暟鎹槸鍚︿负绌� +// delayedConfirmationCancelDialog.dismiss(); +// } +// +// @Override +// public void onFailure(HDLException e) { +// HdlThreadLogic.toast(_mActivity, e); +// } +// }); +// } +// }); +// delayedConfirmationCancelDialog.setNoOnclickListener(new ConfirmationCancelDialog.onNoOnclickListener() { +// @Override +// public void Cancel() { +// delayedConfirmationCancelDialog.dismiss(); +// } +// }); + + } + }); + + //缂栬緫鐢电珯鎸夐挳 + viewBinding.toolbarTopFragmentHouseListRl.topEditIv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (is_edit) { + //闃叉澶氭鐐瑰嚮 + return; + } + is_edit = true; + viewBinding.toolbarTopFragmentHouseListRl.topBackBtn.setVisibility(View.VISIBLE); + if (houseInfoAdapter == null) { + return; + } + initData();//鍒濆鍖栫紦瀛樻暟鎹� + setAllItemEdit(true); + houseInfoAdapter.setList(houseListBeanIDList);//閲嶆柊鍒锋柊鍒楄〃 + } }); } private void initView() { viewBinding.toolbarTopFragmentHouseListRl.topTitleTv.setText(R.string.my_power_station); + viewBinding.toolbarTopFragmentHouseListRl.topEditIv.setVisibility(View.VISIBLE); + viewBinding.toolbarTopFragmentHouseListRl.topEditIv.setImageResource(R.drawable.editor_house); viewBinding.toolbarTopFragmentHouseListRl.topMoreIv.setVisibility(View.VISIBLE); viewBinding.toolbarTopFragmentHouseListRl.topMoreIv.setImageResource(R.drawable.add); LinearLayoutManager linearLayout = new LinearLayoutManager(_mActivity); @@ -169,7 +234,7 @@ if (HDLUniMP.UNI_EVENT_REPLY_HOME_MODEL.equals(eventBus.getTopic())) { if (HDLUniMP.UNI_EVENT_REPLY_HOME_CREATION.equals(eventBus.getType())) { //uin鍒涘缓鐢电珯鎴愬姛鍚庨�氱煡 - updateUIData(false); + downReadData(false); if (eventBus.getData() != null) { Gson gson = new Gson(); String json = eventBus.getData().toString(); @@ -208,7 +273,7 @@ if (MqttRecvClient.getInstance() != null) { MqttRecvClient.getInstance().removeAllTopic(); } - updateUIData(false); + downReadData(false); } else if (HDLUniMP.UNI_EVENT_REPLY_DEVICE_LIST.equals(eventBus.getType())) { //杩涘幓浣忓畢璇︽儏uni璇诲彇閫嗗彉鍣ㄥ垪琛ㄦ垚鍔熷悗閫氱煡 @@ -227,12 +292,24 @@ } } + + /** + * 璁剧疆鍏ㄩ儴缂撳瓨鏁版嵁缂栬緫鐘舵�� + * + * @param edit true琛ㄧず鍦ㄧ紪杈戠姸鎬� + */ + private void setAllItemEdit(boolean edit) { + for (int i = 0; i < houseListBeanIDList.size(); i++) { + houseListBeanIDList.get(i).setEdit(edit); + } + } + /** * 鍒锋柊UI * * @param isRefreshing 琛ㄧず鏄笅鎷夊埛鏂扮殑 */ - private void updateUIData(boolean isRefreshing) { + private void downReadData(boolean isRefreshing) { //鑾峰彇浣忓畢(鐢电珯)ID鍒楄〃 HdlResidenceLogic.getInstance().getResidenceIdList("", "", new CloudCallBeak<List<HouseIdBean>>() { @Override @@ -248,8 +325,10 @@ //鏇存柊缂撳瓨 HdlResidenceLogic.getInstance().setHouseIdList(list); if (houseInfoAdapter != null) { + initData(); + setAllItemEdit(is_edit); //鏇存柊UI - houseInfoAdapter.setList(list); + houseInfoAdapter.setList(houseListBeanIDList); } } diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/DelayedConfirmationCancelDialog.java b/app/src/main/java/com/hdl/photovoltaic/widget/DelayedConfirmationCancelDialog.java new file mode 100644 index 0000000..f260d96 --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/DelayedConfirmationCancelDialog.java @@ -0,0 +1,241 @@ +package com.hdl.photovoltaic.widget; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.text.TextUtils; +import android.view.View; + +import androidx.annotation.NonNull; + +import com.hdl.photovoltaic.R; +import com.hdl.photovoltaic.databinding.DialogConfirmCancelBinding; + +/** + * 寤舵椂纭妗� + */ +public class DelayedConfirmationCancelDialog extends Dialog { + public DelayedConfirmationCancelDialog(@NonNull Context context) { + super(context, R.style.Custom_Dialog); + this.mContext = context; + } + + CountDownTimer timer; + private final Context mContext; + private ConfirmationCancelDialog.onNoOnclickListener noOnclickListener;//鍙栨秷鎸夐挳琚偣鍑讳簡鐨勭洃鍚櫒 + private ConfirmationCancelDialog.onYesOnclickListener yesOnclickListener;//纭畾鎸夐挳琚偣鍑讳簡鐨勭洃鍚櫒 + private DialogConfirmCancelBinding viewBinding; + private String titleStr, contentStr, yesStr, noStr; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + viewBinding = DialogConfirmCancelBinding.inflate(getLayoutInflater()); + setContentView(viewBinding.getRoot()); +// setCancelable(true);//绯荤粺鍚庨��鍙互鍙栨秷 + //绌虹櫧澶勪笉鑳藉彇娑堝姩鐢� + setCanceledOnTouchOutside(false); + //鍒濆鍖栫晫闈㈡帶浠� + initView(); + //鍒濆鍖栫晫闈㈡暟鎹� + initData(); + //鍒濆鍖栫晫闈㈡帶浠剁殑浜嬩欢 + initEvent(); + + } + + /** + * 鑷畾涔�"鏍囬"鏂囨湰 + * + * @param title 鍐呭 + */ + public void setTitle(String title) { + if (TextUtils.isEmpty(title)) { + return; + } + titleStr = title; + if (viewBinding != null) { + viewBinding.loadingConfirmationTitleTv.setText(titleStr); + } + + } + + /** + * 鑷畾涔�"纭"鏂囨湰 + * + * @param confirm 鍐呭 + */ + public void setConfirmation(String confirm) { + if (TextUtils.isEmpty(confirm)) { + return; + } + yesStr = confirm; + + + if (viewBinding != null) { + viewBinding.dialogConfirmTv.setText(yesStr); + } + + } + + /** + * 鑷畾涔�"纭"鏂囨湰棰滆壊 + */ + public void setConfirmationColor(int color) { + if (viewBinding != null) { + viewBinding.dialogConfirmTv.setTextColor(color); + } + + + } + + /** + * 鑷畾涔�"鍙栨秷"鏂囨湰 + * + * @param cancel 鍐呭 + */ + public void setCancel(String cancel) { + if (TextUtils.isEmpty(cancel)) { + return; + } + noStr = cancel; + if (viewBinding != null) { + viewBinding.dialogCancelTv.setText(noStr); + } + + } + + /** + * 鑷畾涔�"鍐呭"鏂囨湰 + * + * @param content 鍐呭 + */ + public void setContent(String content) { + if (TextUtils.isEmpty(content)) { + return; + } + contentStr = content; + if (viewBinding != null) { + viewBinding.loadingConfirmationContentTv.setText(contentStr); + } + } + + private void initEvent() { + viewBinding.dialogCancelLy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (noOnclickListener != null) { + noOnclickListener.Cancel(); + } + } + }); + viewBinding.dialogConfirmLy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (yesOnclickListener != null) { + yesOnclickListener.Confirm(); + } + } + }); + + + } + + + /** + * 鍒濆鍖栫晫闈㈡帶浠剁殑鏄剧ず鏁版嵁 + */ + private void initData() { + //濡傛灉鐢ㄦ埛鑷畾浜唗itle鍜宮essage + if (!TextUtils.isEmpty(titleStr)) { + viewBinding.loadingConfirmationTitleTv.setText(titleStr); + } + if (!TextUtils.isEmpty(contentStr)) { + viewBinding.loadingConfirmationContentTv.setText(contentStr); + } + //濡傛灉璁剧疆鎸夐挳鏂囧瓧 + if (!TextUtils.isEmpty(yesStr)) { + viewBinding.dialogConfirmTv.setText(yesStr); + } + if (!TextUtils.isEmpty(noStr)) { + viewBinding.dialogCancelTv.setText(noStr); + } + } + + private void initView() { + + + } + + /** + * 寮�濮嬪�掕鏃� + * + * @param seconds 琛ㄧず澶氬皯绉� + */ + public void startCountdown(long seconds) { + if (timer != null) { + timer.cancel(); + timer = null; + } + timer = new CountDownTimer(seconds * 1000, 1000) { // 璁剧疆鍊掕鏃朵负3绉掞紙鍗曚綅锛氭绉掞級 + public void onTick(long millisUntilFinished) { + int secondsRemaining = (int) (millisUntilFinished / 1000); + String timeLeft = "(" + secondsRemaining + ")"; + String text = mContext.getString(R.string.loading_affirm) + timeLeft; + viewBinding.dialogConfirmTv.setText(text); + viewBinding.dialogConfirmTv.setTextColor(Color.parseColor("#C2EDDE")); + viewBinding.dialogConfirmLy.setEnabled(false); + viewBinding.dialogConfirmTv.setEnabled(false); + } + + public void onFinish() { + viewBinding.dialogConfirmTv.setText(mContext.getString(R.string.loading_affirm)); + viewBinding.dialogConfirmTv.setTextColor(Color.parseColor("#38C494")); + viewBinding.dialogConfirmLy.setEnabled(true); + viewBinding.dialogConfirmTv.setEnabled(true); + if (timer != null) { + timer.cancel(); + timer = null; + } + } + }; + + timer.start(); + } + + + /** + * 璁剧疆鍙栨秷鎸夐挳鐩戝惉 + * + * @param onNoOnclickListener - + */ + public void setNoOnclickListener(ConfirmationCancelDialog.onNoOnclickListener onNoOnclickListener) { + if (onNoOnclickListener != null) { + this.noOnclickListener = onNoOnclickListener; + } + } + + /** + * 璁剧疆纭畾鎸夐挳鐩戝惉 + * + * @param yesOnclickListener - + */ + public void setYesOnclickListener(ConfirmationCancelDialog.onYesOnclickListener yesOnclickListener) { + if (yesOnclickListener != null) { + this.yesOnclickListener = yesOnclickListener; + } + + } + + public interface onNoOnclickListener { + void Cancel(); + + } + + public interface onYesOnclickListener { + void Confirm(); + } +} diff --git a/app/src/main/java/com/hdl/photovoltaic/widget/SwipeLayout.java b/app/src/main/java/com/hdl/photovoltaic/widget/SwipeLayout.java new file mode 100644 index 0000000..d41e049 --- /dev/null +++ b/app/src/main/java/com/hdl/photovoltaic/widget/SwipeLayout.java @@ -0,0 +1,1557 @@ +package com.hdl.photovoltaic.widget; + + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.FrameLayout; + +import androidx.annotation.Nullable; +import androidx.core.view.GravityCompat; +import androidx.core.view.ViewCompat; +import androidx.customview.widget.ViewDragHelper; + + +import com.hdl.photovoltaic.R; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class SwipeLayout extends FrameLayout { + + public static final int EMPTY_LAYOUT = -1; + private static final int DRAG_LEFT = 1; + private static final int DRAG_RIGHT = 2; + private static final int DRAG_TOP = 4; + private static final int DRAG_BOTTOM = 8; + private static final DragEdge DefaultDragEdge = DragEdge.Right; + + private int mTouchSlop; + + private DragEdge mCurrentDragEdge = DefaultDragEdge; + private ViewDragHelper mDragHelper; + + private int mDragDistance = 0; + private LinkedHashMap<DragEdge, View> mDragEdges = new LinkedHashMap<DragEdge, View>(); + private ShowMode mShowMode; + + private float[] mEdgeSwipesOffset = new float[4]; + + private List<SwipeListener> mSwipeListeners = new ArrayList<SwipeListener>(); + private List<SwipeDenier> mSwipeDeniers = new ArrayList<SwipeDenier>(); + private Map<View, ArrayList<OnRevealListener>> mRevealListeners = new HashMap<View, ArrayList<OnRevealListener>>(); + private Map<View, Boolean> mShowEntirely = new HashMap<View, Boolean>(); + + private DoubleClickListener mDoubleClickListener; + + private boolean mSwipeEnabled = true; + private boolean[] mSwipesEnabled = new boolean[]{true, true, true, true}; + private boolean mClickToClose = false; + + public static enum DragEdge { + Left, + Top, + Right, + Bottom + } + + public static enum ShowMode { + LayDown, + PullOut + } + + public SwipeLayout(Context context) { + this(context, null); + } + + public SwipeLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SwipeLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mDragHelper = ViewDragHelper.create(this, mDragHelperCallback); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwipeLayout); + int dragEdgeChoices = a.getInt(R.styleable.SwipeLayout_drag_edge, DRAG_RIGHT); + mEdgeSwipesOffset[DragEdge.Left.ordinal()] = a.getDimension(R.styleable.SwipeLayout_leftEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Right.ordinal()] = a.getDimension(R.styleable.SwipeLayout_rightEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Top.ordinal()] = a.getDimension(R.styleable.SwipeLayout_topEdgeSwipeOffset, 0); + mEdgeSwipesOffset[DragEdge.Bottom.ordinal()] = a.getDimension(R.styleable.SwipeLayout_bottomEdgeSwipeOffset, 0); + setClickToClose(a.getBoolean(R.styleable.SwipeLayout_clickToClose, mClickToClose)); + + if ((dragEdgeChoices & DRAG_LEFT) == DRAG_LEFT) { + mDragEdges.put(DragEdge.Left, null); + } + if ((dragEdgeChoices & DRAG_TOP) == DRAG_TOP) { + mDragEdges.put(DragEdge.Top, null); + } + if ((dragEdgeChoices & DRAG_RIGHT) == DRAG_RIGHT) { + mDragEdges.put(DragEdge.Right, null); + } + if ((dragEdgeChoices & DRAG_BOTTOM) == DRAG_BOTTOM) { + mDragEdges.put(DragEdge.Bottom, null); + } + int ordinal = a.getInt(R.styleable.SwipeLayout_show_mode, ShowMode.PullOut.ordinal()); + mShowMode = ShowMode.values()[ordinal]; + a.recycle(); + + } + + public interface SwipeListener { + public void onStartOpen(SwipeLayout layout); + + public void onOpen(SwipeLayout layout); + + public void onStartClose(SwipeLayout layout); + + public void onClose(SwipeLayout layout); + + public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset); + + public void onHandRelease(SwipeLayout layout, float xvel, float yvel); + } + + + public void addSwipeListener(SwipeListener l) { + mSwipeListeners.clear(); + mSwipeListeners.add(l); + } + + public void removeSwipeListener(SwipeListener l) { + mSwipeListeners.remove(l); + } + + public static interface SwipeDenier { + /* + * Called in onInterceptTouchEvent Determines if this swipe event should + * be denied Implement this interface if you are using views with swipe + * gestures As a child of SwipeLayout + * + * @return true deny false allow + */ + public boolean shouldDenySwipe(MotionEvent ev); + } + + public void addSwipeDenier(SwipeDenier denier) { + mSwipeDeniers.add(denier); + } + + public void removeSwipeDenier(SwipeDenier denier) { + mSwipeDeniers.remove(denier); + } + + public void removeAllSwipeDeniers() { + mSwipeDeniers.clear(); + } + + public interface OnRevealListener { + public void onReveal(View child, DragEdge edge, float fraction, int distance); + } + + /** + * bind a view with a specific + * + * @param childId the view id. + * @param l the target + */ + public void addRevealListener(int childId, OnRevealListener l) { + View child = findViewById(childId); + if (child == null) { + throw new IllegalArgumentException("Child does not belong to SwipeListener."); + } + + if (!mShowEntirely.containsKey(child)) { + mShowEntirely.put(child, false); + } + if (mRevealListeners.get(child) == null) + mRevealListeners.put(child, new ArrayList<OnRevealListener>()); + + mRevealListeners.get(child).add(l); + } + + /** + * bind multiple views with an + * + * @param childIds the view id. + * @param l + */ + public void addRevealListener(int[] childIds, OnRevealListener l) { + for (int i : childIds) + addRevealListener(i, l); + } + + public void removeRevealListener(int childId, OnRevealListener l) { + View child = findViewById(childId); + + if (child == null) return; + + mShowEntirely.remove(child); + if (mRevealListeners.containsKey(child)) mRevealListeners.get(child).remove(l); + } + + public void removeAllRevealListeners(int childId) { + View child = findViewById(childId); + if (child != null) { + mRevealListeners.remove(child); + mShowEntirely.remove(child); + } + } + + private ViewDragHelper.Callback mDragHelperCallback = new ViewDragHelper.Callback() { + + @Override + public int clampViewPositionHorizontal(View child, int left, int dx) { + if (child == getSurfaceView()) { + switch (mCurrentDragEdge) { + case Top: + case Bottom: + return getPaddingLeft(); + case Left: + if (left < getPaddingLeft()) return getPaddingLeft(); + if (left > getPaddingLeft() + mDragDistance) + return getPaddingLeft() + mDragDistance; + break; + case Right: + if (left > getPaddingLeft()) return getPaddingLeft(); + if (left < getPaddingLeft() - mDragDistance) + return getPaddingLeft() - mDragDistance; + break; + } + } else if (getCurrentBottomView() == child) { + + switch (mCurrentDragEdge) { + case Top: + case Bottom: + return getPaddingLeft(); + case Left: + if (mShowMode == ShowMode.PullOut) { + if (left > getPaddingLeft()) return getPaddingLeft(); + } + break; + case Right: + if (mShowMode == ShowMode.PullOut) { + if (left < getMeasuredWidth() - mDragDistance) { + return getMeasuredWidth() - mDragDistance; + } + } + break; + } + } + return left; + } + + @Override + public int clampViewPositionVertical(View child, int top, int dy) { + if (child == getSurfaceView()) { + switch (mCurrentDragEdge) { + case Left: + case Right: + return getPaddingTop(); + case Top: + if (top < getPaddingTop()) return getPaddingTop(); + if (top > getPaddingTop() + mDragDistance) + return getPaddingTop() + mDragDistance; + break; + case Bottom: + if (top < getPaddingTop() - mDragDistance) { + return getPaddingTop() - mDragDistance; + } + if (top > getPaddingTop()) { + return getPaddingTop(); + } + } + } else { + View surfaceView = getSurfaceView(); + int surfaceViewTop = surfaceView == null ? 0 : surfaceView.getTop(); + switch (mCurrentDragEdge) { + case Left: + case Right: + return getPaddingTop(); + case Top: + if (mShowMode == ShowMode.PullOut) { + if (top > getPaddingTop()) return getPaddingTop(); + } else { + if (surfaceViewTop + dy < getPaddingTop()) + return getPaddingTop(); + if (surfaceViewTop + dy > getPaddingTop() + mDragDistance) + return getPaddingTop() + mDragDistance; + } + break; + case Bottom: + if (mShowMode == ShowMode.PullOut) { + if (top < getMeasuredHeight() - mDragDistance) + return getMeasuredHeight() - mDragDistance; + } else { + if (surfaceViewTop + dy >= getPaddingTop()) + return getPaddingTop(); + if (surfaceViewTop + dy <= getPaddingTop() - mDragDistance) + return getPaddingTop() - mDragDistance; + } + } + } + return top; + } + + @Override + public boolean tryCaptureView(View child, int pointerId) { + boolean result = child == getSurfaceView() || getBottomViews().contains(child); + if (result) { + isCloseBeforeDrag = getOpenStatus() == Status.Close; + } + return result; + } + + @Override + public int getViewHorizontalDragRange(View child) { + return mDragDistance; + } + + @Override + public int getViewVerticalDragRange(View child) { + return mDragDistance; + } + + boolean isCloseBeforeDrag = true; + + @Override + public void onViewReleased(View releasedChild, float xvel, float yvel) { + super.onViewReleased(releasedChild, xvel, yvel); + for (SwipeListener l : mSwipeListeners) { + l.onHandRelease(SwipeLayout.this, xvel, yvel); + } + processHandRelease(xvel, yvel, isCloseBeforeDrag); + + invalidate(); + } + + @Override + public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { + View surfaceView = getSurfaceView(); + if (surfaceView == null) return; + View currentBottomView = getCurrentBottomView(); + int evLeft = surfaceView.getLeft(), + evRight = surfaceView.getRight(), + evTop = surfaceView.getTop(), + evBottom = surfaceView.getBottom(); + if (changedView == surfaceView) { + + if (mShowMode == ShowMode.PullOut && currentBottomView != null) { + if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) { + currentBottomView.offsetLeftAndRight(dx); + } else { + currentBottomView.offsetTopAndBottom(dy); + } + } + + } else if (getBottomViews().contains(changedView)) { + + if (mShowMode == ShowMode.PullOut) { + surfaceView.offsetLeftAndRight(dx); + surfaceView.offsetTopAndBottom(dy); + } else { + Rect rect = computeBottomLayDown(mCurrentDragEdge); + if (currentBottomView != null) { + currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + } + + int newLeft = surfaceView.getLeft() + dx, newTop = surfaceView.getTop() + dy; + + if (mCurrentDragEdge == DragEdge.Left && newLeft < getPaddingLeft()) + newLeft = getPaddingLeft(); + else if (mCurrentDragEdge == DragEdge.Right && newLeft > getPaddingLeft()) + newLeft = getPaddingLeft(); + else if (mCurrentDragEdge == DragEdge.Top && newTop < getPaddingTop()) + newTop = getPaddingTop(); + else if (mCurrentDragEdge == DragEdge.Bottom && newTop > getPaddingTop()) + newTop = getPaddingTop(); + + surfaceView.layout(newLeft, newTop, newLeft + getMeasuredWidth(), newTop + getMeasuredHeight()); + } + } + + dispatchRevealEvent(evLeft, evTop, evRight, evBottom); + + dispatchSwipeEvent(evLeft, evTop, dx, dy); + + invalidate(); + } + }; + + /** + * the dispatchRevealEvent method may not always get accurate position, it + * makes the view may not always get the event when the view is totally + * show( fraction = 1), so , we need to calculate every time. + */ + protected boolean isViewTotallyFirstShowed(View child, Rect relativePosition, DragEdge edge, int surfaceLeft, + int surfaceTop, int surfaceRight, int surfaceBottom) { + if (mShowEntirely.get(child)) return false; + int childLeft = relativePosition.left; + int childRight = relativePosition.right; + int childTop = relativePosition.top; + int childBottom = relativePosition.bottom; + boolean r = false; + if (getShowMode() == ShowMode.LayDown) { + if ((edge == DragEdge.Right && surfaceRight <= childLeft) + || (edge == DragEdge.Left && surfaceLeft >= childRight) + || (edge == DragEdge.Top && surfaceTop >= childBottom) + || (edge == DragEdge.Bottom && surfaceBottom <= childTop)) r = true; + } else if (getShowMode() == ShowMode.PullOut) { + if ((edge == DragEdge.Right && childRight <= getWidth()) + || (edge == DragEdge.Left && childLeft >= getPaddingLeft()) + || (edge == DragEdge.Top && childTop >= getPaddingTop()) + || (edge == DragEdge.Bottom && childBottom <= getHeight())) r = true; + } + return r; + } + + protected boolean isViewShowing(View child, Rect relativePosition, DragEdge availableEdge, int surfaceLeft, + int surfaceTop, int surfaceRight, int surfaceBottom) { + int childLeft = relativePosition.left; + int childRight = relativePosition.right; + int childTop = relativePosition.top; + int childBottom = relativePosition.bottom; + if (getShowMode() == ShowMode.LayDown) { + switch (availableEdge) { + case Right: + if (surfaceRight > childLeft && surfaceRight <= childRight) { + return true; + } + break; + case Left: + if (surfaceLeft < childRight && surfaceLeft >= childLeft) { + return true; + } + break; + case Top: + if (surfaceTop >= childTop && surfaceTop < childBottom) { + return true; + } + break; + case Bottom: + if (surfaceBottom > childTop && surfaceBottom <= childBottom) { + return true; + } + break; + } + } else if (getShowMode() == ShowMode.PullOut) { + switch (availableEdge) { + case Right: + if (childLeft <= getWidth() && childRight > getWidth()) return true; + break; + case Left: + if (childRight >= getPaddingLeft() && childLeft < getPaddingLeft()) return true; + break; + case Top: + if (childTop < getPaddingTop() && childBottom >= getPaddingTop()) return true; + break; + case Bottom: + if (childTop < getHeight() && childTop >= getPaddingTop()) return true; + break; + } + } + return false; + } + + protected Rect getRelativePosition(View child) { + View t = child; + Rect r = new Rect(t.getLeft(), t.getTop(), 0, 0); + while (t.getParent() != null && t != getRootView()) { + t = (View) t.getParent(); + if (t == this) break; + r.left += t.getLeft(); + r.top += t.getTop(); + } + r.right = r.left + child.getMeasuredWidth(); + r.bottom = r.top + child.getMeasuredHeight(); + return r; + } + + private int mEventCounter = 0; + + protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, int dx, int dy) { + DragEdge edge = getDragEdge(); + boolean open = true; + if (edge == DragEdge.Left) { + if (dx < 0) open = false; + } else if (edge == DragEdge.Right) { + if (dx > 0) open = false; + } else if (edge == DragEdge.Top) { + if (dy < 0) open = false; + } else if (edge == DragEdge.Bottom) { + if (dy > 0) open = false; + } + + dispatchSwipeEvent(surfaceLeft, surfaceTop, open); + } + + protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, boolean open) { + safeBottomView(); + Status status = getOpenStatus(); + + if (!mSwipeListeners.isEmpty()) { + mEventCounter++; + for (SwipeListener l : mSwipeListeners) { + if (mEventCounter == 1) { + if (open) { + l.onStartOpen(this); + } else { + l.onStartClose(this); + } + } + l.onUpdate(SwipeLayout.this, surfaceLeft - getPaddingLeft(), surfaceTop - getPaddingTop()); + } + + if (status == Status.Close) { + for (SwipeListener l : mSwipeListeners) { + l.onClose(SwipeLayout.this); + } + mEventCounter = 0; + } + + if (status == Status.Open) { + View currentBottomView = getCurrentBottomView(); + if (currentBottomView != null) { + currentBottomView.setEnabled(true); + } + for (SwipeListener l : mSwipeListeners) { + l.onOpen(SwipeLayout.this); + } + mEventCounter = 0; + } + } + } + + /** + * prevent bottom view get any touch event. Especially in LayDown mode. + */ + private void safeBottomView() { + Status status = getOpenStatus(); + List<View> bottoms = getBottomViews(); + + if (status == Status.Close) { + for (View bottom : bottoms) { + if (bottom != null && bottom.getVisibility() != INVISIBLE) { + bottom.setVisibility(INVISIBLE); + } + } + } else { + View currentBottomView = getCurrentBottomView(); + if (currentBottomView != null && currentBottomView.getVisibility() != VISIBLE) { + currentBottomView.setVisibility(VISIBLE); + } + } + } + + protected void dispatchRevealEvent(final int surfaceLeft, final int surfaceTop, final int surfaceRight, + final int surfaceBottom) { + if (mRevealListeners.isEmpty()) return; + for (Map.Entry<View, ArrayList<OnRevealListener>> entry : mRevealListeners.entrySet()) { + View child = entry.getKey(); + Rect rect = getRelativePosition(child); + if (isViewShowing(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop, + surfaceRight, surfaceBottom)) { + mShowEntirely.put(child, false); + int distance = 0; + float fraction = 0f; + if (getShowMode() == ShowMode.LayDown) { + switch (mCurrentDragEdge) { + case Left: + distance = rect.left - surfaceLeft; + fraction = distance / (float) child.getWidth(); + break; + case Right: + distance = rect.right - surfaceRight; + fraction = distance / (float) child.getWidth(); + break; + case Top: + distance = rect.top - surfaceTop; + fraction = distance / (float) child.getHeight(); + break; + case Bottom: + distance = rect.bottom - surfaceBottom; + fraction = distance / (float) child.getHeight(); + break; + } + } else if (getShowMode() == ShowMode.PullOut) { + switch (mCurrentDragEdge) { + case Left: + distance = rect.right - getPaddingLeft(); + fraction = distance / (float) child.getWidth(); + break; + case Right: + distance = rect.left - getWidth(); + fraction = distance / (float) child.getWidth(); + break; + case Top: + distance = rect.bottom - getPaddingTop(); + fraction = distance / (float) child.getHeight(); + break; + case Bottom: + distance = rect.top - getHeight(); + fraction = distance / (float) child.getHeight(); + break; + } + } + + for (OnRevealListener l : entry.getValue()) { + l.onReveal(child, mCurrentDragEdge, Math.abs(fraction), distance); + if (Math.abs(fraction) == 1) { + mShowEntirely.put(child, true); + } + } + } + + if (isViewTotallyFirstShowed(child, rect, mCurrentDragEdge, surfaceLeft, surfaceTop, + surfaceRight, surfaceBottom)) { + mShowEntirely.put(child, true); + for (OnRevealListener l : entry.getValue()) { + if (mCurrentDragEdge == DragEdge.Left + || mCurrentDragEdge == DragEdge.Right) + l.onReveal(child, mCurrentDragEdge, 1, child.getWidth()); + else + l.onReveal(child, mCurrentDragEdge, 1, child.getHeight()); + } + } + + } + } + + @Override + public void computeScroll() { + super.computeScroll(); + if (mDragHelper.continueSettling(true)) { + ViewCompat.postInvalidateOnAnimation(this); + } + } + + /** + * {@link OnLayoutChangeListener} added in API 11. I need + * to support it from API 8. + */ + public interface OnLayout { + public void onLayout(SwipeLayout v); + } + + private List<OnLayout> mOnLayoutListeners; + + public void addOnLayoutListener(OnLayout l) { + if (mOnLayoutListeners == null) mOnLayoutListeners = new ArrayList<OnLayout>(); + mOnLayoutListeners.add(l); + } + + public void removeOnLayoutListener(OnLayout l) { + if (mOnLayoutListeners != null) mOnLayoutListeners.remove(l); + } + + public void addDrag(DragEdge dragEdge, View child) { + addDrag(dragEdge, child, null); + } + + public void addDrag(DragEdge dragEdge, View child, ViewGroup.LayoutParams params) { + if (params == null) { + params = generateDefaultLayoutParams(); + } + if (!checkLayoutParams(params)) { + params = generateLayoutParams(params); + } + int gravity = -1; + switch (dragEdge) { + case Left: + gravity = Gravity.LEFT; + break; + case Right: + gravity = Gravity.RIGHT; + break; + case Top: + gravity = Gravity.TOP; + break; + case Bottom: + gravity = Gravity.BOTTOM; + break; + } + if (params instanceof LayoutParams) { + ((LayoutParams) params).gravity = gravity; + } + addView(child, 0, params); + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + int gravity = Gravity.NO_GRAVITY; + try { + gravity = (Integer) params.getClass().getField("gravity").get(params); + } catch (Exception e) { + e.printStackTrace(); + } + + if (gravity > 0) { + gravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)); + + if ((gravity & Gravity.LEFT) == Gravity.LEFT) { + mDragEdges.put(DragEdge.Left, child); + } + if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) { + mDragEdges.put(DragEdge.Right, child); + } + if ((gravity & Gravity.TOP) == Gravity.TOP) { + mDragEdges.put(DragEdge.Top, child); + } + if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) { + mDragEdges.put(DragEdge.Bottom, child); + } + } else { + for (Map.Entry<DragEdge, View> entry : mDragEdges.entrySet()) { + if (entry.getValue() == null) { + //means used the drag_edge attr, the no gravity child should be use set + mDragEdges.put(entry.getKey(), child); + break; + } + } + } + if (child == null || child.getParent() == this) { + return; + } + super.addView(child, index, params); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + updateBottomViews(); + + if (mOnLayoutListeners != null) for (int i = 0; i < mOnLayoutListeners.size(); i++) { + mOnLayoutListeners.get(i).onLayout(this); + } + } + + void layoutPullOut() { + Rect rect = computeSurfaceLayoutArea(false); + View surfaceView = getSurfaceView(); + if (surfaceView != null) { + surfaceView.layout(rect.left, rect.top, rect.right, rect.bottom); + bringChildToFront(surfaceView); + } + rect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect); + View currentBottomView = getCurrentBottomView(); + if (currentBottomView != null) { + currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + } + } + + void layoutLayDown() { + Rect rect = computeSurfaceLayoutArea(false); + View surfaceView = getSurfaceView(); + if (surfaceView != null) { + surfaceView.layout(rect.left, rect.top, rect.right, rect.bottom); + bringChildToFront(surfaceView); + } + rect = computeBottomLayoutAreaViaSurface(ShowMode.LayDown, rect); + View currentBottomView = getCurrentBottomView(); + if (currentBottomView != null) { + currentBottomView.layout(rect.left, rect.top, rect.right, rect.bottom); + } + } + + private boolean mIsBeingDragged; + + private void checkCanDrag(MotionEvent ev) { + if (mIsBeingDragged) return; + if (getOpenStatus() == Status.Middle) { + mIsBeingDragged = true; + return; + } + Status status = getOpenStatus(); + float distanceX = ev.getRawX() - sX; + float distanceY = ev.getRawY() - sY; + float angle = Math.abs(distanceY / distanceX); + angle = (float) Math.toDegrees(Math.atan(angle)); + if (getOpenStatus() == Status.Close) { + DragEdge dragEdge; + if (angle < 45) { + if (distanceX > 0 && isLeftSwipeEnabled()) { + dragEdge = DragEdge.Left; + } else if (distanceX < 0 && isRightSwipeEnabled()) { + dragEdge = DragEdge.Right; + } else return; + + } else { + if (distanceY > 0 && isTopSwipeEnabled()) { + dragEdge = DragEdge.Top; + } else if (distanceY < 0 && isBottomSwipeEnabled()) { + dragEdge = DragEdge.Bottom; + } else return; + } + setCurrentDragEdge(dragEdge); + } + + boolean doNothing = false; + if (mCurrentDragEdge == DragEdge.Right) { + boolean suitable = (status == Status.Open && distanceX > mTouchSlop) + || (status == Status.Close && distanceX < -mTouchSlop); + suitable = suitable || (status == Status.Middle); + + if (angle > 30 || !suitable) { + doNothing = true; + } + } + + if (mCurrentDragEdge == DragEdge.Left) { + boolean suitable = (status == Status.Open && distanceX < -mTouchSlop) + || (status == Status.Close && distanceX > mTouchSlop); + suitable = suitable || status == Status.Middle; + + if (angle > 30 || !suitable) { + doNothing = true; + } + } + + if (mCurrentDragEdge == DragEdge.Top) { + boolean suitable = (status == Status.Open && distanceY < -mTouchSlop) + || (status == Status.Close && distanceY > mTouchSlop); + suitable = suitable || status == Status.Middle; + + if (angle < 60 || !suitable) { + doNothing = true; + } + } + + if (mCurrentDragEdge == DragEdge.Bottom) { + boolean suitable = (status == Status.Open && distanceY > mTouchSlop) + || (status == Status.Close && distanceY < -mTouchSlop); + suitable = suitable || status == Status.Middle; + + if (angle < 60 || !suitable) { + doNothing = true; + } + } + mIsBeingDragged = !doNothing; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (!isSwipeEnabled()) { + return false; + } + if (mClickToClose && getOpenStatus() == Status.Open && isTouchOnSurface(ev)) { + return true; + } + for (SwipeDenier denier : mSwipeDeniers) { + if (denier != null && denier.shouldDenySwipe(ev)) { + return false; + } + } + + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + mDragHelper.processTouchEvent(ev); + mIsBeingDragged = false; + sX = ev.getRawX(); + sY = ev.getRawY(); + //if the swipe is in middle state(scrolling), should intercept the touch + if (getOpenStatus() == Status.Middle) { + mIsBeingDragged = true; + } + break; + case MotionEvent.ACTION_MOVE: + boolean beforeCheck = mIsBeingDragged; + checkCanDrag(ev); + if (mIsBeingDragged) { + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + if (!beforeCheck && mIsBeingDragged) { + //let children has one chance to catch the touch, and request the swipe not intercept + //useful when swipeLayout wrap a swipeLayout or other gestural layout + return false; + } + break; + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + mIsBeingDragged = false; + mDragHelper.processTouchEvent(ev); + break; + default://handle other action, such as ACTION_POINTER_DOWN/UP + mDragHelper.processTouchEvent(ev); + } + return mIsBeingDragged; + } + + private float sX = -1, sY = -1; + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isSwipeEnabled()) return super.onTouchEvent(event); + + int action = event.getActionMasked(); + gestureDetector.onTouchEvent(event); + + switch (action) { + case MotionEvent.ACTION_DOWN: + mDragHelper.processTouchEvent(event); + sX = event.getRawX(); + sY = event.getRawY(); + + + case MotionEvent.ACTION_MOVE: { + //the drag state and the direction are already judged at onInterceptTouchEvent + checkCanDrag(event); + if (mIsBeingDragged) { + getParent().requestDisallowInterceptTouchEvent(true); + mDragHelper.processTouchEvent(event); + } + break; + } + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mIsBeingDragged = false; + mDragHelper.processTouchEvent(event); + break; + + default://handle other action, such as ACTION_POINTER_DOWN/UP + mDragHelper.processTouchEvent(event); + } + + return super.onTouchEvent(event) || mIsBeingDragged || action == MotionEvent.ACTION_DOWN; + } + + public boolean isClickToClose() { + return mClickToClose; + } + + public void setClickToClose(boolean mClickToClose) { + this.mClickToClose = mClickToClose; + } + + public void setSwipeEnabled(boolean enabled) { + mSwipeEnabled = enabled; + } + + public boolean isSwipeEnabled() { + return mSwipeEnabled; + } + + public boolean isLeftSwipeEnabled() { + View bottomView = mDragEdges.get(DragEdge.Left); + return bottomView != null && bottomView.getParent() == this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Left.ordinal()]; + } + + public void setLeftSwipeEnabled(boolean leftSwipeEnabled) { + this.mSwipesEnabled[DragEdge.Left.ordinal()] = leftSwipeEnabled; + } + + public boolean isRightSwipeEnabled() { + View bottomView = mDragEdges.get(DragEdge.Right); + return bottomView != null && bottomView.getParent() == this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Right.ordinal()]; + } + + public void setRightSwipeEnabled(boolean rightSwipeEnabled) { + this.mSwipesEnabled[DragEdge.Right.ordinal()] = rightSwipeEnabled; + } + + public boolean isTopSwipeEnabled() { + View bottomView = mDragEdges.get(DragEdge.Top); + return bottomView != null && bottomView.getParent() == this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Top.ordinal()]; + } + + public void setTopSwipeEnabled(boolean topSwipeEnabled) { + this.mSwipesEnabled[DragEdge.Top.ordinal()] = topSwipeEnabled; + } + + public boolean isBottomSwipeEnabled() { + View bottomView = mDragEdges.get(DragEdge.Bottom); + return bottomView != null && bottomView.getParent() == this + && bottomView != getSurfaceView() && mSwipesEnabled[DragEdge.Bottom.ordinal()]; + } + + public void setBottomSwipeEnabled(boolean bottomSwipeEnabled) { + this.mSwipesEnabled[DragEdge.Bottom.ordinal()] = bottomSwipeEnabled; + } + + private boolean insideAdapterView() { + return getAdapterView() != null; + } + + private AdapterView getAdapterView() { + ViewParent t = getParent(); + if (t instanceof AdapterView) { + return (AdapterView) t; + } + return null; + } + + private void performAdapterViewItemClick() { + if (getOpenStatus() != Status.Close) return; + ViewParent t = getParent(); + if (t instanceof AdapterView) { + AdapterView view = (AdapterView) t; + int p = view.getPositionForView(SwipeLayout.this); + if (p != AdapterView.INVALID_POSITION) { + view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view + .getAdapter().getItemId(p)); + } + } + } + + private boolean performAdapterViewItemLongClick() { + if (getOpenStatus() != Status.Close) return false; + ViewParent t = getParent(); + if (t instanceof AdapterView) { + AdapterView view = (AdapterView) t; + int p = view.getPositionForView(SwipeLayout.this); + if (p == AdapterView.INVALID_POSITION) return false; + long vId = view.getItemIdAtPosition(p); + boolean handled = false; + try { + Method m = AbsListView.class.getDeclaredMethod("performLongPress", View.class, int.class, long.class); + m.setAccessible(true); + handled = (boolean) m.invoke(view, SwipeLayout.this, p, vId); + + } catch (Exception e) { + e.printStackTrace(); + + if (view.getOnItemLongClickListener() != null) { + handled = view.getOnItemLongClickListener().onItemLongClick(view, SwipeLayout.this, p, vId); + } + if (handled) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } + } + return handled; + } + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (insideAdapterView()) { + if (clickListener == null) { + setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + performAdapterViewItemClick(); + } + }); + } + if (longClickListener == null) { + setOnLongClickListener(new OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + performAdapterViewItemLongClick(); + return true; + } + }); + } + } + } + + OnClickListener clickListener; + + @Override + public void setOnClickListener(OnClickListener l) { + super.setOnClickListener(l); + clickListener = l; + } + + OnLongClickListener longClickListener; + + @Override + public void setOnLongClickListener(OnLongClickListener l) { + super.setOnLongClickListener(l); + longClickListener = l; + } + + private Rect hitSurfaceRect; + + private boolean isTouchOnSurface(MotionEvent ev) { + View surfaceView = getSurfaceView(); + if (surfaceView == null) { + return false; + } + if (hitSurfaceRect == null) { + hitSurfaceRect = new Rect(); + } + surfaceView.getHitRect(hitSurfaceRect); + return hitSurfaceRect.contains((int) ev.getX(), (int) ev.getY()); + } + + private GestureDetector gestureDetector = new GestureDetector(getContext(), new SwipeDetector()); + + class SwipeDetector extends GestureDetector.SimpleOnGestureListener { + @Override + public boolean onSingleTapUp(MotionEvent e) { + if (mClickToClose && isTouchOnSurface(e)) { + close(); + } + return super.onSingleTapUp(e); + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + if (mDoubleClickListener != null) { + View target; + View bottom = getCurrentBottomView(); + View surface = getSurfaceView(); + if (bottom != null && e.getX() > bottom.getLeft() && e.getX() < bottom.getRight() + && e.getY() > bottom.getTop() && e.getY() < bottom.getBottom()) { + target = bottom; + } else { + target = surface; + } + mDoubleClickListener.onDoubleClick(SwipeLayout.this, target == surface); + } + return true; + } + } + + /** + * set the drag distance, it will force set the bottom view's width or + * height via this value. + * + * @param max max distance in dp unit + */ + public void setDragDistance(int max) { + if (max < 0) max = 0; + mDragDistance = dp2px(max); + requestLayout(); + } + + /** + * There are 2 diffirent show mode. + * + * @param mode + */ + public void setShowMode(ShowMode mode) { + mShowMode = mode; + requestLayout(); + } + + public DragEdge getDragEdge() { + return mCurrentDragEdge; + } + + public int getDragDistance() { + return mDragDistance; + } + + public ShowMode getShowMode() { + return mShowMode; + } + + /** + * return null if there is no surface view(no children) + */ + public View getSurfaceView() { + if (getChildCount() == 0) return null; + return getChildAt(getChildCount() - 1); + } + + /** + * return null if there is no bottom view + */ + @Nullable + public View getCurrentBottomView() { + List<View> bottoms = getBottomViews(); + if (mCurrentDragEdge.ordinal() < bottoms.size()) { + return bottoms.get(mCurrentDragEdge.ordinal()); + } + return null; + } + + /** + * @return all bottomViews: left, top, right, bottom (may null if the edge is not set) + */ + public List<View> getBottomViews() { + ArrayList<View> bottoms = new ArrayList<View>(); + for (DragEdge dragEdge : DragEdge.values()) { + bottoms.add(mDragEdges.get(dragEdge)); + } + return bottoms; + } + + public enum Status { + Middle, + Open, + Close + } + + /** + * get the open status. + */ + public Status getOpenStatus() { + View surfaceView = getSurfaceView(); + if (surfaceView == null) { + return Status.Close; + } + int surfaceLeft = surfaceView.getLeft(); + int surfaceTop = surfaceView.getTop(); + if (surfaceLeft == getPaddingLeft() && surfaceTop == getPaddingTop()) return Status.Close; + + if (surfaceLeft == (getPaddingLeft() - mDragDistance) || surfaceLeft == (getPaddingLeft() + mDragDistance) + || surfaceTop == (getPaddingTop() - mDragDistance) || surfaceTop == (getPaddingTop() + mDragDistance)) + return Status.Open; + + return Status.Middle; + } + + + /** + * Process the surface release event. + * + * @param xvel xVelocity + * @param yvel yVelocity + * @param isCloseBeforeDragged the open state before drag + */ + protected void processHandRelease(float xvel, float yvel, boolean isCloseBeforeDragged) { + float minVelocity = mDragHelper.getMinVelocity(); + View surfaceView = getSurfaceView(); + DragEdge currentDragEdge = mCurrentDragEdge; + if (currentDragEdge == null || surfaceView == null) { + return; + } + float willOpenPercent = (isCloseBeforeDragged ? .25f : .75f); + if (currentDragEdge == DragEdge.Left) { + if (xvel > minVelocity) open(); + else if (xvel < -minVelocity) close(); + else { + float openPercent = 1f * getSurfaceView().getLeft() / mDragDistance; + if (openPercent > willOpenPercent) open(); + else close(); + } + } else if (currentDragEdge == DragEdge.Right) { + if (xvel > minVelocity) close(); + else if (xvel < -minVelocity) open(); + else { + float openPercent = 1f * (-getSurfaceView().getLeft()) / mDragDistance; + if (openPercent > willOpenPercent) open(); + else close(); + } + } else if (currentDragEdge == DragEdge.Top) { + if (yvel > minVelocity) open(); + else if (yvel < -minVelocity) close(); + else { + float openPercent = 1f * getSurfaceView().getTop() / mDragDistance; + if (openPercent > willOpenPercent) open(); + else close(); + } + } else if (currentDragEdge == DragEdge.Bottom) { + if (yvel > minVelocity) close(); + else if (yvel < -minVelocity) open(); + else { + float openPercent = 1f * (-getSurfaceView().getTop()) / mDragDistance; + if (openPercent > willOpenPercent) open(); + else close(); + } + } + } + + /** + * smoothly open surface. + */ + public void open() { + open(true, true); + } + + public void open(boolean smooth) { + open(smooth, true); + } + + public void open(boolean smooth, boolean notify) { + View surface = getSurfaceView(), bottom = getCurrentBottomView(); + if (surface == null) { + return; + } + int dx, dy; + Rect rect = computeSurfaceLayoutArea(true); + if (smooth) { + mDragHelper.smoothSlideViewTo(surface, rect.left, rect.top); + } else { + dx = rect.left - surface.getLeft(); + dy = rect.top - surface.getTop(); + surface.layout(rect.left, rect.top, rect.right, rect.bottom); + if (getShowMode() == ShowMode.PullOut) { + Rect bRect = computeBottomLayoutAreaViaSurface(ShowMode.PullOut, rect); + if (bottom != null) { + bottom.layout(bRect.left, bRect.top, bRect.right, bRect.bottom); + } + } + if (notify) { + dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom); + dispatchSwipeEvent(rect.left, rect.top, dx, dy); + } else { + safeBottomView(); + } + } + invalidate(); + } + + public void open(DragEdge edge) { + setCurrentDragEdge(edge); + open(true, true); + } + + public void open(boolean smooth, DragEdge edge) { + setCurrentDragEdge(edge); + open(smooth, true); + } + + public void open(boolean smooth, boolean notify, DragEdge edge) { + setCurrentDragEdge(edge); + open(smooth, notify); + } + + /** + * smoothly close surface. + */ + public void close() { + close(true, true); + } + + public void close(boolean smooth) { + close(smooth, true); + } + + /** + * close surface + * + * @param smooth smoothly or not. + * @param notify if notify all the listeners. + */ + public void close(boolean smooth, boolean notify) { + View surface = getSurfaceView(); + if (surface == null) { + return; + } + int dx, dy; + if (smooth) + mDragHelper.smoothSlideViewTo(getSurfaceView(), getPaddingLeft(), getPaddingTop()); + else { + Rect rect = computeSurfaceLayoutArea(false); + dx = rect.left - surface.getLeft(); + dy = rect.top - surface.getTop(); + surface.layout(rect.left, rect.top, rect.right, rect.bottom); + if (notify) { + dispatchRevealEvent(rect.left, rect.top, rect.right, rect.bottom); + dispatchSwipeEvent(rect.left, rect.top, dx, dy); + } else { + safeBottomView(); + } + } + invalidate(); + } + + public void toggle() { + toggle(true); + } + + public void toggle(boolean smooth) { + if (getOpenStatus() == Status.Open) + close(smooth); + else if (getOpenStatus() == Status.Close) open(smooth); + } + + + /** + * a helper function to compute the Rect area that surface will hold in. + * + * @param open open status or close status. + */ + private Rect computeSurfaceLayoutArea(boolean open) { + int l = getPaddingLeft(), t = getPaddingTop(); + if (open) { + if (mCurrentDragEdge == DragEdge.Left) + l = getPaddingLeft() + mDragDistance; + else if (mCurrentDragEdge == DragEdge.Right) + l = getPaddingLeft() - mDragDistance; + else if (mCurrentDragEdge == DragEdge.Top) + t = getPaddingTop() + mDragDistance; + else t = getPaddingTop() - mDragDistance; + } + return new Rect(l, t, l + getMeasuredWidth(), t + getMeasuredHeight()); + } + + private Rect computeBottomLayoutAreaViaSurface(ShowMode mode, Rect surfaceArea) { + Rect rect = surfaceArea; + View bottomView = getCurrentBottomView(); + + int bl = rect.left, bt = rect.top, br = rect.right, bb = rect.bottom; + if (mode == ShowMode.PullOut) { + if (mCurrentDragEdge == DragEdge.Left) + bl = rect.left - mDragDistance; + else if (mCurrentDragEdge == DragEdge.Right) + bl = rect.right; + else if (mCurrentDragEdge == DragEdge.Top) + bt = rect.top - mDragDistance; + else bt = rect.bottom; + + if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) { + bb = rect.bottom; + br = bl + (bottomView == null ? 0 : bottomView.getMeasuredWidth()); + } else { + bb = bt + (bottomView == null ? 0 : bottomView.getMeasuredHeight()); + br = rect.right; + } + } else if (mode == ShowMode.LayDown) { + if (mCurrentDragEdge == DragEdge.Left) + br = bl + mDragDistance; + else if (mCurrentDragEdge == DragEdge.Right) + bl = br - mDragDistance; + else if (mCurrentDragEdge == DragEdge.Top) + bb = bt + mDragDistance; + else bt = bb - mDragDistance; + + } + return new Rect(bl, bt, br, bb); + + } + + private Rect computeBottomLayDown(DragEdge dragEdge) { + int bl = getPaddingLeft(), bt = getPaddingTop(); + int br, bb; + if (dragEdge == DragEdge.Right) { + bl = getMeasuredWidth() - mDragDistance; + } else if (dragEdge == DragEdge.Bottom) { + bt = getMeasuredHeight() - mDragDistance; + } + if (dragEdge == DragEdge.Left || dragEdge == DragEdge.Right) { + br = bl + mDragDistance; + bb = bt + getMeasuredHeight(); + } else { + br = bl + getMeasuredWidth(); + bb = bt + mDragDistance; + } + return new Rect(bl, bt, br, bb); + } + + public void setOnDoubleClickListener(DoubleClickListener doubleClickListener) { + mDoubleClickListener = doubleClickListener; + } + + public interface DoubleClickListener { + public void onDoubleClick(SwipeLayout layout, boolean surface); + } + + private int dp2px(float dp) { + return (int) (dp * getContext().getResources().getDisplayMetrics().density + 0.5f); + } + + + /** + * Deprecated, use {@link #addDrag(DragEdge, View)} + */ + @Deprecated + public void setDragEdge(DragEdge dragEdge) { + if (getChildCount() >= 2) { + mDragEdges.put(dragEdge, getChildAt(getChildCount() - 2)); + } + setCurrentDragEdge(dragEdge); + } + + public void onViewRemoved(View child) { + for (Map.Entry<DragEdge, View> entry : new HashMap<DragEdge, View>(mDragEdges).entrySet()) { + if (entry.getValue() == child) { + mDragEdges.remove(entry.getKey()); + } + } + } + + public Map<DragEdge, View> getDragEdgeMap() { + return mDragEdges; + } + + /** + * Deprecated, use {@link #getDragEdgeMap()} + */ + @Deprecated + public List<DragEdge> getDragEdges() { + return new ArrayList<DragEdge>(mDragEdges.keySet()); + } + + /** + * Deprecated, use {@link #addDrag(DragEdge, View)} + */ + @Deprecated + public void setDragEdges(List<DragEdge> dragEdges) { + for (int i = 0, size = Math.min(dragEdges.size(), getChildCount() - 1); i < size; i++) { + DragEdge dragEdge = dragEdges.get(i); + mDragEdges.put(dragEdge, getChildAt(i)); + } + if (dragEdges.size() == 0 || dragEdges.contains(DefaultDragEdge)) { + setCurrentDragEdge(DefaultDragEdge); + } else { + setCurrentDragEdge(dragEdges.get(0)); + } + } + + /** + * Deprecated, use {@link #addDrag(DragEdge, View)} + */ + @Deprecated + public void setDragEdges(DragEdge... mDragEdges) { + setDragEdges(Arrays.asList(mDragEdges)); + } + + /** + * Deprecated, use {@link #addDrag(DragEdge, View)} + * When using multiple drag edges it's a good idea to pass the ids of the views that + * you're using for the left, right, top bottom views (-1 if you're not using a particular view) + */ + @Deprecated + public void setBottomViewIds(int leftId, int rightId, int topId, int bottomId) { + addDrag(DragEdge.Left, findViewById(leftId)); + addDrag(DragEdge.Right, findViewById(rightId)); + addDrag(DragEdge.Top, findViewById(topId)); + addDrag(DragEdge.Bottom, findViewById(bottomId)); + } + + private float getCurrentOffset() { + if (mCurrentDragEdge == null) return 0; + return mEdgeSwipesOffset[mCurrentDragEdge.ordinal()]; + } + + private void setCurrentDragEdge(DragEdge dragEdge) { + if (mCurrentDragEdge != dragEdge) { + mCurrentDragEdge = dragEdge; + updateBottomViews(); + } + } + + private void updateBottomViews() { + View currentBottomView = getCurrentBottomView(); + if (currentBottomView != null) { + if (mCurrentDragEdge == DragEdge.Left || mCurrentDragEdge == DragEdge.Right) { + mDragDistance = currentBottomView.getMeasuredWidth() - dp2px(getCurrentOffset()); + } else + mDragDistance = currentBottomView.getMeasuredHeight() - dp2px(getCurrentOffset()); + } + + if (mShowMode == ShowMode.PullOut) + layoutPullOut(); + else if (mShowMode == ShowMode.LayDown) layoutLayDown(); + + safeBottomView(); + } +} diff --git a/app/src/main/res/drawable/del_house.png b/app/src/main/res/drawable/del_house.png new file mode 100644 index 0000000..b03ba61 --- /dev/null +++ b/app/src/main/res/drawable/del_house.png Binary files differ diff --git a/app/src/main/res/drawable/editor_house.png b/app/src/main/res/drawable/editor_house.png new file mode 100644 index 0000000..74be3cc --- /dev/null +++ b/app/src/main/res/drawable/editor_house.png Binary files differ diff --git a/app/src/main/res/drawable/move_house.png b/app/src/main/res/drawable/move_house.png new file mode 100644 index 0000000..444710b --- /dev/null +++ b/app/src/main/res/drawable/move_house.png Binary files differ diff --git a/app/src/main/res/layout/frgment_house_list_line.xml b/app/src/main/res/layout/frgment_house_list_line.xml index af4cd44..55fb773 100644 --- a/app/src/main/res/layout/frgment_house_list_line.xml +++ b/app/src/main/res/layout/frgment_house_list_line.xml @@ -1,79 +1,92 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + +<com.hdl.photovoltaic.widget.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/item_parent_swipeLayout" android:layout_width="match_parent" - android:layout_height="142dp" - android:background="@color/text_F9FAFB"> + android:layout_height="wrap_content"> + + <include + android:id="@+id/swipe_layout_il" + layout="@layout/swipe_right_layout" /> <RelativeLayout - android:id="@+id/fragment_house_list_line_parent_rl" - android:layout_width="0dp" - android:layout_height="130dp" - android:layout_alignParentStart="true" - android:layout_alignParentEnd="true" - android:layout_marginTop="@dimen/dp_12" - android:layout_marginStart="@dimen/dp_20" - android:layout_marginEnd="@dimen/dp_20" - android:background="@drawable/house_list_line_parent_bg"> + android:id="@+id/item_parent_rl" + android:layout_width="match_parent" + android:layout_height="142dp" + android:background="@color/text_F9FAFB"> - <ImageView - android:id="@+id/fragment_house_list_line_left_iv" - android:layout_width="113dp" + <RelativeLayout + android:id="@+id/fragment_house_list_line_parent_rl" + android:layout_width="0dp" android:layout_height="130dp" - android:scaleType="centerCrop" - /> - - <TextView - android:id="@+id/fragment_house_list_line_name_tv" - android:layout_width="170dp" - android:layout_height="@dimen/dp_23" - android:layout_marginStart="@dimen/dp_15" - android:layout_marginTop="@dimen/dp_28" - android:layout_toEndOf="@+id/fragment_house_list_line_left_iv" - android:gravity="center_vertical|start" - android:text="@string/power_station" - android:textColor="@color/text_90000000" - android:ellipsize="end" - android:singleLine="true" - android:textSize="@dimen/text_16" /> - - <TextView - android:id="@+id/fragment_house_list_line_capacity_tv" - android:layout_width="wrap_content" - android:layout_height="@dimen/dp_17" - android:layout_below="@+id/fragment_house_list_line_name_tv" - android:layout_alignStart="@+id/fragment_house_list_line_name_tv" - android:layout_marginTop="@dimen/dp_13" - android:gravity="center_vertical" - android:text="@string/my_power_station_installed_capacity" - android:textColor="@color/text_40000000" - android:textSize="@dimen/text_12" /> - - <TextView - android:id="@+id/fragment_house_list_line_power_tv" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@+id/fragment_house_list_line_capacity_tv" - android:layout_alignStart="@+id/fragment_house_list_line_capacity_tv" - android:layout_marginTop="@dimen/dp_13" - android:gravity="center_vertical" - android:text="@string/power_station_generated_power" - android:textColor="@color/text_40000000" - android:textSize="@dimen/text_12" /> - - <TextView - android:id="@+id/fragment_house_list_line_state_tv" - android:layout_width="@dimen/dp_48" - android:layout_height="@dimen/dp_33" - android:layout_alignParentTop="true" + android:layout_alignParentStart="true" android:layout_alignParentEnd="true" - android:background="@drawable/state_ffb300" - android:gravity="center" - android:text="@string/my_power_station_connecting" - android:textColor="@color/text_FFFFFFFF" - android:textSize="@dimen/text_12" /> + android:layout_marginStart="@dimen/dp_20" + android:layout_marginTop="@dimen/dp_12" + android:layout_marginEnd="@dimen/dp_20" + android:background="@drawable/house_list_line_parent_bg"> + + <ImageView + android:id="@+id/fragment_house_list_line_left_iv" + android:layout_width="113dp" + android:layout_height="130dp" + android:scaleType="centerCrop" /> + + <TextView + android:id="@+id/fragment_house_list_line_name_tv" + android:layout_width="170dp" + android:layout_height="@dimen/dp_23" + android:layout_marginStart="@dimen/dp_15" + android:layout_marginTop="@dimen/dp_28" + android:layout_toEndOf="@+id/fragment_house_list_line_left_iv" + android:ellipsize="end" + android:gravity="center_vertical|start" + android:singleLine="true" + android:text="@string/power_station" + android:textColor="@color/text_90000000" + android:textSize="@dimen/text_16" /> + + <TextView + android:id="@+id/fragment_house_list_line_capacity_tv" + android:layout_width="wrap_content" + android:layout_height="@dimen/dp_17" + android:layout_below="@+id/fragment_house_list_line_name_tv" + android:layout_alignStart="@+id/fragment_house_list_line_name_tv" + android:layout_marginTop="@dimen/dp_13" + android:gravity="center_vertical" + android:text="@string/my_power_station_installed_capacity" + android:textColor="@color/text_40000000" + android:textSize="@dimen/text_12" /> + + <TextView + android:id="@+id/fragment_house_list_line_power_tv" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/fragment_house_list_line_capacity_tv" + android:layout_alignStart="@+id/fragment_house_list_line_capacity_tv" + android:layout_marginTop="@dimen/dp_13" + android:gravity="center_vertical" + android:text="@string/power_station_generated_power" + android:textColor="@color/text_40000000" + android:textSize="@dimen/text_12" /> + + <TextView + android:id="@+id/fragment_house_list_line_state_tv" + android:layout_width="@dimen/dp_48" + android:layout_height="@dimen/dp_33" + android:layout_alignParentTop="true" + android:layout_alignParentEnd="true" + android:background="@drawable/state_ffb300" + android:gravity="center" + android:text="@string/my_power_station_connecting" + android:textColor="@color/text_FFFFFFFF" + android:textSize="@dimen/text_12" /> + + + </RelativeLayout> </RelativeLayout> +</com.hdl.photovoltaic.widget.SwipeLayout> -</RelativeLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/swipe_right_layout.xml b/app/src/main/res/layout/swipe_right_layout.xml new file mode 100644 index 0000000..c1a28b5 --- /dev/null +++ b/app/src/main/res/layout/swipe_right_layout.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="82dp" + android:layout_height="142dp" + android:layout_marginTop="@dimen/dp_12" + android:orientation="vertical"> + + <View + android:layout_width="wrap_content" + android:layout_height="@dimen/dp_19" /> + + <ImageView + android:id="@+id/move_home_iv" + android:layout_width="@dimen/dp_50" + android:layout_height="@dimen/dp_50" + android:layout_marginStart="@dimen/dp_16" + android:src="@drawable/move_house" /> + + <View + android:layout_width="wrap_content" + android:layout_height="@dimen/dp_16" /> + + <ImageView + android:id="@+id/del_home_iv" + android:layout_width="@dimen/dp_50" + android:layout_height="@dimen/dp_50" + android:layout_marginStart="@dimen/dp_16" + android:src="@drawable/del_house" /> + + +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/toolbar_top_view_52.xml b/app/src/main/res/layout/toolbar_top_view_52.xml index a198bc4..ddcf450 100644 --- a/app/src/main/res/layout/toolbar_top_view_52.xml +++ b/app/src/main/res/layout/toolbar_top_view_52.xml @@ -48,6 +48,14 @@ android:orientation="horizontal"> <ImageView + android:id="@+id/top_edit_iv" + android:layout_width="@dimen/dp_28" + android:layout_height="@dimen/dp_28" + android:adjustViewBounds="true" + android:scaleType="centerInside" + android:visibility="gone" /> + + <ImageView android:id="@+id/top_more_iv" android:layout_width="@dimen/dp_28" android:layout_height="@dimen/dp_28" diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 3eab926..4253f75 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -4,4 +4,6 @@ <item name="android:background">@color/black_overlay</item> <item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item> </style> + + </resources> \ No newline at end of file diff --git a/app/src/main/res/values/values.xml b/app/src/main/res/values/values.xml new file mode 100644 index 0000000..a671fc5 --- /dev/null +++ b/app/src/main/res/values/values.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <declare-styleable name="SwipeLayout"> + <attr name="drag_edge"> + <flag name="left" value="1" /> + <flag name="right" value="2" /> + <flag name="top" value="4" /> + <flag name="bottom" value="8" /> + </attr> + <attr name="leftEdgeSwipeOffset" format="dimension" /> + <attr name="rightEdgeSwipeOffset" format="dimension" /> + <attr name="topEdgeSwipeOffset" format="dimension" /> + <attr name="bottomEdgeSwipeOffset" format="dimension" /> + <attr name="show_mode" format="enum"> + <enum name="lay_down" value="0" /> + <enum name="pull_out" value="1" /> + </attr> + <attr name="clickToClose" format="boolean" /> + </declare-styleable> +</resources> \ No newline at end of file -- Gitblit v1.8.0