autoscrolling textview in android - java

I'm building a chat-like application that displays text the user inputs to the screen using a scrollview. What I'd like to do is making the scrollview autoscroll as more text is appended to the screen.
I'm using a textview to display the input. The xml portion of the scrollview is as follows:
<ScrollView
android:id="#+id/scroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#id/buttons"
>
<LinearLayout
android:id="#+id/start_chat"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
</LinearLayout>
</ScrollView>
How do I go about doing that? I tried setting the layout's gravity to "bottom", but that doesn't work correctly (text inputed that moves up as the scrollview is scrolled down can't be viewed again).
Any help is greatly appreciated.

If you want to scroll to the absolute bottom (where new TextView is added) use fullScroll on the ScrollView when the TextView is added.
ScrollView my_scrollview = (ScrollView) findViewById(R.id.scroller);
my_scrollview.fullScroll(ScrollView.FOCUS_DOWN);
If instead you want to scroll relative from the current position the user is viewing, I would try something like smoothScrollBy or scrollBy
/* recently_added_textview being the TextView that was added to trigger this */
ScrollView my_scrollview = (ScrollView) findViewById(R.id.scroller);
int height = recently_added_textview.getHeight();
my_scrollview.smoothScrollBy(0, height);
/* x being 0 assuming you don't want to scroll left and right */
This way the user isn't sent to the bottom of the ScrollView if they're reading something around the top or middle.

You can add this after you added a new chat in your textview
scroller.post(new Runnable() {
public void run() {
//ScrollView.FOCUS_DOWN if you want to scroll down
//ScrollView.FOCUS_UP if you want to scroll up
svComments.fullScroll(ScrollView.FOCUS_DOWN);
}
});

Related

How to make Image Buttons act like Radio buttons

I'm trying to make Image buttons act like Radio buttons. Let me explain. I have a basic layout containing an Image Button and a TextView, that I load with different images and texts.
XML layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/button_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#FFFFFF"/>
<TextView
android:id="#+id/text_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</LinearLayout>
Java method :
LinearLayout categoryLayout = view.findViewById(R.id.categories_layout);
for (int i = 0; i<categories.size(); i++) {
final String name = categories.get(i).name;
final int resource = categories.get(i).resource;
View v = getLayoutInflater().inflate(R.layout.choose_category, null);
final TextView text = v.findViewById(R.id.text_category);
text.setText(name);
ImageButton button = v.findViewById(R.id.button_category);
button.setImageResource(resource);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectedCategory = resource;
text.setTypeface(text.getTypeface(), Typeface.BOLD);
}
});
categoryLayout.addView(v);
}
Every time an image is clicked, the text is set bold to indicate which button was clicked. My problem is that I only want one button to be clickable at a time. I thought of, each time a button is clicked, reseting the appearance of all TextView, only leaving the last text that was clicked as bold. However, I don't know how to navigate through all layouts that have been generated.
I hope I was clear, thank you if you can help me !
That might not be the most efficient way to solve this problem, but it works. Every time the button is clicked, the icon selected is saved. Then, I use removeAllViews() method on the RadioGroup, and recreate the views. I just make sure the text below the previously selected icon is set bold.

setting height to wrap_content in Java makes the view deny all predefined XML attributes?

I have created a TextView in XML and have set some rules for it (for example layout_bellow="something"), and made it's height set to 0, so that when a button is clicked, it's height would be set to wrap_content. I wrote the code bellow for the button responsible for resizing, and below it is the XML code i wrote for the TextView. The problem is, when i click the button, the height becomes match_parent, the layout_bellow attribute gets ignored and it is drawn from the start of the parent layout, and width (that was set to match_parent) becomes wrap_content. Whats the problem? thanks.
the Button:
btnExpand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, height));
}
});
the XML:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/firstRow"
android:layout_width="match_parent"
android:layout_height="wrap_content">
.
.
.
</LinearLayout>
<TextView
android:id="#+id/theTextView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#id/firstRow"
android:text="lorem ipsom lorem ipsom">
</RelativeLayout>
EDIT: here's an image to demonstrate the problem
Basically the problem is you are creating new LayoutParams and setting it to the view. You have get the already set(xml) LayoutParams of the view and modify whichever you want to modify and set it back to the View.
LayoutParams layoutParams = textView.getLayoutParams();
//height = LayoutParams.WRAP_CONTENT;or 100 or whatever
layoutParams.height = LayoutParams.WRAP_CONTENT;
textView.setLayoutParams(layoutParams);

Can't hide Bottom Sheet, Android

