您的位置:首页 > 移动开发 > Android开发

android 仿nice实现在图片上打标签

2016-02-27 15:25 453 查看
如果有玩过nice这款APP的话,里面有个在图片上打标签的功能,如图



实现原理:

1:实现自定义一个ViewGroup类型,设置好它的背景,

2:在onTouch down的时候,获取相对于view的按下的x,y坐标,然后遍历所有的子view判断是否重叠因为每个view其实都是一个矩形,Rect类方法中可以判断该点是否在view上,

大概就这些,下面是实现的源码:

PictureTagLayout.java

package com.example.tagview.view;

import com.example.tagview.view.TagView.Direction;

import com.example.tagview.view.TagView.Status;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.Rect;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnTouchListener;

import android.widget.RelativeLayout;

public class PictureTagLayout extends RelativeLayout implements OnTouchListener {

private static final int CLICKRANGE = 5;

private static final String TAG = PictureTagLayout.class.getSimpleName();

private View touchView,clickView;//单机和触摸都可以打标签

private int startX;//按下的x轴坐标

private int startY;//按下的y轴坐标

@SuppressLint("ClickableViewAccessibility")

public PictureTagLayout(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

setOnTouchListener(this);

}

public PictureTagLayout(Context context, AttributeSet attrs) {

this(context, attrs,0);

}

public PictureTagLayout(Context context) {

this(context,null);

}

@SuppressLint("ClickableViewAccessibility")

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

touchView = null;

if(clickView!=null){//这个clickView什么时候给它赋值呢?

((TagView)clickView).setStatus(Status.Normal);

clickView = null;

}

startX = (int) event.getX();//获取按下的x轴坐标 相对于view本身的左上角

startY = (int) event.getY();//获取按下的y轴坐标,相对于view本身

if(!hasView(startX,startY)){//表示重叠

addItem(startX,startY);

}

break;

case MotionEvent.ACTION_UP:

int endX = (int) event.getX();

int endY = (int) event.getY();

//如果挪动的范围很小,则判定为单击

if(touchView!=null&&Math.abs(endX - startX)<CLICKRANGE&&Math.abs(endY - startY)<CLICKRANGE){

//当前点击的view进入编辑状态

((TagView)touchView).setStatus(Status.Edit);

clickView = touchView;

}

touchView = null;

break;

}

return true;

}

//循环获取子view,判断xy是否在子view上,即判断是否按住了子view

private boolean hasView(int x,int y){

for(int index = 0; index < this.getChildCount(); index ++){//遍历相对布局中所有的子view然后生成一个矩形,

View view = this.getChildAt(index);

int left = (int) view.getX();

int top = (int) view.getY();

int right = view.getRight();

int bottom = view.getBottom();

Rect rect = new Rect(left, top, right, bottom);//生成一个矩形

Rect newRect = new Rect(x,y,x+TagView.getViewWidth(),y+TagView.getViewHeight());

boolean isContains = rect.intersect(newRect);//判断view是否交互

//如果没有交互

if(isContains){

touchView = view;

touchView.bringToFront();//置为父view之上

return true;

}

}

touchView = null;

return false;

}

private void addItem(int x,int y){

View view = null;//就要新生成一个新的view

RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

if(x>getWidth()*0.5){//如果x坐标大于view宽度的一半 用来判断是在左边还是右边

// params.leftMargin = x - TagView.getViewWidth();

params.leftMargin = x;

view = new TagView(getContext(),Direction.Right);//生成一个view对象

}

else{

params.leftMargin = x;

view = new TagView(getContext(),Direction.Left);

}

params.topMargin = y;//向上就是他的y坐标

//上下位置在视图内

if(params.topMargin<0)params.topMargin =0;//边界判断

else if((params.topMargin+TagView.getViewHeight())>getHeight()){//判断这个view 在 这个图片上 防止部分

params.topMargin = getHeight() - TagView.getViewHeight();

}

this.addView(view, params);

}

}

TagView.java 标签view

package com.example.tagview.view;

