简单介绍一下:点击“+”号图标可添加图片,图片添加后点击可查看,长按弹出popView,可选择删除或查看。
这是在逍遥模拟器上运行后的效果,因为我设置的是一行4个图片,所以间隔有点大。
这里有几个要考虑的点,因为是涉及到图片,所以必要的权限一定是要给的。下面是我用Kotlin写的一个Activity,注意重写onRequestPermissionsResult方法,不然权限被关了的话不会出现要求获取访问图库的权限提示。
abstract class AddPictureActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
private var onPermissionListener: OnBooleanListener? = null
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//权限通过
if (onPermissionListener != null) {
onPermissionListener!!.onClick(true)
}
}
} else {
//权限拒绝
if (onPermissionListener != null) {
onPermissionListener!!.onClick(false)
}
}
return
}
@TargetApi(Build.VERSION_CODES.M)
fun permissionRequests(activity: Activity, permission: String, onBooleanListener: OnBooleanListener) {
onPermissionListener = onBooleanListener
if (ContextCompat.checkSelfPermission(this@AddPictureActivity, permission) != PackageManager.PERMISSION_GRANTED) {
// if (ActivityCompat.shouldShowRequestPermissionRationale(activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// //权限通过
// onPermissionListener.onClick(true);
// } else {
//没有权限,申请一下
ActivityCompat.requestPermissions(activity, arrayOf(permission), 1)
// }
} else {
//权限已有
if (onPermissionListener != null) {
onPermissionListener!!.onClick(true)
}
}
}
/**
* 图片选择,图库或者相机
*/
private var file: File? = null
fun selectPic(tag: Boolean) {
if (tag) {
permissionRequests(this@AddPictureActivity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, object : OnBooleanListener {
override fun onClick(bln: Boolean) {
if (bln) {
//图库选图的intent
val intent1 = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
//intent1.setDataAndType(, "image/*");
//相机拍照
val intent2 = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), System.currentTimeMillis().toString() + ".jpg")
val imageUri = Uri.fromFile(file)
intent2.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
val intent = Intent.createChooser(intent1, "选取上传图片方式")
intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(intent2))
startActivityForResult(intent, ChgActivityCode.PicStoreCode)
//通过onResume()刷新数据
}
}
})
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == ChgActivityCode.PicStoreCode) {
//打开图片
if (resultCode == Activity.RESULT_OK) {
var picPath: String? = null
var uri: Uri? = null
if (data != null) {
uri = data.data
if (!TextUtils.isEmpty(uri!!.authority)) {
val cr = this.contentResolver
//查询选择图片
val cursor = cr.query(
uri,
arrayOf(MediaStore.Images.Media.DATA), null, null, null) ?: return
//返回 没找到选择图片
//光标移动至开头 获取图片路径
cursor.moveToFirst()
picPath = cursor.getString(cursor
.getColumnIndex(MediaStore.Images.Media.DATA))
}
} else {
//拍照获取uri
uri = Uri.fromFile(file)
picPath = file.toString()
}
if (!TextUtils.isEmpty(picPath)) { //选择了图片并添加
iconAdd(picPath)
}
}
}
else if (resultCode == ChgActivityCode.ShowIconDelCode){
iconDelete()
afterIconDelete()
}
if (resultCode == ChgActivityCode.ALL_ACTIVITY_CLOSE){
this.setResult(ChgActivityCode.ALL_ACTIVITY_CLOSE)
finish()
}
}
protected fun notifyGridViewDeleteData(position: Int, imgs: MutableList<String>, adapter: AddPictureAdapter){
if (imgs.size == 6){
imgs.add("")
}
imgs.removeAt(position)
adapter.notifyDataSetChanged()
}
protected fun notifyGridViewAddData(path: String, position: Int, adapter: AddPictureAdapter){
if (position == 5){
adapter.getData()!![5] = path
}
else{
adapter.getData()!!.add(position, path)
}
adapter.notifyDataSetChanged()
}
abstract fun iconAdd(path : String?);
abstract fun iconDelete();
abstract fun afterIconDelete();
}
个人觉得在图片右上角加个“X”不好看,而且屏幕小了的话不好点,所以弄一个popView辅助,这里是防QQ来的做的样子。看下面的代码就知道,实际上就是两张图片做背景的按钮。没什么稀奇的。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/my_pop_btn_check"
android:layout_width="50dp"
android:layout_height="50dp"
android:textSize="13sp"
android:textColor="@color/colorWhite"
android:background="@mipmap/ic_popbgl"
android:paddingBottom="10dp"
android:text="查看" />
<Button
android:id="@+id/my_pop_btn_delete"
android:layout_width="50dp"
android:layout_height="50dp"
android:paddingBottom="10dp"
android:layout_toRightOf="@+id/my_pop_btn_check"
android:textSize="13sp"
android:textColor="@color/colorWhite"
android:background="@mipmap/ic_popbgr"
android:text="删除" />
</RelativeLayout>
我写的这个popView最多可以适用4个按钮的layout资源,所以呢代码里面你会看到有两个在这里一点卵关系都没有的代码段,忽略就行了。就是下面这货也参与了。
class MyPopOption @JvmOverloads constructor(private val context: Context, private val parent: ViewGroup?, private val resouce: Int = R.layout.mypop_layout) {
private var popupWidth: Int = 0
private var popupHeight: Int = 0
private var popupWindow: PopupWindow? = null
private var mEvent: PopClickEvent? = null
private var preBtn: Button? = null
private var nextBtn: Button? = null
private var mName: TextView? = null
private var mContent: TextView? = null
private var panoramaBtn: Button? = null
private var navigateBtn: Button? = null
private var buildingBean: BuildingBean? = null
var view: View? = null
private set
private var locationX: Int = 0
private var locationY: Int = 0
private val oneDp: Int
val isShown: Boolean
get() = if (popupWindow == null) {
false
} else popupWindow!!.isShowing
init {
oneDp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1.0f, context.resources.displayMetrics).toInt()
// WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
init()
}
private fun init() {
val popupView = LayoutInflater.from(context).inflate(resouce, parent, false)
preBtn = popupView.findViewById<Button>(R.id.my_pop_btn_check)
nextBtn = popupView.findViewById<Button>(R.id.my_pop_btn_delete)
mName = popupView.findViewById<TextView>(R.id.building_pop_name)
mContent = popupView.findViewById<TextView>(R.id.building_pop_introduce)
if (mName != null) {
popupWindow = PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, true)
// popupWindow.setBackgroundDrawable(new BitmapDrawable());
panoramaBtn = popupView.findViewById<Button>(R.id.my_pop_btn_panorama)
navigateBtn = popupView.findViewById<Button>(R.id.my_pop_btn_navigate)
popupWindow!!.isTouchable = true
popupWindow!!.isFocusable = false
// popupWindow.setOutsideTouchable(true);
popupWindow!!.animationStyle = R.style.my_pop_window
// popupWindow.setTouchInterceptor(new View.OnTouchListener(){
//
// @Override
// public boolean onTouch(View view, MotionEvent motionEvent) {
// Log.i("hhh", "good " + motionEvent.getAction());
// return false;
// }
// });
var distance = 0f;
var currentY = 0f;
var startY = 0f;
popupView.setOnTouchListener(object : View.OnTouchListener{
override fun onTouch(p0: View?, motionEvent: MotionEvent?): Boolean {
when(motionEvent!!.action){
MotionEvent.ACTION_DOWN -> {
startY = motionEvent.y
}
MotionEvent.ACTION_MOVE -> {
currentY = motionEvent.y
distance = currentY - startY
if (distance > 0){
popupView.translationY = distance
}
}
MotionEvent.ACTION_UP -> {
currentY = motionEvent.y
distance = currentY - startY
if (distance > 30 * oneDp){
popupView.translationY = 0f
popupWindow!!.dismiss()
}
else {
addAnimationValue(popupView, distance)
if (valueAnimator != null){
valueAnimator!!.start()
}
}
distance = 0f
startY = 0f
currentY = 0f
}
else -> {
return false
}
}
return true
}
})
} else {
popupWindow = PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, true)
popupWindow!!.setBackgroundDrawable(BitmapDrawable())
}
popupView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
popupWidth = popupView.measuredWidth
popupHeight = popupView.measuredHeight
}
fun setBtnEnable(enable: Boolean) {
if (preBtn != null) {
preBtn!!.isEnabled = enable
}
if (nextBtn != null) {
nextBtn!!.isEnabled = enable
}
}
fun show(view: View) {
this.view = view
initEvent()
val location = IntArray(2)
view.getLocationOnScreen(location)
popupWindow!!.showAtLocation(view, Gravity.NO_GRAVITY, location[0] + view.width / 2 - popupWidth / 2,
location[1] - popupHeight)
}
fun show(marker: Marker) {
initEvent()
// LatLng latLng = marker.getPosition();
// popupWindow.showAtLocation(parent, Gravity.NO_GRAVITY, locationX - 60 * oneDp, locationY - 60 * oneDp);
if (parent != null) {
popupWindow!!.showAtLocation(parent, Gravity.BOTTOM, 0, 0)
}
}
fun dismiss() {
popupWindow!!.dismiss()
}
private fun initEvent() {
if (mEvent != null) {
preBtn!!.setOnClickListener { mEvent!!.onPreBtnClick() }
nextBtn!!.setOnClickListener { mEvent!!.onNextBtnClick() }
//全景按钮
if (panoramaBtn != null){
panoramaBtn!!.setOnClickListener { mEvent!!.onPanoramaBtnClick() }
}
//导航按钮
if (navigateBtn != null){
navigateBtn!!.setOnClickListener { mEvent!!.onNavigateBtnClick() }
}
}
}
fun getmEvent(): PopClickEvent? {
return mEvent
}
fun setmEvent(mEvent: PopClickEvent) {
this.mEvent = mEvent
}
interface PopClickEvent {
fun onPreBtnClick()
fun onNextBtnClick()
fun onPanoramaBtnClick()
fun onNavigateBtnClick()
}
fun setPreBtnText(text: String) {
preBtn!!.text = text
}
fun setNextBtn(text: String) {
nextBtn!!.text = text
}
fun setLocationX(x: Int) {
locationX = x
}
fun setLocationY(y: Int) {
locationY = y
}
fun addBuildingBean(bean: BuildingBean) {
buildingBean = bean
if (buildingBean != null && mName != null) {
mName!!.text = buildingBean!!.BuildingName
mContent!!.text = buildingBean!!.OrganizationName
if (buildingBean!!.BuildingState == "1") {
setPreBtnText("恢复")
}
else {
setPreBtnText("停用")
}
}
}
private var valueAnimator:ValueAnimator? = null
private fun addAnimationValue(popView: View, popHeight: Float){
valueAnimator = ValueAnimator.ofFloat(popHeight, 0f)
valueAnimator!!.setDuration(500)
valueAnimator!!.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener{
override fun onAnimationUpdate(p0: ValueAnimator?) {
val value = p0!!.animatedValue as Float
popView.translationY = value
popView.requestLayout()
}
})
}
}
GridView肯定是要配合Adapter用的,另外图片的显示也需要用图片缓存处理ImageCache来,如果你比较懒,可以看我另外一篇博客。至于GridView,还是需要改改的,至少onMeasure方法可以改一下,因为我的是嵌套在listView里面,所以不想变成滚动的GridView的话建议还是重写这个View吧。
class SubGridView : GridView {
@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs, 0) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE shr 2, View.MeasureSpec.AT_MOST)
super.onMeasure(widthMeasureSpec, expandSpec)
}
}
使用时就很简单了。收功~
<com.IntelligenceSecuritySystem.view.SubGridView
android:id="@+id/add_inspect_pics"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="@+id/add_inspect_result"
app:layout_constraintRight_toRightOf="@+id/add_inspect_result"
app:layout_constraintTop_toBottomOf="@+id/add_inspect_result"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="@dimen/inspect_margin_top"
android:layout_marginBottom="@dimen/inspect_margin"
android:verticalSpacing="10dp"
android:numColumns="4">
</com.IntelligenceSecuritySystem.view.SubGridView>