package aisk.timebar; import aisk.bottombar.R; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; /** * to use this widget, you can use following code * <code><br/> * in activity<br/> * TimePicker picker = (TimePicker) findViewById(R.id.picker);<br/> * int[] data = {1, 3, 5, 7, 13, 15, 19, 24, 29, 33, 37, 41, 48, 49, 50};<br/> * picker.setTimeData(data);<br/> * in res/layout/main.xml<br/> * <aisk.timebar.TimePicker<br/> * android:id="@+id/picker"<br/> * android:layout_width="fill_parent"<br/> * android:layout_height="wrap_content"/><br/> * </code><br/> * * @author Jayzhou215 * @email jayzhou215@ssreader.cn * @qq 512582912 * */ public class TimePicker extends RelativeLayout { private TimeBar timeBar; private TimePanel timePanelLeft; private TimePanel timePanelRight; private TextView focusedBtn; private final int WC = RelativeLayout.LayoutParams.WRAP_CONTENT; private final int FP = RelativeLayout.LayoutParams.FILL_PARENT; public final int WIDTH = 100; public final int HEIGHT = 64; public TimePicker(Context context) { this(context, null); } public TimePicker(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); creatView(context); } public void setTimeData(int[] data){ timeBar.setTimeData(data); } private void creatView(Context context) { timeBar = new TimeBar(context); timePanelLeft = new TimePanel(context); timePanelRight = new TimePanel(context); LayoutParams lp; lp = new LayoutParams(FP, WC); lp.addRule(CENTER_VERTICAL, RelativeLayout.TRUE); addView((View)timeBar, lp); lp = new LayoutParams(WC, WC); lp.addRule(ALIGN_PARENT_LEFT, RelativeLayout.TRUE); lp.addRule(CENTER_VERTICAL, RelativeLayout.TRUE); addView((View)timePanelLeft, lp); lp = new LayoutParams(WC, WC); lp.addRule(ALIGN_PARENT_RIGHT, RelativeLayout.TRUE); lp.addRule(CENTER_VERTICAL, RelativeLayout.TRUE); addView((View)timePanelRight, lp); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int x = timeBar.getScrollX(); focusedBtn = (TextView)timeBar.getSelectedView(); if (focusedBtn != null){ if (focusedBtn.getLeft() - x < 0){ ((TextView)timePanelLeft.getChildTextView()).setText(focusedBtn.getText()); timePanelLeft.setVisibility(View.VISIBLE); timePanelRight.setVisibility(View.GONE); } else if (focusedBtn.getRight() - x > getWidth()){ ((TextView)timePanelRight.getChildTextView()).setText(focusedBtn.getText()); timePanelRight.setVisibility(View.VISIBLE); timePanelLeft.setVisibility(View.GONE); } else{ timePanelRight.setVisibility(View.GONE); timePanelLeft.setVisibility(View.GONE); } } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { timeBar.onTouchEvent(ev); return super.dispatchTouchEvent(ev); } private class TimeBar extends HorizontalScrollView { private TextView mSelectedView; private Paint paint; private Triangle curTriangle = null; private Triangle tarTriangle = null; private int[] mData; private Context mContext; private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT; public TimeBar(Context context) { this(context, null); } public TimeBar(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setWillNotDraw(false); setHorizontalScrollBarEnabled(false); } public int[] getTimeData(){ return mData; } public void setTimeData(int[] data) { mData = data; if (mData == null) return; LinearLayout layout = new LinearLayout(mContext); LinearLayout.LayoutParams lp; for (int i = 0; mData.length > i; i++){ TextView textView = new TextView(mContext); textView.setText(Integer.toString(mData[i])); textView.setTextColor(Color.WHITE); textView.setGravity(Gravity.CENTER); textView.setTextSize(20); textView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mSelectedView = (TextView) view; tarTriangle.left = view.getLeft() + view.getWidth()/2 - 10; tarTriangle.right = view.getLeft() + view.getWidth()/2 + 10; tarTriangle.top = view.getTop() - 4; tarTriangle.bottom = view.getTop() + 13.3f; invalidate(); } }); lp = new LinearLayout.LayoutParams(WIDTH, HEIGHT); lp.gravity = CENTER_HORIZONTAL; layout.addView((View)textView, lp); if (i == 0) mSelectedView = textView; } lp = new LinearLayout.LayoutParams(WC, HEIGHT); addView(layout); } public void setSelectedView(TextView i) { mSelectedView = i; } public TextView getSelectedView() { return mSelectedView; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); //Log.d("Validated!", "Should not always validate"); if (mSelectedView != null){ int step = getWidth()/30; canvas.drawColor(Color.BLACK); paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.LTGRAY); paint.setStyle(Paint.Style.FILL); if (curTriangle == null){ curTriangle = new Triangle( mSelectedView.getLeft() + mSelectedView.getWidth()/2 - 10, mSelectedView.getTop() - 4, mSelectedView.getLeft() + mSelectedView.getWidth()/2 + 10, mSelectedView.getTop() + 13.3f ); } if (tarTriangle == null){ tarTriangle = new Triangle( mSelectedView.getLeft() + mSelectedView.getWidth()/2 - 10, mSelectedView.getTop() - 4, mSelectedView.getLeft() + mSelectedView.getWidth()/2 + 10, mSelectedView.getTop() + 13.3f ); } if (Math.abs(curTriangle.left - tarTriangle.left) < step) { curTriangle.left = tarTriangle.left; curTriangle.right = tarTriangle.right; curTriangle.reDraw(); } if (curTriangle.left > tarTriangle.left){ curTriangle.left -= step; curTriangle.right -= step; curTriangle.reDraw(); invalidate(); } else if (curTriangle.left < tarTriangle.left) { curTriangle.left += step; curTriangle.right += step; curTriangle.reDraw(); invalidate(); } canvas.drawPath(curTriangle.getPath(), paint); } } } private class TimePanel extends LinearLayout { private Paint paint; private TextView mTextView; private Triangle curTriangle = null; public TimePanel(Context context) { this(context, null); } public TimePanel(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); paint = new Paint(); paint.setAntiAlias(true); mTextView = new TextView(context); mTextView.setTextColor(Color.WHITE); mTextView.setGravity(Gravity.CENTER); mTextView.setTextSize(20); LinearLayout.LayoutParams lp; lp = new LinearLayout.LayoutParams(WIDTH, HEIGHT); lp.gravity = CENTER_HORIZONTAL; addView((View)mTextView, lp); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.BLACK); paint.setColor(Color.LTGRAY); paint.setStyle(Paint.Style.FILL); if (curTriangle == null){ curTriangle = new Triangle( mTextView.getLeft() + mTextView.getWidth()/2 - 10, mTextView.getTop() - 4, mTextView.getLeft() + mTextView.getWidth()/2 + 10, mTextView.getTop() + 13.3f ); } canvas.drawPath(curTriangle.getPath(), paint); } public TextView getChildTextView(){ return mTextView; } } public class Triangle implements Parcelable{ public float left; public float top; public float right; public float bottom; private Path mPath; public Path getPath() { return mPath; } public void setPath(Path mPath) { this.mPath = mPath; } public Triangle(float left, float top, float right, float bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; mPath = new Path(); mPath.moveTo(left, top); mPath.lineTo(right, top); mPath.lineTo((left + right)/2, bottom); mPath.close(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeFloat(left); dest.writeFloat(top); dest.writeFloat(right); dest.writeFloat(bottom); } public void reDraw() { mPath.reset(); mPath.moveTo(left, top); mPath.lineTo(right, top); mPath.lineTo((left + right)/2, bottom); mPath.close(); } } }