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