先上效果图:
标有on/off的两个滑块是仿照我的“可拖动的按钮”做的自定义View:
public class CustomDragView extends ImageButton{ private int rightBoundary = 10000; //向右滑动边界 private int leftBoundary = 0; //向左滑动边界 private int screenWidth; //屏幕宽度 private int CurrentX; //触摸位置X坐标 private int flag; //判断是否拖动 private int mid; //滑块中心位置 private Paint paint = new Paint(); private boolean isInit = true; Resources res = getResources(); //getDisplayMetrics()返回当前展示的metrics. //metrics中有density、widthPixels、heighPixelst、scaledDensity、xdpi、ydpi六个属性 //density英文含义为密度,表示展示的逻辑密度,它是Dip(Density Independent Pixel设备独立像素,也就是常用的dp)的一个比例因子 //在一个大约160dpi(dot per inch)的屏幕上,一个DIP就是一个像素,这是系统屏显的基准 //举例:在160dpi的屏幕上density的值为1,在120dpi的屏幕上density的值为0.75 DisplayMetrics metrics = res.getDisplayMetrics(); private final int offset = (int) (16.5 * metrics.density); private final int textSize = (int) (14 * metrics.density); public CustomDragView(Context context, int leftBoundary, int rightBoundary) { super(context); this.rightBoundary = rightBoundary; this.leftBoundary = leftBoundary; } //如果要在XML布局文件中使用该自定义组建,则必须定义该构造方法 public CustomDragView(Context context, AttributeSet attrs) { super(context, attrs, 0); } //重写onTouchEvent()方法,控制组建随拖动改变位置(只改变X坐标) @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); int ea=event.getAction(); switch(ea) { case MotionEvent.ACTION_DOWN: CurrentX = (int) event.getRawX(); //getRawX(),getRawY()获取的是相对于屏幕的坐标值 flag=0; //它们是MotionEvent的方法 break; case MotionEvent.ACTION_MOVE: int dx =(int)event.getRawX() - CurrentX; //getLeft(),getTop(),getRight(),getBottom()获取 int left = this.getLeft() + dx; //的是组建左、上、右、下边界相对于父布局的坐标值 int top = this.getTop(); //它们是View的方法 int right = this.getRight() + dx; int bottom = this.getBottom(); mid = (left + right)/2; if(mid < leftBoundary){ mid = leftBoundary; right = mid + this.getWidth() / 2; //getWidth(),getHeight()获取的是组建的宽、高,它们是View的方法 left = right - this.getWidth(); } if(mid > rightBoundary){ mid = rightBoundary; left = mid - this.getWidth() / 2; right = left + this.getWidth(); } this.layout(left, top, right, bottom); CurrentX = (int) event.getRawX(); flag=1; postInvalidate(); break; case MotionEvent.ACTION_UP: if(flag==0) { return false; } else { return true; } } return true; } @SuppressLint("NewApi") @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); paint.setARGB(255, 255, 255, 255); paint.setAntiAlias(true); //paint.setTextAlign()设置paint绘制文字的对齐方式: //Paint.Align.CENTER表示居中对齐 //Paint.Align.LEFT、Paint.Align.RIGHT分别表示左对齐、右对齐 paint.setTextAlign(Paint.Align.CENTER); paint.setTextSize(textSize); if(isInit) { mid = (getLeft()+getRight()) / 2; rightBoundary = screenWidth; leftBoundary = 0; isInit = false; } //下面的方法控制控件绘制text的方法:通常情况下,控件将时间绘制在中间 //当控件左边缘滑动到屏幕左边之后,文字偏向右边显示,反之,偏向左边显示 if(mid >= (getRight() - getLeft())/2 - offset && mid <= screenWidth - (getRight() - getLeft())/2 + offset) { //Canvas.drawText(String text, float x, float y, Paint paint)方法中 //x表示绘制文字的起始位置(左边),y则表示绘制文字的baseline,也就是底部位置, //这两个数值都是相对于控件的位置,不是相对于屏幕的位置。 canvas.drawText(Cast_X_to_time(), (getRight() - getLeft())/2, textSize, paint); } else if(mid < (getRight() - getLeft())/2 - offset) { canvas.drawText(Cast_X_to_time(), getWidth() - mid - offset, textSize, paint); } else if(mid > screenWidth - (getRight() - getLeft())/2 + offset) { canvas.drawText(Cast_X_to_time(), screenWidth - mid + offset, textSize, paint); } } public int getflag() { return flag; } public void setLeftBoundary(int leftBoundary) { this.leftBoundary = leftBoundary; } public void setRightBoundary(int rightBoundary) { this.rightBoundary = rightBoundary; } public void setScreenWidth(int screenWidth) { this.screenWidth = screenWidth; } public int getLeftBoundary() { return leftBoundary; } public int getRightBoundary() { return rightBoundary; } public int getXposition() { return mid; } public void setLayout(int left){ this.layout(left, this.getTop(), left+this.getWidth(), this.getBottom()); mid = left + this.getWidth() / 2; invalidate(); }/** * @author sofa * 如果把屏幕横坐标换轴当作时间轴,该方法把屏幕横坐标换算为时间 * @return */ private String Cast_X_to_time() { float temp = (float)mid * 1440 / screenWidth ; int hour = (int) (temp / 60); int min = (int) (temp % 60); if(min >= 10) return ""+hour+":"+min; else { return ""+hour+":0"+min; } } }
on/off滑块下面的色块条也是自定义View:
public class CustomLengthView extends Button{ private int leftBoundary = 0; private int rightBoundary = 0; private int mCurrentX; private boolean ifAddNewTiming = true; private List<Zone> list = new ArrayList<Zone>(); private List<Zone> tempList = new ArrayList<Zone>(); private Paint paint = new Paint(); private final int lineWidth = 3; public CustomLengthView(Context context) { super(context); } public CustomLengthView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @SuppressLint("ResourceAsColor") @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub // super.onDraw(canvas); paint.setARGB(255, 32, 201, 147); //绘制边框 canvas.drawRect(0, 0, getRight(), lineWidth, paint); canvas.drawRect(0, getBottom()-getTop()-lineWidth, getRight(), getBottom() - getTop(), paint); //绘制正在随滑块变动的灰色色块 if(ifAddNewTiming) { paint.setARGB(255, 67, 80, 76); canvas.drawRect(leftBoundary, lineWidth, rightBoundary, getBottom() - getTop() - lineWidth, paint); } //绘制待添加的灰色色块 for(int i = 0; i < tempList.size(); i++) { paint.setARGB(255, 67, 80, 76); canvas.drawRect(tempList.get(i).startX, lineWidth, tempList.get(i).endX, getBottom() - getTop() - lineWidth, paint); } //绘制已经添加的绿色色块 for(int i = 0; i < list.size(); i++) { paint.setARGB(255, 32, 201, 147); canvas.drawRect(list.get(i).startX, lineWidth, list.get(i).endX, getBottom() - getTop() - lineWidth, paint); } } public void setBoundary(int left, int right) { leftBoundary = left; rightBoundary = right; postInvalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub int ea=event.getAction(); switch (ea) { case MotionEvent.ACTION_DOWN: mCurrentX = (int) event.getRawX(); Log.v("ACTION_DOWN","ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.v("ACTION_MOVE","ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.v("ACTION_UP","ACTION_UP"); break; default: break; } return super.onTouchEvent(event); } public int getTouchedX() { return mCurrentX; } public void setNewTimingZone(int startX, int endX) { Zone zone = new Zone(); zone.startX = startX; zone.endX = endX; list.add(zone); postInvalidate(); } public void setTempTimingZone(int startX, int endX) { Zone zone = new Zone(); zone.startX = startX; zone.endX = endX; tempList.add(zone); postInvalidate(); } public void clearTempTimingZone() { tempList.clear(); } public void deleteTimingZone(int x) { for(int i = 0; i < list.size(); i++) { if(list.get(i).startX <= x && list.get(i).endX >=x) { list.remove(i); postInvalidate(); } } } private class Zone { int startX; int endX; } public List<Zone> getList() { return list; } public void setList(List<Zone> list) { this.list = list; } public List<Zone> getTempList() { return tempList; } public void setTempList(List<Zone> tempList) { this.tempList = tempList; } }
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#000" android:layout_marginTop="18dp" tools:context=".MainActivity" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#1f1f1f" > <Button android:id="@+id/timer_save" android:layout_width="53.5dp" android:layout_height="21.5dp" android:background="#0000" android:text="@string/timer_save" android:textColor="#fff" android:textSize="14dp" android:layout_centerVertical="true" android:layout_alignParentRight="true"/> <ImageView android:layout_width="1dp" android:layout_height="12dp" android:background="#fff" android:layout_centerVertical="true" android:layout_toLeftOf="@id/timer_save" /> <Button android:id="@+id/timer_add" android:layout_width="53.5dp" android:layout_height="21.5dp" android:background="#0000" android:text="@string/timer_add" android:textColor="#fff" android:textSize="14dp" android:layout_centerVertical="true" android:layout_toLeftOf="@id/timer_save" />" </RelativeLayout> <RelativeLayout android:id="@+id/timer_layout" android:layout_width="fill_parent" android:layout_height="200dp" android:background="#1f1f1f" > <com.example.test1.CustomDragView android:id="@+id/rihgtDragView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/timing_off" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" /> <com.example.test1.CustomDragView android:id="@+id/leftDragView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/timing_on" android:layout_alignParentBottom="true" /> <View android:id="@+id/invisible_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#0000" /> </RelativeLayout> <com.example.test1.CustomLengthView android:id="@+id/lengthView" android:layout_width="match_parent" android:layout_height="30.5dp" android:background="#1f1f1f" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height="25dp" > <ImageView android:id="@+id/timer_repeat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/timing_repeat_default" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_marginRight="35dp" /> <TextView android:id="@+id/timer_repeat_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/timer_repeat" android:layout_centerVertical="true" android:layout_toLeftOf="@id/timer_repeat" android:layout_marginRight="11dp" /> </RelativeLayout> <RelativeLayout android:layout_width="fill_parent" android:layout_height="32dp" android:background="#1f1f1f" > <GridView android:id="@+id/timer_gridview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:numColumns="7" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" /> </RelativeLayout> </LinearLayout>
测试Activity:
public class MainActivity extends Activity { CustomDragView leftDragView; CustomDragView rightDragView; CustomLengthView lengthView; private final String[] days = new String[] { "日","一","二","三","四","五","六", }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获得屏幕分辨率 DisplayMetrics dm = getResources().getDisplayMetrics(); final int screenWidth = dm.widthPixels; View view = findViewById(R.id.invisible_view); view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub return true; } }); view.setVisibility(View.GONE); // view.setVisibility(View.VISIBLE); leftDragView = (CustomDragView)findViewById(R.id.leftDragView); rightDragView = (CustomDragView)findViewById(R.id.rihgtDragView); lengthView = (CustomLengthView)findViewById(R.id.lengthView); leftDragView.setLeftBoundary(leftDragView.getWidth()/2); rightDragView.setRightBoundary(screenWidth - rightDragView.getWidth()/2); leftDragView.setScreenWidth(screenWidth); rightDragView.setScreenWidth(screenWidth); leftDragView.setFocusableInTouchMode(false); rightDragView.setFocusableInTouchMode(false); // lengthView.setBoundary(rightDragView.getLeftBoundary(),leftDragView.getRightBoundary()); leftDragView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub int ea=event.getAction(); switch (ea) { case MotionEvent.ACTION_DOWN: leftDragView.setRightBoundary(rightDragView.getLeft() + rightDragView.getWidth() / 2); break; case MotionEvent.ACTION_MOVE: rightDragView.setLeftBoundary(leftDragView.getRight() - leftDragView.getWidth() / 2); lengthView.setBoundary(rightDragView.getLeftBoundary(),leftDragView.getRightBoundary()); break; case MotionEvent.ACTION_UP: rightDragView.setLeftBoundary(leftDragView.getRight() - leftDragView.getWidth() / 2); lengthView.setBoundary(rightDragView.getLeftBoundary(),leftDragView.getRightBoundary()); break; default: break; } return false; } }); rightDragView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub int ea=event.getAction(); switch (ea) { case MotionEvent.ACTION_DOWN: rightDragView.setLeftBoundary(leftDragView.getRight() - leftDragView.getWidth() / 2); break; case MotionEvent.ACTION_MOVE: leftDragView.setRightBoundary(rightDragView.getLeft() + rightDragView.getWidth() / 2); lengthView.setBoundary(rightDragView.getLeftBoundary(),leftDragView.getRightBoundary()); break; case MotionEvent.ACTION_UP: leftDragView.setRightBoundary(rightDragView.getLeft() + rightDragView.getWidth() / 2); lengthView.setBoundary(rightDragView.getLeftBoundary(),leftDragView.getRightBoundary()); break; default: break; } return false; } }); lengthView.setClickable(true); lengthView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { // TODO Auto-generated method stub lengthView.deleteTimingZone(lengthView.getTouchedX()); return false; } }); List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>(); for(int i = 0; i < days.length; i++) { Map<String, Object> listItem = new HashMap<String, Object>(); listItem.put("day", days[i]); listItems.add(listItem); } SimpleAdapter simpleAdapter = new SimpleAdapter(this , listItems, R.layout.smart_socket_new_timer_gridviewitem , new String[]{"day"}, new int []{R.id.smart_socket_new_timer_gridviewitem_text}); GridView gridView = (GridView)findViewById(R.id.smart_socket_new_timer_gridview); gridView.setAdapter(simpleAdapter); lengthView.setNewTimingZone(50, 250); lengthView.setTempTimingZone(300, 350); lengthView.setNewTimingZone(500, 700); leftDragView.postDelayed(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub leftDragView.setLayout(300); leftDragView.invalidate(); } },300); // leftDragView.setLayout(600); // rightDragView.setLayout(250); } }