一、初始化
首先我们需要到乐橙开放平台下载android对应的开发包,将sdk中提供的jar和so文件添加到项目中;
二、获取监控列表
监控列表我们是通过从自家后台服务器中获取的,这个自己根据需要调整;
package com.aldx.hccraftsman.activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.aldx.hccraftsman.NewHcgjApplication;
import com.aldx.hccraftsman.R;
import com.aldx.hccraftsman.adapter.DahuaCameraListAdapter;
import com.aldx.hccraftsman.loadinglayout.LoadingLayout;
import com.aldx.hccraftsman.model.DahuaCamera;
import com.aldx.hccraftsman.model.DahuaCameraListModel;
import com.aldx.hccraftsman.model.DahuaDevice;
import com.aldx.hccraftsman.model.DahuaDeviceListModel;
import com.aldx.hccraftsman.okhttp.LoadingDialogCallback;
import com.aldx.hccraftsman.utils.Api;
import com.aldx.hccraftsman.utils.Constants;
import com.aldx.hccraftsman.utils.FastJsonUtils;
import com.aldx.hccraftsman.utils.OtherUtils;
import com.jcodecraeer.xrecyclerview.XRecyclerView;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.model.Response;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* author: chenzheng
* created on: 2019/8/8 15:31
* description: 大华监控列表
*/
public class DahuaCameraListActivity extends BaseActivity {
@BindView(R.id.back_iv)
ImageView backIv;
@BindView(R.id.layout_back)
LinearLayout layoutBack;
@BindView(R.id.title_tv)
TextView titleTv;
@BindView(R.id.right_tv)
TextView rightTv;
@BindView(R.id.layout_right)
LinearLayout layoutRight;
@BindView(R.id.dhcamera_recyclerview)
XRecyclerView dhcameraRecyclerview;
@BindView(R.id.loading_layout)
LoadingLayout loadingLayout;
private DahuaCameraListAdapter dahuaCameraListAdapter;
public List<DahuaCamera> list = new ArrayList<>();
private String projectId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dahua_camera_list);
ButterKnife.bind(this);
initView();
requestDeviceList();
}
private void initView() {
titleTv.setText("监控列表");
dahuaCameraListAdapter = new DahuaCameraListAdapter(this);
dhcameraRecyclerview.setAdapter(dahuaCameraListAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
Drawable dividerDrawable = ContextCompat.getDrawable(this, R.drawable.divider_sample);
dhcameraRecyclerview.addItemDecoration(dhcameraRecyclerview.new DividerItemDecoration(dividerDrawable));
dhcameraRecyclerview.setLayoutManager(layoutManager);
OtherUtils.setXRecyclerViewAttr(dhcameraRecyclerview);
dhcameraRecyclerview.setLoadingMoreEnabled(false);
dhcameraRecyclerview.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
requestDeviceList();
}
@Override
public void onLoadMore() {
}
});
dahuaCameraListAdapter.setOnItemClickListener(new DahuaCameraListAdapter.OnRecyclerViewItemClickListener() {
@Override
public void onItemClick(View view, DahuaCamera data) {
if (data != null) {
Intent intent = new Intent(DahuaCameraListActivity.this, DahuaCameraFullPlayActivity.class);
intent.putExtra("DAHUA_CAMERA_INFO", data);
startActivity(intent);
}
}
});
loadingLayout.setEmptyClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dhcameraRecyclerview.refresh();
}
});
loadingLayout.showLoading();
}
private void requestDeviceList(){
OkGo.<String>get(Api.GET_DAHUA_DEVICE_LIST)
.tag(this)
.params("projectId", "05771166ea834823b077d2166f7afe65")
.params("pageNum", Constants.FIRSTPAGE)
.params("pageSize", Constants.PAGESIZE)
.execute(new LoadingDialogCallback(this, Constants.NET_REQUEST_TXT) {
@Override
public void onSuccess(Response<String> response) {
DahuaDeviceListModel dahuaDeviceListModel = null;
try {
dahuaDeviceListModel = FastJsonUtils.parseObject(response.body(), DahuaDeviceListModel.class);
} catch (Exception e) {
e.printStackTrace();
}
if (dahuaDeviceListModel != null) {
if (dahuaDeviceListModel.code == Api.SUCCESS_CODE) {
if (dahuaDeviceListModel.data != null && dahuaDeviceListModel.data.list != null
&& dahuaDeviceListModel.data.list.size() > 0) {
loadingLayout.showContent();
DahuaDevice dahuaDevice = dahuaDeviceListModel.data.list.get(0);
requestCameraList(dahuaDevice.deviceId);
} else {
tipDialog();
}
} else {
tipDialog();
}
}
}
@Override
public void onError(Response<String> response) {
super.onError(response);
NewHcgjApplication.showResultToast(DahuaCameraListActivity.this, response);
}
});
}
private void requestCameraList(String deviceId){
OkGo.<String>get(Api.GET_DAHUA_CAMERA_LIST)
.tag(this)
.params("deviceId", deviceId)
.execute(new LoadingDialogCallback(this, Constants.NET_REQUEST_TXT) {
@Override
public void onSuccess(Response<String> response) {
dhcameraRecyclerview.refreshComplete();
DahuaCameraListModel dahuaCameraListModel = null;
try {
dahuaCameraListModel = FastJsonUtils.parseObject(response.body(), DahuaCameraListModel.class);
} catch (Exception e) {
e.printStackTrace();
}
if (dahuaCameraListModel != null) {
if (dahuaCameraListModel.code == Api.SUCCESS_CODE) {
if (dahuaCameraListModel.data != null && dahuaCameraListModel.data.size() > 0) {
list.addAll(dahuaCameraListModel.data);
dahuaCameraListAdapter.setItems(list);
} else {
tipDialog();
}
} else {
tipDialog();
}
}
}
@Override
public void onError(Response<String> response) {
super.onError(response);
dhcameraRecyclerview.refreshComplete();
NewHcgjApplication.showResultToast(DahuaCameraListActivity.this, response);
}
});
}
private void tipDialog() {
new MaterialDialog.Builder(DahuaCameraListActivity.this)
.title("温馨提示")
.content("您没有可以预览的监控,请联系管理员添加!")
.positiveText("我知道了")
.cancelable(false)
.show();
}
@OnClick({R.id.layout_back, R.id.layout_right})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.layout_back:
finish();
break;
case R.id.layout_right:
break;
}
}
public static void startActivity(Context context) {
Intent intent = new Intent(context, DahuaCameraListActivity.class);
context.startActivity(intent);
}
}
三、实时预览
添加预览工具类:
package com.aldx.hccraftsman.utils; import android.content.Context; import android.os.Handler; import android.os.Message; import android.view.ViewGroup; import com.aldx.hccraftsman.model.LeChangeRecordInfo; import com.lechange.opensdk.api.LCOpenSDK_Api; import com.lechange.opensdk.api.bean.QueryLocalRecordNum; import com.lechange.opensdk.api.bean.QueryLocalRecords; import com.lechange.opensdk.api.client.BaseRequest; import com.lechange.opensdk.api.client.BaseResponse; import com.lechange.opensdk.listener.LCOpenSDK_EventListener; import com.lechange.opensdk.media.LCOpenSDK_PlayWindow; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import cn.qqtheme.framework.util.LogUtils; /** * author: chenzheng * created on: 2019/8/9 9:26 * description: */ public class PlayerLeChange { private static final String TAG = "LeChange"; private Handler handler; public LCOpenSDK_PlayWindow lcOpenSDK_playWindow; //播放窗口 public PlayerLeChange(Context context, ViewGroup viewGroup, Handler handler) { LCOpenSDK_Api.setHost("openapi.lechange.cn:443"); //设置乐橙服务地址 lcOpenSDK_playWindow = new LCOpenSDK_PlayWindow(); lcOpenSDK_playWindow.initPlayWindow(context, viewGroup, 0); //初始化播放功能,父窗口绑定到LCOpenSDK_playWindow的实例上 this.handler = handler; } /** * 实时预览 * @param token * @param deviceId * @param channelNo * @param quality */ public void live(String token, String deviceId, String encryptKey, int channelNo, int quality) { lcOpenSDK_playWindow.playRtspReal(token, deviceId, encryptKey, channelNo, quality); /** * 为播放窗口设置监听 */ lcOpenSDK_playWindow.setWindowListener(new LCOpenSDK_EventListener() { @Override public void onPlayerResult(int index, String code, int resultSource) { super.onPlayerResult(index, code, resultSource); if (resultSource == 0 && "4".equals(code)) { messageFeedback(1); } else { messageFeedback(2); } } }); } /** * 远程回放 * @param token * @param deviceId * @param encryptKey * @param channelNo * @param beginTime * @param endTime */ public void playback(String token, String deviceId, String encryptKey, int channelNo, long beginTime, long endTime) { lcOpenSDK_playWindow.playRtspPlaybackByUtcTime(token, deviceId, encryptKey, channelNo, beginTime, endTime); lcOpenSDK_playWindow.setWindowListener(new LCOpenSDK_EventListener() { @Override public void onPlayerResult(int index, String code, int resultSource) { super.onPlayerResult(index, code, resultSource); if (resultSource == 0 && "4".equals(code)) { messageFeedback(1); } else { messageFeedback(2); } } }); } /** * 停止实时预览 */ public void stopLive() { lcOpenSDK_playWindow.stopRtspReal(); } /** * 停止远程回放 */ public void stopPlayback() { lcOpenSDK_playWindow.stopRtspPlayback(); } /** * 查询录像段文件数量 * @param token * @param deviceId * @param channelNo * @param beginTime * @param endTime */ public int queryRecordNum(String token, String deviceId, int channelNo, String beginTime, String endTime) { QueryLocalRecordNum req = new QueryLocalRecordNum(); req.data.token = token; req.data.deviceId = deviceId; req.data.channelId = channelNo + ""; req.data.beginTime = beginTime; req.data.endTime = endTime; RetObject retObject = request(req, 60 * 1000); QueryLocalRecordNum.Response resp = (QueryLocalRecordNum.Response) retObject.resp; if (retObject.mErrorCode != 0) { //查询录像失败 return -1; } else { if (resp.data == null) { //录像数据为空 return 0; } else { return resp.data.recordNum; } } } /** * 获取录像段文件 * @param token * @param deviceId * @param channelNo * @param beginTime * @param endTime * @param queryRange * @return */ public List<LeChangeRecordInfo> getRecordFile(String token, String deviceId, int channelNo, String beginTime, String endTime, String queryRange) { List<LeChangeRecordInfo> recordInfoList = new ArrayList<LeChangeRecordInfo>(); QueryLocalRecords req = new QueryLocalRecords(); req.data.token = token; req.data.deviceId = deviceId; req.data.channelId = channelNo + ""; req.data.beginTime = beginTime; req.data.endTime = endTime; req.data.queryRange = queryRange; RetObject retObject = request(req); QueryLocalRecords.Response resp = (QueryLocalRecords.Response) retObject.resp; if (retObject.mErrorCode == 0 && resp.data != null && resp.data.records != null) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (QueryLocalRecords.ResponseData.RecordsElement element:resp.data.records) { LeChangeRecordInfo recordInfo = new LeChangeRecordInfo(); try { recordInfo.setStartTime(sdf.parse(element.beginTime).getTime()); recordInfo.setEndTime(sdf.parse(element.endTime).getTime()); recordInfoList.add(recordInfo); } catch (ParseException e) { e.printStackTrace(); } } } return recordInfoList; } public static class RetObject { public int mErrorCode = 0; //错误码表示符 -1:返回体为null,0:成功,1:http错误,2:业务错误 public String mMsg; public Object resp; } /** * 发送网络请求,并对请求结果的错误码进行处理 * @param req * @return */ private RetObject request(BaseRequest req) { return request(req, 5 * 1000); } /** * 发送网络请求,并对请求结果的错误码进行处理 * @param req * @param timeout * @return */ private RetObject request(BaseRequest req, int timeout) { RetObject retObject = new RetObject(); BaseResponse t = null; try { t = LCOpenSDK_Api.request(req, timeout); //openAPI请求方法 if (t.getCode() == 200) { //请求成功 if (!t.getApiRetCode().equals("0")) { //业务错误 retObject.mErrorCode = 2; retObject.mMsg = "业务错误码:" + t.getApiRetCode() + ",错误消息:" + t.getApiRetMsg(); LogUtil.e(TAG, "retObject.mMsg:" + retObject.mMsg); } } else { retObject.mErrorCode = 1; //http错误 retObject.mMsg = "HTTP错误码:" + t.getCode() + ",错误消息:" + t.getDesc(); LogUtil.e(TAG, "retObject.mMsg:" + retObject.mMsg); } } catch (Exception e) { e.printStackTrace(); retObject.mErrorCode = -1000; retObject.mMsg = "内部错误码 : -1000, 错误消息 :" + e.getMessage(); LogUtil.e(TAG, "retObject.mMsg:" + retObject.mMsg); } retObject.resp = t; return retObject; } private void messageFeedback(int bfCode) { LogUtil.e("bfCode="+bfCode); Message message = Message.obtain(); message.obj = bfCode; handler.sendMessage(message); } }
package com.aldx.hccraftsman.model; import java.util.UUID; /** * author: chenzheng * created on: 2019/8/9 9:27 * description: */ public class LeChangeRecordInfo { public enum RecordType { DeviceLocal, // 设备本地录像 PrivateCloud, // 私有云 PublicCloud, // 公有云 } public enum RecordEventType { All, // 所有录像 Manual, // 手动录像 Event, // 事件录像 } private String id = UUID.randomUUID().toString(); private RecordType type; // 录像类型 private float fileLength; // 文件长度 private float downLength = -1; // 已下载长度 private long startTime; // 开始时间 private long endTime; // 结束时间 private String deviceId; //设备ID private String deviceKey; private String backgroudImgUrl; // 录像文件Url private String chnlUuid; // 通道的uuid private RecordEventType eventType; // 事件类型 private long recordID; //录像ID private String recordPath; //录像ID(设备录像) public String getDeviceId() { return deviceId; } public void setDeviceId(String deviceId) { this.deviceId = deviceId; } public String getDeviceKey() { return deviceKey; } public void setDeviceKey(String deviceKey) { this.deviceKey = deviceKey; } public RecordType getType() { return type; } public void setType(RecordType type) { this.type = type; } public long getStartTime() { return startTime; } public float getFileLength() { return fileLength; } public void setFileLength(float fileLength) { this.fileLength = fileLength; } public float getDownLength() { return downLength; } public void setDownLength(float downLength) { this.downLength = downLength; } public void setStartTime(long startTime) { this.startTime = startTime; } public long getEndTime() { return endTime; } public void setEndTime(long endTime) { this.endTime = endTime; } public String getBackgroudImgUrl() { return backgroudImgUrl; } public void setBackgroudImgUrl(String backgroudImgUrl) { this.backgroudImgUrl = backgroudImgUrl; } public String getChnlUuid() { return chnlUuid; } public void setChnlUuid(String chnlUuid) { this.chnlUuid = chnlUuid; } public RecordEventType getEventType() { return eventType; } public void setEventType(RecordEventType eventType) { this.eventType = eventType; } public String getId() { return id; } public void setId(String id) { this.id = id; } public void setRecordID(long id) { this.recordID = id; } public long getRecordID() { return this.recordID; } public boolean isDownload() { return downLength >= 0; } public String getRecordPath() { return recordPath; } public void setRecordPath(String recordPath) { this.recordPath = recordPath; } }
编写预览页面:
package com.aldx.hccraftsman.activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.afollestad.materialdialogs.MaterialDialog; import com.aldx.hccraftsman.NewHcgjApplication; import com.aldx.hccraftsman.R; import com.aldx.hccraftsman.model.DahuaCamera; import com.aldx.hccraftsman.model.EZTokenModel; import com.aldx.hccraftsman.okhttp.LoadingDialogCallback; import com.aldx.hccraftsman.utils.Api; import com.aldx.hccraftsman.utils.Constants; import com.aldx.hccraftsman.utils.FastJsonUtils; import com.aldx.hccraftsman.utils.LogUtil; import com.aldx.hccraftsman.utils.PlayerLeChange; import com.aldx.hccraftsman.utils.ToastUtil; import com.aldx.hccraftsman.utils.Utils; import com.kongqw.rockerlibrary.view.RockerView; import com.lechange.opensdk.listener.LCOpenSDK_EventListener; import com.lzy.okgo.OkGo; import com.lzy.okgo.model.Response; import com.pnikosis.materialishprogress.ProgressWheel; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; /** * author: chenzheng * created on: 2019/8/8 11:43 * description: 大华摄像头全屏播放 */ public class DahuaCameraFullPlayActivity extends BaseActivity { @BindView(R.id.progress_wheel) ProgressWheel progressWheel; @BindView(R.id.back_iv) ImageView backIv; @BindView(R.id.go_zoombig_btn) TextView goZoombigBtn; @BindView(R.id.go_zoomsmall_btn) TextView goZoomsmallBtn; @BindView(R.id.rocker_iv) ImageView rockerIv; @BindView(R.id.monitor_name_tv) TextView monitorNameTv; @BindView(R.id.layout_bottom_menu) LinearLayout layoutBottomMenu; @BindView(R.id.tools_control_iv) ImageView toolsControlIv; @BindView(R.id.tool_control_layout) LinearLayout toolControlLayout; @BindView(R.id.rockerView) RockerView rockerView; @BindView(R.id.rocker_close_iv) ImageView rockerCloseIv; @BindView(R.id.layout_rocker) LinearLayout layoutRocker; private ViewGroup liveWindowContent; private View load_layout; private DahuaCamera dahuaCamera; private String dahuaToken; private PlayerLeChange playerLeChange; private Handler mHander = new Handler() { public void handleMessage(Message msg) { int status = (int) msg.obj; switch (status){ case 1://播放成功 load_layout.setVisibility(View.GONE); break; case 2://播放失败 tipDialog("当前摄像头无法播放!"); load_layout.setVisibility(View.GONE); break; } return; } }; @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); super.onCreate(savedInstanceState); setContentView(R.layout.activity_dahua_camera_full_play); ButterKnife.bind(this); dahuaCamera = getIntent().getParcelableExtra("DAHUA_CAMERA_INFO"); if (dahuaCamera != null && "offline".equals(dahuaCamera.status)) { tipDialog("当前摄像头不在线,请检查设备网络!"); return; } initView(); requestDahuaToken(); } private void initView() { load_layout = this.findViewById(R.id.load_layout); liveWindowContent = this.findViewById(R.id.live_window_content); } /** * 描述:开始播放 */ public void play() { playerLeChange = new PlayerLeChange(this, liveWindowContent, mHander); playerLeChange.live(dahuaToken, dahuaCamera.deviceId, dahuaCamera.deviceId, Utils.toInt(dahuaCamera.channelId), 0); } @Override protected void onDestroy() { super.onDestroy(); if(playerLeChange!=null) { playerLeChange.stopLive(); } } private void tipDialog(String messageStr) { new MaterialDialog.Builder(this) .title("温馨提示") .content(messageStr) .positiveText("我知道了") .cancelable(false) .show(); } @OnClick({R.id.back_iv, R.id.go_zoombig_btn, R.id.go_zoomsmall_btn, R.id.rocker_iv}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.back_iv: finish(); break; case R.id.go_zoombig_btn: break; case R.id.go_zoomsmall_btn: break; case R.id.rocker_iv: break; } } private void requestDahuaToken() { OkGo.<String>get(Api.GET_DAHUA_ACCESS_TOKEN) .tag(this) .execute(new LoadingDialogCallback(this, Constants.NET_REQUEST_TXT) { @Override public void onSuccess(Response<String> response) { EZTokenModel ezTokenModel = null; try { ezTokenModel = FastJsonUtils.parseObject(response.body(), EZTokenModel.class); } catch (Exception e) { e.printStackTrace(); } if (ezTokenModel != null) { if (ezTokenModel.code == Api.SUCCESS_CODE) { if (!TextUtils.isEmpty(ezTokenModel.data)) { dahuaToken = ezTokenModel.data; play(); } } else { if (!TextUtils.isEmpty(ezTokenModel.msg)) { ToastUtil.show(DahuaCameraFullPlayActivity.this, ezTokenModel.msg); } } } } @Override public void onError(Response<String> response) { super.onError(response); NewHcgjApplication.showResultToast(DahuaCameraFullPlayActivity.this, response); } }); } class MyBaseWindowListener extends LCOpenSDK_EventListener { } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/live_window_content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/black" /> <include android:id="@+id/load_layout" layout="@layout/view_loading" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" /> <ImageView android:id="@+id/back_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="30dp" android:src="@drawable/back_btn_round_background" /> <LinearLayout android:id="@+id/layout_bottom_menu" android:layout_width="match_parent" android:layout_height="48dp" android:layout_gravity="bottom" android:layout_marginRight="48dp" android:background="#80000000" android:gravity="center_vertical" android:orientation="horizontal" android:padding="5dp" android:visibility="gone"> <TextView android:id="@+id/go_zoombig_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/bg_round_corner_solid_white" android:padding="5dp" android:text="放大" android:textColor="@color/textview_color_gray3" android:textSize="@dimen/s_size" android:visibility="gone" /> <TextView android:id="@+id/go_zoomsmall_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:background="@drawable/bg_round_corner_solid_white" android:padding="5dp" android:text="缩小" android:textColor="@color/textview_color_gray3" android:textSize="@dimen/s_size" android:visibility="gone" /> <ImageView android:id="@+id/rocker_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:src="@drawable/rocker_icon_white" android:visibility="gone" /> <TextView android:id="@+id/monitor_name_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:textColor="@color/white" android:textSize="@dimen/m_size" /> </LinearLayout> <LinearLayout android:id="@+id/tool_control_layout" android:layout_width="48dp" android:layout_height="48dp" android:layout_gravity="right|bottom" android:background="#80000000" android:gravity="center" android:orientation="horizontal"> <ImageView android:id="@+id/tools_control_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/hk_tools_open" /> </LinearLayout> <LinearLayout android:id="@+id/layout_rocker" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|bottom" android:layout_marginBottom="40dp" android:orientation="horizontal" android:visibility="gone"> <com.kongqw.rockerlibrary.view.RockerView xmlns:kongqw="http://schemas.android.com/apk/res-auto" android:id="@+id/rockerView" android:layout_width="120dp" android:layout_height="120dp" kongqw:areaBackground="@drawable/default_area_bg" kongqw:rockerBackground="@drawable/default_rocker_bg" kongqw:rockerRadius="20dp" /> <ImageView android:id="@+id/rocker_close_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:src="@drawable/hk_rock_close" /> </LinearLayout> </FrameLayout> </LinearLayout>