I'm writing a simple text editor in my app. Accordingly, I need to scroll through a large editable text.
My layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scroll"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:id="#+id/note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/black"
android:padding="5dp"
android:textSize="14sp"/>
</ScrollView>
In my Activity I set large text :
public class FileEditorActivity extends Activity {
private EditText text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_editor);
text = (EditText)findViewById(R.id.note);
text.setText(newText); ////// LARGE TEXT
}
}
Now, text scrolls but when the scroll speed is reduced scrolling starts to twitch (jerky)!!!!!!
I thought why so ......... And try the following :
scrollView = (ScrollView)findViewById(R.id.scroll);
scrollView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
scrollView.setFocusable(true);
scrollView.setFocusableInTouchMode(true);
scrollView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.requestFocusFromTouch();
if (text.hasFocus()) {
text.clearFocus();
}
return false;
}
});
And after that (when edittext always lost focus before scrolling) scroll large text working perfect when the scroll speed is reduced.
But I need to always stay in focus and maintain the state of the cursor when scrolling text ((((
How to do it ?????????
P.S. I want to like this :
ES Explorer app
When open text file on edit
Thanks in advance !!!!
Related
I have an activity with some edittexts and some checkboxes, etc.
I have validators set on text entries that get executed when a text entry loses focus. But the problem is when the user clicks/touches a checkbox, edittext doesn't lose focus and therefore the validator is not run.
What is the best way for causing unfocus of text entries when the user touches another input field? I know I can e.g. set a handler on every checkbox to force unfocusing of text fields happen, but I think there is probably a more concise/general method for this purpose; Setting a handler on every checkbox seems too cumbersome and error prone.
thank u.
You can try this way(it only is an example).
your_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sv_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="EditText 1" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="EditText 2" />
..............other views................
</LinearLayout>
</ScrollView>
Using android:focusableInTouchMode="true" in the LinearLayout to make the EditText is focused when touching on it( or when starting this activity there is not auto focus to any EditText also).
In your activity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
ScrollView svContent = findViewById(R.id.sv_content);
svContent.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
int action = motionEvent.getAction();
if(action == MotionEvent.ACTION_MOVE || action == MotionEvent.ACTION_UP) {
View focusView = getCurrentFocus();
if (focusView != null) {
// The code for unfocus here
return true;
}
}
return false;
}
});
}
What i want in pictures:
On the words: i want to disable scrolling with formatting text inside HorizontalScrollView.
Part of XML:
<ScrollView
android:id="#+id/review_scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="horizontal"
android:fillViewport="true"
android:layout_marginTop="10dp">
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tt_review_content"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Some long text"
android:scrollHorizontally="true"/>
</HorizontalScrollView>
</ScrollView>
Method(doesn't works):
private void setTtAreaWrapContent(boolean value) {
ViewGroup.LayoutParams params = textField.getLayoutParams();
if(value) { // Wrap content
textField.setWidth(scrollView.getWidth());
} else { // Scroll
params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
}
textField.setLayoutParams(params);
}
There is a very simple way to do this.
Check if the user wants to scroll or not and then store it in a boolean variable, shouldScroll.
Now do this in onCreate,
HorziontalScrollView scrollView= (HorizontalScrollView)findViewById(R.id.scrollView);
if(!shouldScroll)
scrollView.setOnTouchListener(new OnTouch());
You also need to define a class OnTouch extending the OnTouchListener
private class OnTouch implements OnTouchListener
{
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
}
Now for the TextView formatting, just use android:singleLine="false" or use android:width="0dip"
I had absolutely the same need for code, so I initially proposed a ViewSwitcher with the same layouts, but one with HorizontalScrollView and one without it. And switch to the corresponding view depending on the setting.
However, I found an easier solution. After recreation of the Activity (when wrapping settings are changed by the user), use the code in the onCreate methode:
if (isWrapContent)
{
View mTV = findViewById(R.id.my_text_view);
HorizontalScrollView myHSV = (HorizontalScrollView) findViewById(R.id.my_hsv);
ViewGroup parent = (ViewGroup) myHSV.getParent();
ViewGroup.LayoutParams params = myHSV.getLayoutParams();
int index = parent.indexOfChild(myHSV);
myHSV.removeAllViews();
parent.removeView(myHSV);
parent.addView(mTV, index, params);
}
You need to use your id's and variables correspondingly.
It will remove the horizontal scrollview with the embedded textview and then reinsert the textview.
My answer provides direct and valid answer on how the asked issue could be resolved instead of freezing the horizontal scrollview or wondering about the point of the question, as it is done in the other comments and answers.
I need to create a Widget which look like photo below:
Upper part of photo resembles normal state of my costume widget and lower part of it resembles highlight state of the widget.
Widget primary features:
Both Normal and Highlighted sates could have a background with image and color at same time.
It could re-size by width easily (for example 200dp or 100dp)
I have 3 questions:
Is there any particular widget which could help me to create something like what I said?
Or should I create a custom widget myself?
Create a custom layout with a Vertical LinearLayout and two child TextView for Title and description.
Set the description TextView visibility as GONE , since you need to show the description only on highlight state.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_highlight"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#drawable/image_shape">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title"
android:textStyle="bold"
android:textSize="30dp"
android:layout_margin="10dp"/>
<TextView
android:id="#+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello! Iam here to display the description"
android:textStyle="italic"
android:textSize="25dp"
android:layout_margin="5dp"
android:visibility="gone"/>
</LinearLayout>
Now, on the code change the description TextView visibility as visible on long click.
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.layout_highlight);
final TextView descriptionTextView = (TextView)findViewById(R.id.description);
linearLayout.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
descriptionTextView.setVisibility(View.VISIBLE);
return true;
}
});
Also , you need to hide back the description when long click is released. so you have to have onTouch listener like this..
linearLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
descriptionTextView.setVisibility(View.GONE);
}
return false;
}
});
To be more specific I've done small example of this behaviour.
Layout:
<ScrollView
android:id="#+id/scroll_view_for_et"
android:scrollbars="horizontal"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<EditText
android:id="#+id/edit_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top"
android:text="Long text there" />
</ScrollView>
Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText editText = (EditText) findViewById(R.id.edit_text);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Adding random span to text
editText.getEditableText().setSpan(new ForegroundColorSpan(Color.RED), 100, 500, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}, 7000);
}
So if I set a cursor in some place, and then scrolling text in other position, after 7 seconds passed it will be scrolled back to coursor position. How to avoid this behaviour?
BitBucket link for full code of this example.
I found some solution. Issue was in that EditText recieved a focus after execution of setSpan method. So I've added android:descendantFocusability="beforeDescendants" to parent element in my view hierarchy ( in my case it was LinearLayout), and OnTouchListener to ScrollView:
mScrollViewAroundEt.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (mCustomEditText.hasFocus()) {
mCustomEditText.clearFocus();
}
return false;
}
});
So now EditText do not recieve focus when user scroll.
I'm working on an Android app and I've got 2 editviews and a label. The user can enter 2 values and the label shows some calculation using input from the editviews. What I want is the following;
user enters either value with soft-keyboard
user presses "Return" softkey
editview should lose focus
the soft-keyboard should disappear
textview label should be recalculated
Now, the v.clearFocus only seems to works when there is another widget that can can get focus(?), so I've also added a dummie zero-pixel layout that can 'steal' the focus from the first editview. The Return key works now, but when the user switches focus from edit1 to edit2 by simply tapping then HideKeyboard() crashes. I've tried checking if inputMethodManager==null but that didn't help.
This all feels like I'm hacking to trick Android into doing some common UI behaviour, so I can't help but think that I'm overlooking something here.
Any help would be greatly appreciated. Btw I know this is similar to this question: How to lose the focus of a edittext when "done" button in the soft keyboard is pressed?
But I've tried that and it doesn't work.
So my layout xml is this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- Dummy control item so that first textview can lose focus -->
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>
<EditText
android:id="#+id/editTest1"
android:layout_width="250px"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:imeOptions="actionDone" >
</EditText>
<EditText
android:id="#+id/editTest2"
android:layout_width="250px"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:imeOptions="actionDone" >
</EditText>
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test123" />
</LinearLayout>
And the source is this:
public class CalcActivity extends Activity implements OnFocusChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab2_weight);
EditText testedit = (EditText) findViewById(R.id.editTest1);
testedit.setOnFocusChangeListener(this);
testedit.setOnEditorActionListener(new OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId==EditorInfo.IME_ACTION_DONE){
//Clear focus here from edittext
Log.d("test app", "v.clearFocus only works when there are other controls that can get focus(?)");
v.clearFocus();
}
return false;
}
});
}
public void hideSoftKeyboard() {
InputMethodManager inputMethodManager = (InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
}
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus == false) {
Log.d("unitconverter", "onFocusChange hasFocus == false");
// update textview label
TextView bla = (TextView) findViewById(R.id.textView1);
bla.setText(String.format("%s + %s", (((EditText) findViewById(R.id.editTest1)).getText()), (((EditText) findViewById(R.id.editTest2)).getText())));
// hide keyboard
hideSoftKeyboard();
}
}
}