दिलचस्प पोस्ट
कैसे Mockito matchers काम करते हैं? लाइन काट, तर्क सूची में सिंटैक्स त्रुटि कैसे एक बालक तत्व के लिए अस्पष्टता रद्द करने के लिए? एंड्रॉयड UI थ्रेड स्टैक आकार की सीमा क्या है और इसे कैसे दूर करना है? फेसबुक ओपन ग्राफ़ नहीं समाशोधन कैश Array.size () बनाम अर्रे। लांघ android.content.res.Resources $ NotFoundException: स्ट्रिंग संसाधन ID # 0x0 कैसे सी # का उपयोग कर HTML टैग को साफ करने के लिए कैसे printf के माध्यम से बाइनरी संख्या को मुद्रित करने के लिए सीएसएस का प्रयोग करके आईई 8 में अक्षम एचटीएमएल कंट्रोल का रंग कैसे बदल सकता है Struts.xml पर उपयोग किए बिना किसी अन्य एक्शन वर्ग पर पुनर्निर्देशित करने का कोई तरीका क्या है? मैं बाउश में एक उद्धृत स्ट्रिंग में न्यूलाइन कैसे सुरक्षित रखूं? क्या जावा हैशमॅप कीसेट () चलना क्रम संगत है? किसी लोकेल विशिष्ट स्ट्रिंग से NSDecimalNumber प्राप्त करना? MVVM WPF में नई विंडो खोलना

एंड्रॉइड: स्पर्श चाल पर एक दृश्य ले जाएं (ACTION_MOVE)

मैं एक साधारण नियंत्रण करना चाहता हूं: अंदर एक दृश्य के साथ एक कंटेनर अगर मैं कंटेनर को स्पर्श करता हूं और मैं उंगली चलाता हूं, तो मैं अपनी उंगली का पालन करने के लिए दृश्य को स्थानांतरित करना चाहता हूं।

किस प्रकार के कंटेनर (लेआउट) मैं उपयोग करना चाहिए? यह कैसे करना है?

मुझे एक सतह का उपयोग करने की आवश्यकता नहीं है, लेकिन एक सरल लेआउट।

Solutions Collecting From Web of "एंड्रॉइड: स्पर्श चाल पर एक दृश्य ले जाएं (ACTION_MOVE)"

कुछ इस तरह:

public class MyActivity extends Activity implements View.OnTouchListener { TextView _view; ViewGroup _root; private int _xDelta; private int _yDelta; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); _root = (ViewGroup)findViewById(R.id.root); _view = new TextView(this); _view.setText("TextView!!!!!!!!"); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 50); layoutParams.leftMargin = 50; layoutParams.topMargin = 50; layoutParams.bottomMargin = -250; layoutParams.rightMargin = -250; _view.setLayoutParams(layoutParams); _view.setOnTouchListener(this); _root.addView(_view); } public boolean onTouch(View view, MotionEvent event) { final int X = (int) event.getRawX(); final int Y = (int) event.getRawY(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); _xDelta = X - lParams.leftMargin; _yDelta = Y - lParams.topMargin; break; case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_POINTER_UP: break; case MotionEvent.ACTION_MOVE: RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); layoutParams.leftMargin = X - _xDelta; layoutParams.topMargin = Y - _yDelta; layoutParams.rightMargin = -250; layoutParams.bottomMargin = -250; view.setLayoutParams(layoutParams); break; } _root.invalidate(); return true; }} 

main.xml केवल @+id/root साथ RelativeLayout main.xml

मुझे ViewPropertyAnimator के साथ ऐसा करने के लिए एक आसान तरीका मिला है:

 float dX, dY; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: dX = view.getX() - event.getRawX(); dY = view.getY() - event.getRawY(); break; case MotionEvent.ACTION_MOVE: view.animate() .x(event.getRawX() + dX) .y(event.getRawY() + dY) .setDuration(0) .start(); break; default: return false; } return true; } 

@ एंड्री दृष्टिकोण के बाद, यदि आप अपने केंद्र से दृश्य को स्थानांतरित करना चाहते हैं, तो आपको केवल आधे की ऊंचाई और चौड़ाई को आंदोलन में बदलना होगा।

 float dX, dY; @Override public boolean onTouchEvent(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: dX = view.getX() - event.getRawX(); dY = view.getY() - event.getRawY(); break; case MotionEvent.ACTION_MOVE: animate() .x(event.getRawX() + dX - view.getWidth()/2) .y(event.getRawY() + dY - view.getHeight()/2) .setDuration(0) .start(); break; default: return false; } return true; } 

