اندروید - ایجاد نقاط حساس به لمس در تصویر
چند وقت پبش یه پروژه ای رو شروع کردم که بیشتر حکم تمرین رو داشت
این پروژه در واقع یک نرم افزار اندروید هست برای دانشجویان مهندسی نفت، یکی از بخش های این نرم افزار مربوط میشه به توضیحات دکل حفاری و کامپوننت های مرتبط با دکل
رفرنسی که برای شماتیک دلک داشتم، در ۲۵ ناحیه شماره گذاری شده بود و هدف این بود که با لمس شدن هرکدوم از اون محدوده ها اطلاعاتش نمایش داده بشه:
راه حلی که به ذهنم رسید این بود که یک تصویر بعنوان ماسک ایجاد کنم که هرکدوم از این ناحیه ها، با یک رنگ مشخص مارک بشن. دراین حالت میشه با محاسبه پیکسلی که لمس شده و بدست آوردن رنگ پیکسل ماسک در همون مختصات؛ واکنش خاصی نسبت به لمس شدن هرکدوم از اون ناحیه ها نشون داد:
مثلاً اگر رنگ پیکسل در اون ناحیه برابر -65536
باشه یعنی ناحیه ی شماره ی ۱
لمس شده
کدی که برای اینکار استفاده کردم این هست:
public class MainActivity extends Activity implements OnTouchListener { private int[] texts = { R.string.crown_block, R.string.catline, R.string.drilling_line, R.string.monkeyboard, R.string.traveling_block, R.string.top_drive, R.string.mast, R.string.drill_pipe, R.string.doghouse, R.string.bop, R.string.water_tank, R.string.ect, R.string.egs, R.string.fuel_tanks, R.string.electric_house, R.string.mud_pump, R.string.bulk_mud, R.string.mud_pits, R.string.reserve_pits, R.string.mgs, R.string.shale_shaker, R.string.choke_manifold, R.string.pipe_ramp, R.string.pipe_racks, R.string.accumulator }; private int[] images = { R.drawable.crown_block, R.drawable.catline, R.drawable.drilling_line, R.drawable.monkeyboard, R.drawable.traveling_block, R.drawable.top_drive, R.drawable.mast, R.drawable.drill_pipe, R.drawable.doghouse, R.drawable.bop, R.drawable.water_tank, R.drawable.ect, R.drawable.egs, R.drawable.fuel_tanks, R.drawable.electric_house, R.drawable.mud_pump, R.drawable.bulk_mud, R.drawable.mud_pits, R.drawable.reserve_pits, R.drawable.mgs, R.drawable.shale_shaker, R.drawable.choke_manifold, R.drawable.pipe_ramp, R.drawable.pipe_racks, R.drawable.accumulator }; private String[] titles = { "Crown Block and Water Table", "Catline Boom and Hoist Line", "Drilling Line", "Monkey Board", "Traveling Block", "Top Drive", "Mast", "Drill Pipe", "Doghouse", "Blowout Preventer", "Water Tank", "Electric Cable Tray", "Engine Generator Sets", "Fuel Tanks", "Electric House", "Mud Pump", "Bulk Mud Components in Storage", "Mud Pits", "Reserve Pits", "Mud Gas Separator", "Shale Shaker", "Choke Manifold", "Pipe Ramp", "Pipe Racks", "Accumulator" }; private float diffW; private float diffH; private float finalWidth; private float finalHeight; private Bitmap bitmap; private HashMap<Integer, Integer> map; private int startX = 0; private int startY = 0; @Override public void onCreate(Bundle inState) { super.onCreate(inState); prepairList(); sv = (ScrollView) findViewById(R.id.image_scrollview); sv.setOnTouchListener(this); final ImageView iv = (ImageView) findViewById(R.id.imageView1); // getting an instance of Mask Image Drawable drawable = getResources().getDrawable(R.drawable.rigmask); bitmap = ((BitmapDrawable) drawable).getBitmap(); final float maskW = bitmap.getWidth(); final float maskH = bitmap.getHeight(); ViewTreeObserver vto = iv.getViewTreeObserver(); vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { finalHeight = iv.getMeasuredHeight(); finalWidth = iv.getMeasuredWidth(); diffW = finalWidth / maskW; diffH = finalHeight / maskH; return true; } }); } @SuppressLint("UseSparseArrays") private void prepairList() { map = new HashMap<Integer, Integer>(); map.put(-65536, 0); map.put(-16772904, 1); map.put(-16264, 2); map.put(-16721904, 3); map.put(-18408, 4); map.put(-33704, 5); map.put(-10984193, 6); map.put(-3652353, 7); map.put(-1019736, 8); map.put(-6885871, 9); map.put(-2792917, 10); map.put(-8355840, 11); map.put(-8883080, 12); map.put(-7798944, 13); map.put(-13421688, 14); map.put(-5494625, 15); map.put(-14120293, 16); map.put(-2031391, 17); map.put(-14981789, 18); map.put(-2611316, 19); map.put(-15439077, 20); map.put(-9106610, 21); map.put(-11214683, 22); map.put(-5559150, 23); map.put(-8855297, 24); } @Override public boolean onTouch(View v, MotionEvent event) { if (v.getId() == R.id.imageView1 || v.getId() == R.id.image_scrollview) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = (int) event.getX(); startY = (int) event.getY(); break; case MotionEvent.ACTION_UP: int cordinate_Y = (int) ((event.getY() + v.getScrollY()) / diffH); int cordinate_X = (int) ((event.getX() + v.getScrollX()) / diffW); if ((Math.abs((int) event.getX() - startX) > 10) || (Math.abs((int) event.getY() - startY) > 10)) { break; } int pixelColor = bitmap.getPixel(cordinate_X, cordinate_Y); if (pixelColor != -1) { showDetails(texts[map.get(pixelColor)], images[map.get(pixelColor)], titles[map.get(pixelColor)]); } break; } } return false; } private void showDetails(int text, int image, String title) { Intent intent = new Intent(this, DetailsActivity.class); intent.putExtra("TEXT", text); intent.putExtra("IMAGE", image); intent.putExtra("TITLE", title); startActivity(intent); } }
درواقع در این کد در متد prepareList یک HashMap ایجاد کردم که کلید (Key) کد رنگ ها هست و مقدار (Value) شماره ی اون ناحیه هست.
سورس قسمتی از پروژه رو از گیت هاب می تونید دانلود کنید (توجه داشته باشید که تغییرات نهایی تو مخزن گیت هاب اضافه نشده و نرم افزار ممکنه باگ هایی داشته باشه):