import com.example.tagview.R;

import android.content.Context;

import android.view.KeyEvent;

import android.view.LayoutInflater;

import android.view.View;

import android.view.inputmethod.InputMethodManager;

import android.widget.EditText;

import android.widget.RelativeLayout;

import android.widget.TextView;

import android.widget.TextView.OnEditorActionListener;

/**

* tag view

* @author Adminis

*

*/

public class TagView extends RelativeLayout implements OnEditorActionListener {

private TextView tvPictureTagLabel;

private EditText etPictureTagLabel;

private View loTag;

private InputMethodManager mInputMethodManager;

public enum Status{Normal,Edit}//标签是编辑状态还是正常的状态

public enum Direction{Left,Right}

private Direction direction = Direction.Left;//标签是左边还是右边

private Context mContext;

private static final int ViewWidth = 80;//单位像素

private static final int ViewHeight = 50;

public TagView(Context context, Direction direction) {

super(context);

this.direction = direction;

this.mContext = context;

initViews();

init();

initEvents();

}

private void init() {

mInputMethodManager = (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE);

directionChange();

}

private void directionChange() {

switch(direction){

case Left:

loTag.setBackgroundResource(R.drawable.bg_picturetagview_tagview_left);

break;

case Right:

loTag.setBackgroundResource(R.drawable.bg_picturetagview_tagview_right);

break;

}

}

/**

* 初始化view

*/

private void initViews() {

LayoutInflater.from(mContext).inflate(R.layout.activity_tag_view, this,true);

tvPictureTagLabel = (TextView) findViewById(R.id.tvPictureTagLabel);

etPictureTagLabel = (EditText) findViewById(R.id.etPictureTagLabel);

loTag = findViewById(R.id.loTag);

}

/** 初始化事件 **/

protected void initEvents(){

etPictureTagLabel.setOnEditorActionListener(this);

}

public static int getViewWidth(){

return ViewWidth;

}

public static int getViewHeight(){

return ViewHeight;

}

@Override

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

setStatus(Status.Normal);

return true;

}

public void setStatus(Status status){

switch(status){

case Normal:

tvPictureTagLabel.setVisibility(View.VISIBLE);

etPictureTagLabel.clearFocus();

tvPictureTagLabel.setText(etPictureTagLabel.getText());

etPictureTagLabel.setVisibility(View.GONE);

//隐藏键盘

mInputMethodManager.hideSoftInputFromWindow(etPictureTagLabel.getWindowToken() , 0);

break;

case Edit:

tvPictureTagLabel.setVisibility(View.GONE);

etPictureTagLabel.setVisibility(View.VISIBLE);

etPictureTagLabel.requestFocus();

//弹出键盘

mInputMethodManager.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);

break;

}

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

super.onLayout(changed, l, t, r, b);

View parent = (View) getParent();//父view就是PictureTagLayout

int halfParentW = (int) (parent.getWidth()*0.5);//获取父view宽度的一半

int center = (int) (l + (this.getWidth()*0.5));

if(center<=halfParentW){

direction = Direction.Left;

}

else{

direction = Direction.Right;

}

directionChange();

}

}

activity_tag_view.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center_vertical"

android:orientation="horizontal" >

<RelativeLayout

android:id="@+id/loTag"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@drawable/bg_picturetagview_tagview_left" >

<TextView

android:id="@+id/tvPictureTagLabel"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@null"

android:gravity="center_vertical"

android:hint="标签"

android:singleLine="true"

android:textColor="@android:color/white"

android:textColorHint="@android:color/white"

android:textSize="12dp" />

<EditText

android:id="@+id/etPictureTagLabel"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@null"

android:gravity="center_vertical"

android:hint="标签"

android:imeOptions="actionDone"

android:maxEms="20"

android:singleLine="true"

android:textColor="@android:color/white"

android:textColorHint="@android:color/white"

android:textSize="12dp"

android:visibility="gone" />

</RelativeLayout>

</LinearLayout>

最终的效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: