xeditText.java
package com.mycompany.myapp;
import android.widget.EditText;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View.OnKeyListener;
import android.view.KeyEvent;
import android.util.Log;
import android.view.View;
import android.text.TextWatcher;
import android.text.Editable;
import android.widget.Toast;
public class xeditText extends EditText
{
private zjjk zj=new zjjk();
public xeditText(Context context)
{
super(context);
}
public xeditText(Context context, AttributeSet attrs)
{
super(context, attrs);
addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s)
{
// TODO Auto-generated method stub
//s:变化后的所有字符
setaj("变了");
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
// TODO Auto-generated method stub
//s:变化前的所有字符; start:字符开始的位置; count:变化前的总字节数;after:变化后的字节数
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
// TODO Auto-generated method stub
//S:变化后的所有字符;start:字符起始的位置;before: 变化之前的总字节数;count:变化后的字节数
}
});
}
public xeditText(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
/*
@Override
public boolean onTextContextMenuItem(int id)
{
if (id == 16908319)
{
setaj("全选");
return false;
}
if (id == 16908328)
setaj("选择");
if (id == 16908320)
{
setaj("剪贴");
return false;
}
if (id == 16908321)
{
setaj("复制");
return false;
}
if (id == 16908322)
{
setaj("粘贴");
return false;
}
if (id == 16908324)
setaj("输入法");
return super.onTextContextMenuItem(id);
}
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_DPAD_LEFT://左
setaj("左键");
break;
case KeyEvent.KEYCODE_DPAD_RIGHT://右
setaj("右键");
break;
case KeyEvent.KEYCODE_DPAD_UP://上
setaj("上键");
break;
case KeyEvent.KEYCODE_DPAD_DOWN://下
setaj("下键");
break;
}
return super.onKeyUp(keyCode, event);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
// TODO: Implement this method
return super.dispatchKeyEvent(event);
}
@Override
public void onEditorAction(int actionCode)
{
// TODO: Implement this method
super.onEditorAction(actionCode);
}
@Override
protected void onSelectionChanged(int selStart, int selEnd)
{
try
{
zj.getMyTextView().setgb(selStart, selEnd);
}
catch (Exception e)
{
}
super.onSelectionChanged(selStart, selEnd);
}
public void setaj(String a)
{
MyTextView myTextView=zj.getMyTextView();
if (myTextView != null)
{
zj.getMyTextView().setxjp(a);
}
}
}
MyTextView.java
package com.mycompany.myapp;
import android.view.View;
import android.content.Context;
import android.util.AttributeSet;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.os.Handler;
import android.widget.EditText;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import android.graphics.Color;
public class MyTextView extends View
{
private zjjk zj=new zjjk();
private Paint paint,paint1,paint2;
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public MyTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
text = "".split("\n", -1);
paint = new Paint();
paint.setColor(-16777216);//黑色
paint.setTextSize(50);
paint1 = new Paint();
paint1.setColor(-176127);//红色
paint1.setStrokeWidth(5);//设置画线宽度
paint2 = new Paint();
paint2.setColor(Color.parseColor("#88fd5100"));//选择行代码
}
public MyTextView(Context context)
{
super(context);
}
private String[] text;
private String aj="日志";
private int hhkd=50;//行号宽度
private int hhgd=55;//行号高度
private int dqh=0;//当前行
private int dqwz=0;//当前位置
private float hbydx,hbydy;//画布移动
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.translate(hbydx, hbydy);
for (int i=0;i < text.length;i++)
{
canvas.drawText(i + "", 5, 100 + hhgd * i, paint);
canvas.drawText(text[i], hhkd, 100 + hhgd * i, paint);
if (dqh == i)
{
canvas.drawLine(gbwz, 110 + hhgd * (i - 1), gbwz, 110 + hhgd * i, paint1);
}
if (jsdqh == i)
{
canvas.drawLine(jsgbwz, 110 + hhgd * (i - 1), jsgbwz, 110 + hhgd * i, paint1);
}
}
hxzh(canvas);
canvas.drawLine(hhkd - 10, hhgd, hhkd - 10, hhgd + hhgd * text.length, paint);
canvas.drawText(aj + "," + dqh + "," + dqwz + "," + jsdqh + "," + jsdqwz, 10, 50, paint);
}
private void hxzh(Canvas canvas){
//画 选择行
int gbx1,gby1,gbx2,gby2;
if (dqh == jsdqh)
{ //两个光标在一行
float ks=paint.measureText(text[dqh].substring(0, dqwz));
float js=paint.measureText(text[dqh].substring(0, jsdqwz));
canvas.drawRect(ks + hhkd, 110 + hhgd * (dqh - 1), js + hhkd, 110 + hhgd * dqh, paint2);
return;
}
if(dqh>jsdqh){
gby1=jsdqh;
gby2=dqh;
gbx1=jsdqwz;
gbx2=dqwz;
}else{
gby1=dqh;
gby2=jsdqh;
gbx1=dqwz;
gbx2=jsdqwz;
}
float ks=paint.measureText(text[gby1].substring(0, gbx1));
float js=paint.measureText(text[gby1]);
canvas.drawRect(ks + hhkd, 110 + hhgd * (gby1 - 1), js + hhkd, 110 + hhgd * gby1, paint2);
for(int i=gby1+1;i<gby2;i++){
js=paint.measureText(text[i]);
canvas.drawRect(hhkd, 110 + hhgd * (i - 1), js + hhkd, 110 + hhgd * i, paint2);
}
js=paint.measureText(text[gby2].substring(0,gbx2));
canvas.drawRect(hhkd, 110 + hhgd * (gby2 - 1), js + hhkd, 110 + hhgd * gby2, paint2);
}
private float anx,any;
private float jhbydx,jhbydy;
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN://按下
anx = event.getX();
any = event.getY();
jhbydx = hbydx;
jhbydy = hbydy;
return true;
case MotionEvent.ACTION_MOVE://拖动
float x1= event.getX() - anx;
float y1 = event.getY() - any;
if (Math.abs(x1) > 5 || Math.abs(y1) > 5)
{
hbydx = jhbydx + (x1 * 2);
hbydy = jhbydy + (y1 * 2);
if (hbydx > 0)
{
hbydx = 0;
}
if (hbydy > 0)
{
hbydy = 0;
}
}
invalidate();
return true;
case MotionEvent.ACTION_UP://弹起
float x=event.getX();
float y = event.getY();
if (x == anx && y == any)
{
dksrf();//打开输入法
jsgb(x + Math.abs(hbydx), y + Math.abs(hbydy));
}
invalidate();
return true;
}
return super.onTouchEvent(event);
}
private boolean szgbzj=false;//设置光标 输入框
//计算光标
public void jsgb(float x, float y)
{
hqsrknr();//获取输入框内容
if (y > 50)
{
dqh = (int)Math.floor((y - 50) / hhgd);
int cd=text.length - 1;
if (dqh > cd)
{
dqh = cd;
}
try
{
jsdqwz(x);//计算当前位置
}
catch (Exception e)
{}
int wz=0;
for (int i=0;i < dqh;i++)
{
wz += text[i].length() + 1;
}
szgbzj = true;
try
{
jsdqh = dqh;//当前行
jsdqwz = dqwz;//当前位置
jsgbwz = gbwz;//画光标位置
zj.getEditText().setSelection(wz + dqwz);
zj.getEditText().requestFocus();
}
catch (Exception e)
{
Log.e("aaa", "报错=" + e);
}
szgbzj = false;
}
}
//计算当前位置
private float gbwz=50;//画光标位置
public void jsdqwz(float x)
{
String txt=text[dqh];
float wz=paint.measureText(txt.substring(0, 1));
if (wz > x)
{
dqwz = 0;
gbwz = hhkd;
return;
}
for (int i=0;i < txt.length() + 1;i++)
{
wz = paint.measureText(txt.substring(0, i)) + hhkd;
if (wz > x)
{
dqwz = i;
gbwz = wz;
return;
}
}
gbwz = paint.measureText(txt) + hhkd;
dqwz = txt.length();
}
//设置光标 输入框传递过来
private int jsdqh,jsdqwz;//结束 当前行 当前位置
private float jsgbwz;//画结束 光标位置
public void setgb(int ks, int js)
{
if (szgbzj)
{
return;
}
try
{
hqsrknr();//获取输入框内容
String txt=zj.getEditText().getText().toString();
String[] txtz=txt.substring(0, ks).split("\n", -1);
dqh = txtz.length - 1;
dqwz = txtz[dqh].length();
gbwz = paint.measureText(txtz[dqh].substring(0, dqwz)) + hhkd;
if (ks != js)
{
txtz = txt.substring(0, js).split("\n", -1);
jsdqh = txtz.length - 1;
jsdqwz = txtz[jsdqh].length();
jsgbwz = paint.measureText(txtz[jsdqh].substring(0, jsdqwz)) + hhkd;
}
else
{
jsdqh = dqh;//当前行
jsdqwz = dqwz;//当前位置
jsgbwz = gbwz;//画光标位置
}
invalidate();
}
catch (Exception e)
{
Log.e("aaa", "报错=" + e);
}
}
//获取输入框内容
public void hqsrknr()
{
EditText editText=zj.getEditText();
if (editText != null)
{
text = editText.getText().toString().split("\n", -1);
}
hhkd = (int)paint.measureText(text.length + "") + 20;
}
//设置小键盘
public void setxjp(String a)
{
aj = a;
if (a.equals("变了"))
{
int wz=zj.getEditText().getSelectionStart();
setgb(wz, wz);
}
invalidate();
}
//输入法 打开 关闭
private InputMethodManager imm = (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
public void dksrf()
{
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);//开启
}
}
package com.mycompany.myapp;
import android.widget.EditText;
public class zjjk
{
private static EditText editText;
public void setEditText(EditText a){
editText=a;
}
public EditText getEditText(){
return editText;
}
private static MyTextView myTextView;
public void setMyTextView(MyTextView a){
myTextView=a;
}
public MyTextView getMyTextView(){
return myTextView;
}
}
package com.mycompany.myapp;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private zjjk zj=new zjjk();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText=findViewById(R.id.editText);
zj.setEditText(editText);
MyTextView myTextView=findViewById(R.id.text);
zj.setMyTextView(myTextView);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.mycompany.myapp.xeditText
android:id="@+id/editText"
android:lines="3"
android:textSize="1px"
android:layout_width="3000px"
android:layout_height="wrap_content"/>
<com.mycompany.myapp.MyTextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>