I'm having problems with my bottom-sheet because when I open the activity it is on, blocking the view
This happens, I think, because of the XML attribute declaring the bottom-sheet with 350dp of height:
<android.support.v4.widget.NestedScrollView
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="350dp"
android:background="?android:attr/windowBackground"
android:clipToPadding="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
The thing is, I can't change that value to 0dp because the next time when I try to open the bottom-sheet, there is no bottom-sheet, because the height is 0dp, so it won't show anything.
My question is, is there a way to declare the bottom-sheet off? (I've tried to setState to STATE_COLLAPSED but didn't work).
Bellow is the java code that interacts with the Bottom Sheet.
JAVA:
View bottomSheet = findViewById( R.id.bottom_sheet );
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
//mBottomSheetBehavior.setPeekHeight(0);
//mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
//mBottomSheetBehavior.isHideable();
}
}
#Override
public void onSlide(View bottomSheet, float slideOffset) {
}
});
first you have to add the attribute
app:behavior_hideable="true"
in your
<android.support.v4.widget.NestedScrollView
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="350dp"
android:background="?android:attr/windowBackground"
android:clipToPadding="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
And then you can hide the bottom sheet using
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
and not
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED)
the state COLLAPSED is between HIDDEN and EXPANDED and his heigth must be specified by the attribute:
app:behavior_peekHeight="200dp"
Write this:
mBottomSheetBehavior.setPeekHeight(0);
In my case i was not able to hide the bottomsheet and it was placed on top of my view. I found out that animateLayoutChanges = "true" in my layout file was causing this issue.
In my case I was using BottomSheetDialog.
app:behavior_hideable - attribute is used to determine if our bottom sheet will hide when it is swiped down. In other words bottom sheet top be off screen, if the peek height isn’t set.
app:behavior_peekHeight - attribute value used to represent how much pixels the bottom sheet will be visible.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_sheet_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="10dp"
android:orientation="vertical"
android:background="#color/colorPrimaryDerived"
app:layout_behavior="#string/bottom_sheet_behavior"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"> ........... </LinearLayout>
I set the peekHeight to 50dp. And peek height has nothing to do with the bottomSheet layout height itself which I set 200dp (for example only).
You can view the changes in your XML viewer if the bottom sheet is expanded, if so add the app:behavior_peekHeight = 0dpfrom the xml layout and it will hide and also inform you of the current state.
Inside onCreate add these lines, it can hide the bottombar
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
mBottomSheetBehavior.setHideable(true); //Important to add
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); //Important to add
When Collapsed set app:behavior_hideable="false"
You need to just simply add the below code and it works perfectly.
To hide the bottomsheet:-
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
To show the bottomsheet:-
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
You can manually hide that bottom sheet by setting the visibility of the parent linear layout to gone
put this line in your code when you want
if (confirmLayoutBehaviour.getState() != BottomSheetBehavior.STATE_EXPANDED) {
//todo hide your bottom sheet if its already open
confirmLayout.setVisibility(View.GONE);
} else {
//set it to visible if its not open
confirmLayout.setVisibility(View.VISIBLE);
}
it worked for me please try it

LayoutParams using AddRules

I know there are related questions but please try my code 1st
I think my code is correct but I don't know why I can't get want I want
I'm trying to Replace the image into a RelativeLayout with the same LayoutParams dimension and placement(programmatically) then inside that RelativeLayout put a WebView in the center of it.
It was almost done but I'm having trouble for the placement of Webview.
see the images below
activity_main.java
#Override
protected void onCreate(Bundle savedInstanceState) {
.........
// Image
ImageView image = (ImageView)findViewById(R.id.image);
// Container of the image
RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_imageView);
loader(rl , image);
}
public void loader(RelativeLayout rl,View view){
// Creating RelativeLayout
RelativeLayout rlnew = new RelativeLayout(this);
// Getting the Layout Parameters of the image such as (position and dimension)
RelativeLayout.LayoutParams lp1 = (RelativeLayout.LayoutParams) view.getLayoutParams();
// Coloring the background of the new Relative Layout into blue
rlnew.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
// passing the parameters to the new relative layout from the image
rlnew.setLayoutParams(lp1);
// image turns into invisible
view.setVisibility(View.INVISIBLE);
// Creating a webView
WebView webView = new WebView(this);
// load the loading.gif
webView.loadDataWithBaseURL("file:///android_asset/", "<center><img src='loading.gif' style=''/></center>", "text/html", "utf-8", null);
// setting up dimension(height and weight) for the webview
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100, 60);
// adding position(Center) for the webview
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
// setting up Layout parameters for the webiview
webView.setLayoutParams(lp);
// adding the webview to the new Relative Layout
rlnew.addView(webView);
// adding the new relative layout into the container
rl.addView(rlnew);
}
activity_main xml
<RelativeLayout
android:layout_width="250dp"
android:layout_height="100dp"
android:background="#ec0c0c"
android:id="#+id/rl_imageView"
android:layout_marginTop="47dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<!--Desired Output-->
<!--<RelativeLayout-->
<!--android:layout_width="70dp"-->
<!--android:layout_height="70dp"-->
<!--android:background="#010e6e"-->
<!--android:layout_alignParentTop="true"-->
<!--android:layout_alignParentEnd="true">-->
<!--<WebView-->
<!--android:layout_width="60dp"-->
<!--android:layout_height="30dp"-->
<!--android:id="#+id/imageView"-->
<!--android:layout_centerVertical="true"-->
<!--android:layout_centerHorizontal="true" />-->
<!--</RelativeLayout>-->
<!--Default Image-->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/sample1"
android:id="#+id/image"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true">
</ImageView>
</RelativeLayout>
Output Images
I'm making a method that will ask for two parameters a RelativeLayout(that contains the second parameter of the method) and View so it can be anything like(Image, TextView, RelativeLayout , etc.,).
This code can replace a specific View like a relativeLayout or textView or Image
and replace it with a relativeLayout with the same size and position of the given View(mine was the image)(It was already Done if you move that image anywhere in the given container the code will replace the image into a relativeLayout no matter where it is as long inside of the given container).
The only problem is the WebView position. . why is webView there?. .I want it in the center of the new RelativeLayout
Can someone tell where did I go wrong
If you have another way just submit answer
Your code is correct, but your xml is not. Try to change your xml below and test again:
<ImageView
android:layout_width="your dimen in dp < rl_imageView. width"
android:layout_height="your dimen in dp < rl_imageView. height"
android:src="#drawable/sample1"
android:id="#+id/image"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true">
</ImageView>
P/S: I suggest create this Imageview programmatically also.

TextView with scrollbar that can handle onTouchEvents

I have problem with handling Touch events inside my TextView on Android 2.3.3. I've got Activity implements OnTouchListener with method
main.java
public boolean onTouchEvent(MotionEvent event) {
if(event.getPointerCount()==1){
textView.setTextSize(mRatio+13);
mRatio++;
Log.d("TouchEvent", "one touch !");
}
if (event.getPointerCount() == 2) {
some code...
}
return true;
}
and my layout(only part of it):
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1.0"
android:fadingEdge="none"
android:background="#color/white">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="10dp">
<!-- TEXT EMAIL : -->
<TextView
android:id="#+id/mail_text"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textSize="15sp"
android:autoLink="web"
android:clickable="true"
android:textColor="#color/mailtext"
android:scrollbars = "vertical"/>
</LinearLayout>
</LinearLayout>
When i 'clicked' anywhere outside my textBox(for example on header or footer), the Touch event trigger, font get bigger. I assume than the problem is probably because scrollbars. But when I cut off android:scrollbars = "vertical" bar just disappear.
This textView usually contain a lots of text.
How to proper fire onTouchEvents inside this textView.
Edit:
when this textView is small my touchEvent work until i get text so big, than the scrollBar is needed. Then all touch event get overrided and You can only scroll textView. No TouchEvent is called.
I handle the problem in other way. OnTouchEvent didn't worked with my TextView so I Override dispatchTouchEvent. It's far more better to performe actions "onTouch".Scrollbar is working and I can add my multitouch events on the whole screen. It's look like:
#Override
public boolean dispatchTouchEvent(MotionEvent motionEvent){
Log.v("NotificationActivity.dispatchTouchEvent()", "got touch");
if (motionEvent.getPointerCount() == 2) {
Log.v("touch", "multi touch !");
int action = motionEvent.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
// some actions ...
}
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:{
//Keep track of the starting down-event.
Log.v("akcjaa","down");
// some actions ...
break;
}
case MotionEvent.ACTION_UP:{
//Consume if necessary and perform the fling / swipe action
//if it has been determined to be a fling / swipe
Log.v("akcjaa","up");
break;
}
}
return super.dispatchTouchEvent(motionEvent);
}
I am assuming your TextView is inside some kind of ScrollView or Scrollable container, right?
Then you will face this issue. Android does not like his apples and pears mixed, you should not be trying to receive "onTouch" events that are being consumed by the father layout on top of the view.
I guess you could:
a) Switch to a onClickListener on your TextView
b) Override your parent view layout touch handler to bleed the touch down to its childs. This is not really 100% recommended, and could cause unwanted behaviour.
Sorry if i cannot be of more help.

Categories