किसी भी मैन्युअल रूप से दर्ज किए गए नंबरों की निर्भरता को हटाने के लिए @ व्याचेस्लाव शिलकिन द्वारा दिए गए समाधान को थोड़ा बदला।

 import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.RelativeLayout; public class MainActivity extends Activity implements View.OnTouchListener { private int _xDelta; private int _yDelta; private int _rightMargin; private int _bottomMargin; private ImageView _floatingView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this._floatingView = (ImageView) findViewById(R.id.textView); this._floatingView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (_floatingView.getViewTreeObserver().isAlive()) _floatingView.getViewTreeObserver().removeOnPreDrawListener(this); updateLayoutParams(_floatingView); return false; } }); this._floatingView.setOnTouchListener(this); } private void updateLayoutParams(View view) { this._rightMargin = -view.getMeasuredWidth(); this._bottomMargin = -view.getMeasuredHeight(); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(view.getMeasuredWidth(), view.getMeasuredHeight()); layoutParams.bottomMargin = this._bottomMargin; layoutParams.rightMargin = this._rightMargin; view.setLayoutParams(layoutParams); } @Override public boolean onTouch(View view, MotionEvent event) { if (view == this._floatingView) { final int X = (int) event.getRawX(); final int Y = (int) event.getRawY(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); this._xDelta = X - lParams.leftMargin; this._yDelta = Y - lParams.topMargin; break; case MotionEvent.ACTION_MOVE: RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); layoutParams.leftMargin = X - this._xDelta; layoutParams.topMargin = Y - this._yDelta; layoutParams.rightMargin = this._rightMargin; layoutParams.bottomMargin = this._bottomMargin; view.setLayoutParams(layoutParams); break; } return true; } else { return false; } } } 

नीचे दिए गए कोड में, मैंने RegionView ( जीआईटी ) नामक कुछ को बनाया है, जो पुन: प्रयोज्य कंटेनर है, जो प्रत्येक नेस्टेड बच्चों के लिए खींचें और ज़ूम संचालन के प्रबंधन के लिए ज़िम्मेदार है।

