Custom rotated EditText view with working selection, cursor location, etc

后端 未结 5 1337
感情败类
感情败类 2020-12-09 17:06

What I want to do

I want to make a rotated and flipped EditText view that has all of the properties of a normal EditText view.

My problem

I have

相关标签:
5条回答
  • 2020-12-09 17:25

    Things are much more simplier. Everything you need is already buit-in View class: http://developer.android.com/reference/android/view/View.html#setRotation(float) A bit more complicated solution if previous one would not works for you by some reason is: http://developer.android.com/reference/android/view/animation/RotateAnimation.html It also using for rotation of views (but animated in most cases however you could use it with zero transition duration).

    Please let me know in the case you have some additional questions (guess no - there is self-explaing method and class).

    Rotating just a canvas - you rotating only image on the screen. setRotation also handles all events, layout flow etc so it should works just fine in your case!

    Hope it would helps!

    0 讨论(0)
  • 2020-12-09 17:26

    Tried to get the partial solution with minor changes, check if that's you want.

    1) Set android:gravity="top|left" in your edittext declaration inside xml.

    2) Noticed that without super method call inside onDraw method, not able to show cursor. So I called,

    super.onDraw(canvas);
    

    instead,

    getLayout().draw(canvas);
    

    3) For touch events, I tried to swap x and y coordinates. So that you can have cursor as per touch event.(Just tried and it was working, got lucky :) )

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        event.setLocation(event.getY(), event.getX());
        return super.onTouchEvent(event);
    }
    

    Comment this line inside onDraw method, for exact touch event(Found by trial and error).

    canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
    

    4) I could not do any thing about highlighting or selecting text.

    ?) Another Solution : If you think that, some how you get RTL language support work on edittext then you just need to rotate it. But unfortunately its not working properly with android. Reference : How to handle RTL languages on pre 4.2 versions of Android? and Android setting with TextView for Hebrew text?

    0 讨论(0)
  • 2020-12-09 17:29

    An attribute is there for the EditText for rotation . It is is simple and also easy to use.It might help you I think.

    <EditText
        android:id="@+id/editTextNumber"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:rotation="90"
        android:layout_marginBottom="10dp"
        android:hint="Enter Mobile Number"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    0 讨论(0)
  • 2020-12-09 17:29

    Try this:

    <EditText
            android:id="@+id/ed1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textView1"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="47dp"
            android:digits="1234567890"
            android:ems="10"
            android:singleLine="true"
            android:cursorVisible="true"
            android:hint="Refreshing time in ms" />
    
    0 讨论(0)
  • 2020-12-09 17:40

    Update

    I ended up developing a vertical script MongolEditText from scratch. It is available as a part of mongol-library.

    Here it is being used with two different third party keyboards.

    Old answer

    This is still a work in progress so I won't mark this as solved yet, but let me post what I have so far. It does most of what I wanted to do. Basically, I'm using TextView rather than EditText because EditText was doing to many strange things when rotated.

    I have an unblinking cursor that responds to touch events but highlighting is still not supported. Here is the code:

    public class MongolTextView extends TextView {
    
        private TextPaint textPaint;
        private Paint cursorPaint = new Paint();
        private boolean mCursorIsVisible;
        private CursorTouchLocationListener listener;
    
        // Naming is based on pre-rotated/mirrored values
        private float mCursorBaseY;
        private float mCursorBottomY;
        private float mCursorAscentY; // This is a negative number
        private float mCursorX;
        
        private static final float CURSOR_THICKNESS = 2f; 
    
        // Constructors
        public MongolTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        public MongolTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public MongolTextView(Context context) {
            super(context);
            init();
        }
    
        // This class requires the mirrored Mongolian font to be in the assets/fonts folder
        private void init() {
            //Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
            //      "fonts/ChimeeWhiteMirrored.ttf");
            //setTypeface(tf);
            
            // Use the above commented code is using a single font in another application 
            Typeface tf = FontCache.get(SettingsActivity.FONT_DEFAULT, getContext());
            if(tf != null) {
                setTypeface(tf);
            }
    
            this.mCursorIsVisible = true;
    
            cursorPaint.setStrokeWidth(CURSOR_THICKNESS);
            cursorPaint.setColor(Color.BLACK); // TODO should be same as text color
            
        }
    
        // This interface may be deleted if touch functionality is not needed
        public interface CursorTouchLocationListener {
    
            /**
             * Returns the touch location to be used for the cursor so you can update the insert
             * location in a text string.
             * 
             * @param glyphIndex
             *            You will need to translate glyphIndex into a Unicode index if you are using a
             *            Unicode string.
             */
            public void onCursorTouchLocationChanged(int glyphIndex);
    
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // swap the height and width
            super.onMeasure(heightMeasureSpec, widthMeasureSpec);
            setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            textPaint = getPaint();
            textPaint.setColor(getCurrentTextColor());
            textPaint.drawableState = getDrawableState();
    
            canvas.save();
    
            // flip and rotate the canvas
            canvas.translate(getWidth(), 0);
            canvas.rotate(90);
            canvas.translate(0, getWidth());
            canvas.scale(1, -1);
            canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
    
            // draw the cursor
            if (mCursorIsVisible) {
                canvas.drawLine(mCursorX, mCursorBottomY, mCursorX, mCursorBaseY + mCursorAscentY,
                        cursorPaint);
            }
    
            getLayout().draw(canvas);
    
            canvas.restore();
        }
    
        public void showCursor(boolean visible) {
            mCursorIsVisible = visible;
            this.invalidate();
            // TODO make the cursor blink
        }
        
        public void setCursorColor(int color) {
            cursorPaint.setColor(color);
        }
    
        public void setCursorLocation(int characterOffset) {
            
            Layout layout = this.getLayout();
            
            if (layout!=null){
                
                try {
                    // This method is giving a lot of crashes so just surrounding with 
                    // try catch for now
                    
                    int line = layout.getLineForOffset(characterOffset);
                    mCursorX = layout.getPrimaryHorizontal(characterOffset);
                    mCursorBaseY = layout.getLineBaseline(line);
                    mCursorBottomY = layout.getLineBottom(line);
                    mCursorAscentY = layout.getLineAscent(line);
                    
                    this.invalidate();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        }
    
        public class InputWindowTouchListener implements OnTouchListener {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
    
                Layout layout = ((TextView) view).getLayout();
    
                // swapping x and y for touch events
                int y = (int) event.getX();
                int x = (int) event.getY();
    
                if (layout != null) {
    
                    int line = layout.getLineForVertical(y);
                    int offset = layout.getOffsetForHorizontal(line, x);
    
                    mCursorX = layout.getPrimaryHorizontal(offset);
                    mCursorBaseY = layout.getLineBaseline(line);
                    mCursorBottomY = layout.getLineBottom(line);
                    mCursorAscentY = layout.getLineAscent(line);
                    //mCursorHeightY = layout.getLineTop(line);
    
                    view.invalidate();
                    
                    switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        //handler.postDelayed(mLongPressed, 1000);
                        listener.onCursorTouchLocationChanged(offset);
                        break;
                    case MotionEvent.ACTION_UP:
                        //handler.removeCallbacks(mLongPressed);
                        // notify the host activity of the new cursor location
                        
                        break;
                    }
    
                }
    
                return false;
            }
            
        }
        
        public void setCursorTouchLocationListener(CursorTouchLocationListener listener) {
            this.listener = listener;
        }
    }
    

    Feel free to add your own answer if you have something better or make a comment if you have something to add for improving this (adding highlighting, getting the cursor to blink, etc.). The most recent version of this code should be on github.

    0 讨论(0)
提交回复
热议问题