यहां, हम चित्र के बारे में आंदोलन को अनुकरण करने के लिए, View के LayoutParams बच्चे के top और left LayoutParams को हेरफेर करते हैं। ड्रैग ऑपरेशन के रूप में क्या समझा जा रहा है, और एक पैमाने पर कार्रवाई करने के लिए क्या निर्धारित किया गया है, इसका निपटान करने के द्वारा हम एक बच्चे के View हेरफेर प्रदान कर सकते हैं View

 package com.zonal.regionview; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.os.Vibrator; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.widget.RelativeLayout; import java.util.HashMap; import java.util.Map; /** * Created by Alexander Thomas (@Cawfree) on 20/07/2017. */ /** Enables users to customize Regions Of Interest on a Canvas. */ public class RegionView extends RelativeLayout implements View.OnTouchListener, GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener { /* Member Variables. */ private final GestureDetector mGestureDetector; private final ScaleGestureDetector mScaleGestureDetector; private final Map<Integer, View> mViewMap; private boolean mScaling; private float mScale; private boolean mWrapContent; private boolean mDropOnScale; public RegionView(Context context) { // Implement the Parent. super(context); // Initialize Member Variables. this.mGestureDetector = new GestureDetector(context, this); this.mViewMap = new HashMap<>(); this.mScaleGestureDetector = new ScaleGestureDetector(context, this); this.mScaling = false; this.mScale = Float.NaN; this.mWrapContent = false; this.mDropOnScale = false; // Register ourself as the OnTouchListener. this.setOnTouchListener(this); } public RegionView(Context context, @Nullable AttributeSet attrs) { // Implement the Parent. super(context, attrs); // Initialize Member Variables. this.mGestureDetector = new GestureDetector(context, this); this.mViewMap = new HashMap<>(); this.mScaleGestureDetector = new ScaleGestureDetector(context, this); this.mScaling = false; this.mWrapContent = false; this.mDropOnScale = false; // Register ourself as the OnTouchListener. this.setOnTouchListener(this); } public RegionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { // Implement the Parent. super(context, attrs, defStyleAttr); // Initialize Member Variables. this.mGestureDetector = new GestureDetector(context, this); this.mViewMap = new HashMap<>(); this.mScaleGestureDetector = new ScaleGestureDetector(context, this); this.mScaling = false; this.mWrapContent = false; this.mDropOnScale = false; // Register ourself as the OnTouchListener. this.setOnTouchListener(this); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public RegionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { // Implement the Parent. super(context, attrs, defStyleAttr, defStyleRes); // Initialize Member Variables. this.mGestureDetector = new GestureDetector(context, this); this.mViewMap = new HashMap<>(); this.mScaleGestureDetector = new ScaleGestureDetector(context, this); this.mScaling = false; this.mWrapContent = false; this.mDropOnScale = false; // Register ourself as the OnTouchListener. this.setOnTouchListener(this); } @Override public boolean onTouch(final View v, final MotionEvent event) { // Calculate the PointerId. final int lPointerId = event.getPointerId(event.getActionIndex()); // Handle the TouchEvent. this.getGestureDetector().onTouchEvent(event); this.getScaleGestureDetector().onTouchEvent(event); // Did the user release a pointer? if(event.getAction() == MotionEvent.ACTION_UP) { // Was there a View associated with this Action? final View lView = this.getViewMap().get(lPointerId); // Does the View exist? if(lView != null) { // Remove the View from the Map. this.getViewMap().remove(lPointerId); /** TODO: Provide a Callback? */ } } // Consume all events for now. return true; } @Override public boolean onDown(MotionEvent e) { // Calculate the PointerId. final Integer lPointerId = Integer.valueOf(e.getPointerId(e.getActionIndex())); // Fetch the View. final View lView = this.getViewFor(Math.round(e.getRawX()), Math.round(e.getRawY())); // Is it valid? if(lView != null) { // Watch the View. this.getViewMap().put(lPointerId, lView); // Configure the Anchor. lView.setPivotX(0); lView.setPivotY(0); // Assert that we handled the event. return true; } // Assert that we ignored the event. return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // Are we not scaling? if(!this.isScaling()) { // Calculate the PointerId. final Integer lPointerId = Integer.valueOf(e1.getPointerId(e1.getActionIndex())); // Fetch the View. final View lView = this.getViewMap().get(lPointerId); // Is the scroll valid for a given View? if(lView != null) { // Calculate the Scaled Width and Height of the View. final float lWidth = lView.getWidth() * lView.getScaleX(); final float lHeight = lView.getHeight() * lView.getScaleY(); // Declare the initial position. final int[] lPosition = new int[] { (int)(e2.getX() - ((lWidth) / 2)), (int)(e2.getY() - ((lHeight) / 2)) }; // Are we wrapping content? if(this.isWrapContent()) { // Wrap the Position. this.onWrapContent(lPosition, lWidth, lHeight); } // Update the Drag. this.onUpdateDrag(lView, lPosition); } // Assert we handled the scroll. return true; } // Otherwise, don't permit scrolling. Don't consume the MotionEvent. return false; } /** Forces X/Y values to be coerced within the confines of the RegionView. */ private final void onWrapContent(final int[] pPosition, final float pWidth, final float pHeight) { // Limit the parameters. (Top-Left) pPosition[0] = Math.max(pPosition[0], 0); pPosition[1] = Math.max(pPosition[1], 0); // Limit the parameters. (Bottom-Right) pPosition[0] = Math.min(pPosition[0], (int)(this.getWidth() - pWidth)); pPosition[1] = Math.min(pPosition[1], (int)(this.getHeight() - pHeight)); } /** Updates the Drag Position of a child View within the Layout. Implicitly, we update the LayoutParams of the View. */ private final void onUpdateDrag(final View pView, final int pLeft, final int pTop) { // Allocate some new MarginLayoutParams. final MarginLayoutParams lMarginLayoutParams = new MarginLayoutParams(pView.getLayoutParams()); // Update the Margin. lMarginLayoutParams.setMargins(pLeft, pTop, 0, 0); // Refactor the MarginLayoutParams into equivalent LayoutParams for the RelativeLayout. pView.setLayoutParams(new RelativeLayout.LayoutParams(lMarginLayoutParams)); } @Override public boolean onScale(ScaleGestureDetector detector) { // Calculate the ScaleFactor. float lScaleFactor = detector.getScaleFactor() - 1; // Fetch the Scaled View. final View lView = this.getViewMap().entrySet().iterator().next().getValue(); // Update the ScaleFactor. final float lScale = this.getScale() + lScaleFactor; // Calculate the Proposed Width and Height. final int lWidth = Math.round(lView.getWidth() * lScale); final int lHeight = Math.round(lView.getHeight() * lScale); // Is the View already too large for wrap content? if(lWidth >= this.getWidth() || lHeight >= this.getHeight()) { // Don't update the scale. return false; } // Persist this Scale for the View. lView.setScaleX(lScale); lView.setScaleY(lScale); // Assign the Scale. this.setScale(lScale); // Compute the Position. final int[] lPosition = new int[] { Math.round(detector.getFocusX()) - (lWidth / 2), Math.round(detector.getFocusY()) - (lHeight / 2) }; // Are we wrapping the Position? if(this.isWrapContent()) { // Wrap the Position. this.onWrapContent(lPosition, lWidth, lHeight); } // Update the Drag. this.onUpdateDrag(lView, lPosition); // Assert that we handled the scale. return true; } /** Update the Drag. */ private final void onUpdateDrag(final View pView, final int[] pPosition) { // Call the sub-implementation. this.onUpdateDrag(pView, pPosition[0], pPosition[1]); } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { // Is the user not dragging at all? if(this.getViewMap().size() == 1) { // Fetch the View. final View lView = this.getViewMap().entrySet().iterator().next().getValue(); // Initialize the Scale. this.setScale(lView.getScaleX()); // Assert that we've started scaling. this.setScaling(true); // Inform the callback. return true; } // Otherwise, don't allow scaling. return false; } @Override public void onScaleEnd(ScaleGestureDetector detector) { // Were we scaling? if(this.isScaling()) { // Assert that we've stopped scaling. this.setScaling(false); // Reset the Scale. this.setScale(Float.NaN); // Should we stop dragging now that we've finished scaling? if(this.isDropOnScale()) { // Clear the ViewMap. this.getViewMap().clear(); } } } /** Returns the View colliding with the given co-ordinates. */ private final View getViewFor(final int pX, final int pY) { // Declare the LocationBuffer. final int[] lLocationBuffer = new int[2]; // Iterate the Views. for(int i = 0; i < this.getChildCount(); i++) { // Fetch the child View. final View lView = this.getChildAt(i); // Fetch its absolute position. lView.getLocationOnScreen(lLocationBuffer); // Determine if the MotionEvent collides with the View. if(pX > lLocationBuffer[0] && pY > lLocationBuffer[1] && (pX < lLocationBuffer[0] + (lView.getWidth() * lView.getScaleX())) && (pY < lLocationBuffer[1] + (lView.getHeight() * lView.getScaleY()))) { // Return the View. return lView; } } // We couldn't find a View. return null; } /* Unused Overrides. */ @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } /* Getters and Setters. */ private final GestureDetector getGestureDetector() { return this.mGestureDetector; } private final ScaleGestureDetector getScaleGestureDetector() { return this.mScaleGestureDetector; } private final Map<Integer, View> getViewMap() { return this.mViewMap; } private final void setScaling(final boolean pIsScaling) { this.mScaling = pIsScaling; } private final boolean isScaling() { return this.mScaling; } private final void setScale(final float pScale) { this.mScale = pScale; } private final float getScale() { return this.mScale; } /** Defines whether we coerce the drag and zoom of child Views within the confines of the Layout. */ public final void setWrapContent(final boolean pIsWrapContent) { this.mWrapContent = pIsWrapContent; } public final boolean isWrapContent() { return this.mWrapContent; } /** Defines whether a drag operation is considered 'finished' once the user finishes scaling a view. */ public final void setDropOnScale(final boolean pIsDropOnScale) { this.mDropOnScale = pIsDropOnScale; } public final boolean isDropOnScale() { return this.mDropOnScale; } } 

यहां मैं एक उदाहरण उपयोग केस दिखाता हूं:

 package com.zonal.regionview; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.AnalogClock; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Allocate a RegionView. final RegionView lRegionView = new RegionView(this); // Add some example items to drag. lRegionView.addView(new AnalogClock(this)); lRegionView.addView(new AnalogClock(this)); lRegionView.addView(new AnalogClock(this)); // Assert that we only want to drag Views within the confines of the RegionView. lRegionView.setWrapContent(true); // Assert that after we've finished scaling a View, we want to stop being able to drag it until a new drag is started. lRegionView.setDropOnScale(true); // Look at the RegionView. this.setContentView(lRegionView); } }