I am creating a UI for my company which has a edit-text at top and a frame layout at bottom. this frame-layout contains a mic image and animation on pressing of which it goes through 3 main state like listening.thinking and idle state.
So in short, user can provide query either by typing in edit text or by providing command by voice.
My problem occurs when user click on edit-text to provide text command. When user do so the android keyboard comes up and user insert text but after entering text if user press back button the ,the whole UI comes up before going down. This all happens very quickly and to a user it gives bad impression. It feels like UI is getting stuck but this is how by default android is handling it.
Is there a way by which I can stop this flickering or make this move smoothly.?
Currently I am making this frame layout invisible when user start editing and visible when user has finished editing but this also does not help.
I know by not providing complete code it is not a good way of asking a doubt.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
style="#style/main_style_mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<RelativeLayout
android:id="#+id/dialog"
style="#style/main_style_dialog"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="360dp"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ScrollView
>
<!--will dynamically add here widgets and edit text button as required>
<LinearLayout
android:id="#+id/linearLayout"
style="#style/main_style_scrollViewlinearLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</LinearLayout>
</ScrollView>
</LinearLayout>
</RelativeLayout>
<FrameLayout
android:id="#+id/mainControlLL"
style="#style/main_style_mainControlLL"
android:layout_width="fill_parent"
android:layout_height="wrap_content" > // Act as parent container for mic image and text view
<FrameLayout> //contains text view which gets displayed on top of mic image
<TextView/>
</FrameLayout>
<FrameLayout
android:id="#+id/mic_btn_layout"
style="#style/main_style_mic_btn_layout"
android:layout_width="wrap_content"
android:layout_height="118dp" >// contains mic images
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false" >// contains mic image for listening state
<ImageView/>
<ImageButton />
<ImageButton/>
<ImageView />
</FrameLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical|center" >//contain mic images for thinking state
<ImageButton />
<ImageButton />
<ImageView />
</RelativeLayout>
<ImageButton />//contains mic image for idle state
</FrameLayout>
</FrameLayout>
</RelativeLayout>
And in my manifest I have
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" and
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|locale"
Please let me know how i can correct my UI behavior.
You should put your activity state on a stack, since you are using fragments(more on this here) and override the onBackPressed() function and restore your fragment state there.
#Override
public void onBackPressed()
{
// restore fragment/activity state here
super.onBackPressed();
}
Below is API which I have modified to stop flickering.
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
this.clearFocus();
//Fix- Ui Flicker
// this.setFocusable(false);
// this.setFocusableInTouchMode(false);
return false;
}
return super.dispatchKeyEvent(event);
}
In above API I commented the piece of code shown above.
But Can some one explain why it was causing the jumping(going up) of UI. It was only disabling the focus of view.
Related
i am trying to achieve a behavior where user click an arrow that can reveal more content such as more description abort something. It can a recycler view as well where more things can be added dynamically and the list will expand.Right now i do not have any idea how it can be achieved. I tried searching on the internet for solutions and saw a widget called spinner but i do not think it can help me achieve my desired behavior. YouTube does apply similar behavior as well
Below are the pictures which will make my question clear. Any help would be appreciated Thank You
Before clicking the arrow pic 1
After clicking the arrow pic 2
In your layout.xml include a nested layout that includes a Textview that holds the additional information and set android:visibility="gone". Use an OnClickListener to the button that is meant to expand the view. In the onClick method check if the view is visible or not. If it's not you make it visible, otherwise you set it to gone again.
layout:
...
<ImageView
android:id="#+id/chevron"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/chevron"
/>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="your additional info here"
android:visibility="gone"/>
...
In your Activity:
ImageView yourView = findViewById(R.id.chevron);
..
yourView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (view.getVisibility() == View.Gone) {
view.setVisibility(View.Visible);
} else {
view.setVisibility(View.Gone);
}
}
});
I used for this purpose ExpandbleLayout from this github library
ExpandableLayout. In readMe of the github repo you can find example of using it, you can get similar experience with as in your example, without need to manually create View for arrow and handling the animation.
You can use it like this :
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.github.aakira.expandablelayout.ExpandableRelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:ael_expanded="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text goes here"
android:textSize="28sp" />
</com.github.aakira.expandablelayout.ExpandableRelativeLayout>
And in your java/kotlin code : do additional logic to expand/collapse call : expandableLayout.toggle();.
All the credit goes to the author of the library.
https://github.com/AAkira/ExpandableLayout
I have a PlayerView that takes up the top half of the Activity in portrait orientation with the bottom half of the screen showing some text.
I need to have the controller under the video without overlapping the video content (it will always be shown). By default when a user touches the video the controller appears at the bottom of the video covering the bottom part of the video. I my case I need the controller to stick under the video with no intersections with the video content.
I went through SimpleExoPlayer and PlayerView APIs but I haven't found any way to do so.
Question: How can I place the controller under the video with ExoPlayer?
Here is how the layout looks like:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#id/video_view"
android:scrollbars="vertical" />
</RelativeLayout>
This will push the controls down to the bottom of the screen:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:use_controller="false" />
<com.google.android.exoplayer2.ui.PlayerControlView
android:id="#+id/controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/video_view"
app:show_timeout="0" />
</RelativeLayout>
Then in Java:
PlayerView videoView = findViewById(R.id.video_view);
PlayerControlView controls = findViewById(R.id.controls);
controls.setPlayer(videoView.getPlayer());
Edit: Modified my answer to suggestion from #RashimiGautam
Refer to the answer by #Pierre.
Also to remove controller from above PlayerView, in that case, #id/video_view by writing player.showController(false) in java file.
You can also use app:use_controller:false in the xml.
So you will the only the video without controller on top. And link it to a new controller, in that case, #id/controls at the bottom of the video.
This might give you an idea, also have you tried to override the controls?
As an example, suppose we want our playback controls to consist of only a play/pause button positioned in the center of the view. We can achieve this by creating exo_playback_control_view.xml file in the application’s res/layout directory, containing:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton android:id="#id/exo_play"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#CC000000"
style="#style/ExoMediaButton.Play"/>
<ImageButton android:id="#id/exo_pause"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#CC000000"
style="#style/ExoMediaButton.Pause"/>
</FrameLayout>
Note that in the layout #id/exo_play and #id/exo_pause are standard ids defined by the ExoPlayer library. Use of standard ids is required so that child views can be identified, bound to the player and updated in an appropriate way. A full list of the standard ids for each view can be found in the Javadoc for PlaybackControlView and SimpleExoPlayerView. Use of each standard id is optional.
https://medium.com/google-exoplayer/customizing-exoplayers-ui-components-728cf55ee07a
In my Android app I have an Activity where a user can add some text to an image. When the button to initiate this is pressed a TextInput appears at the bottom of the screen with the "Save" button overlayed.
The relevant config looks like this:
<activity
android:name=".ImageEditorActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/title_activity_image_editor"
android:parentActivityName=".MainActivity"
android:windowSoftInputMode="adjustResize|stateHidden"
android:theme="#style/FullscreenTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="myApp.MainActivity" />
</activity>
The activity xml looks like this - I have trimmed out a couple of extra buttons that don't related to this feature:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".ImageEditorActivity"
android:id="#+id/fullscreen_content">
<ScrollView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_marginTop="50dp"
android:isScrollContainer="true" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/edit_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"></ImageView>
<EditText
android:id="#+id/image_comment"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="8dp"
android:paddingLeft="8dp"
android:shadowDx="0"
android:shadowDy="0"
android:shadowRadius="2"
android:hint="notes"
android:text=""
android:textColor="#android:color/black"
android:background="#android:color/white"
android:layout_alignParentBottom="true"
android:visibility="invisible"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toBottomOf="parent" />
<Button
android:id="#+id/image_comment_save_button"
android:layout_width="100dp"
android:layout_height="45dp"
android:layout_marginBottom="2dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Save"
android:visibility="invisible"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toBottomOf="parent"
/>
</RelativeLayout>
</ScrollView>
<Button
android:id="#+id/note_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/add_note"
app:layout_constraintBottom_toTopOf="parent"></Button>
The activity is started with the path to an image, which it then loads into the image. When the note button is pressed it shows the textbox.
noteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
writeNotes();
}
});
private void writeNotes() {
InputMethodManager methodMan = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
if (noteBox.getVisibility() == View.VISIBLE) {
String text = noteBox.getText().toString();
if ( 0 < text.trim().length() ) {
Bitmap image = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
writeOnImage(image, text);
imageView.setImageBitmap(image);
saveImage(image, lastTaken);
exifData.put(ExifInterface.TAG_USER_COMMENT, text);
}
noteBox.setVisibility(View.INVISIBLE);
noteSaveButton.setVisibility(View.INVISIBLE);
methodMan.hideSoftInputFromWindow(noteBox.getWindowToken(), 0);
}
else {
noteBox.setText("");
noteBox.setVisibility(View.VISIBLE);
noteSaveButton.setVisibility(View.VISIBLE);
noteBox.requestFocus();
methodMan.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
}
The problem is that when the keyboard opens, there is a big black rectangle over it, that completely obscures the EditText and the Save button. This only happens on my phone, which is on 7.1.1, the emulator variants I have tried seem to work normally. Interestingly although they are obscured, they still work - if I type something on the keyboard and then press where the Save button should be, it saves the text as expected.
This screenshot shows the problem in action:
By changing the settings around the config file, I have found situations where the black rectangle is not shown, but in every case I have found that also hides the EditText component and even after the keyboard is closed I never see it again, leaving the activity in a weird state where there is no way to press the Save button.
If the keyboard is open the whole time the black rectangle only appears once the EditText has focus, prior to that the keyboard looks normal.
The closest thing I can find in previous questions suggests that android:inputType="textNoSuggestions" might help but it doesn't seem to make any difference - this doesn't seem to be a suggestion box, just an arbitrary black rectangle.
What do I need to do to stop my keyboard drawing a pointless black rectangle right over my input box or, if I am approaching this the wrong way somehow, what do I need to do to have an input box that allows the user to see the text that they are writing and then save it when they are content that it is complete?
The problem turned out to be related to the Android software buttons at the bottom of the screen, rather than the keyboard itself- for some reason they were causing the layout to measure the screen incorrectly whenever the keyboard was opened.
The solution was to add android:fitsSystemWindows="true" to the FrameLayout at the root of the view.
So when I click on an activity I want to show a loading gif, instead of a: 'ProgessDialog', but how can I bring this in the center of the screen and to the front without replacing other objects?
<FrameLayout
android:id="#+id/scrim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/dark_translucent"
android:visibility="gone">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="24dp"/>
</FrameLayout>
</FrameLayout>
Add to your build.gradle(Module.app)
dependencies {
compile 'com.github.bumptech.glide:glide:3.6.1'
}
In your Activity
Glide.with(this)
.load(imageGif)
.asGif()
.fitCenter()
.crossFade()
.into(imageView);
There's an excellent library for this called andorid-gif-drawable
You'd want to do this, after adding the library to your project:
<pl.droidsonroids.gif.GifImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/src_drawable_here"
/>
Make sure it's inside a layout that allows center in parent (which means center horizontally and vertically), such as a RelativeLayout.
This is how I do it:
<FrameLayout> <!-- this can also be a CoordinatorLayout -->
... (content)
<FrameLayout
android:id="#+id/scrim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/dark_translucent"
android:visibility="gone">
<ProgressBar
android:id="#+id/progressBar"
style="#style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="24dp"
android:indeterminate="true"/>
</FrameLayout>
</FrameLayout>
This is used in conjunction with a loader. When the loader is started, I set the scrim visibility to visible. When the loader completes, I set the scrim visibility back to gone.
A couple things:
You should track whether the scrim is visible or not in the saved instance state, so if the user rotates the device while the loader is in progress, you can show the scrim again immediately in onCreate.
If you are covering touchable controls, you should make all your controls disabled until completion. Alternatively, you could set an onTouchListener on the scrim layout to consume the touch events so the content controls are effectively disabled.
I am building a view in my Android application using a sliding drawer widget. I have implemented my own custom handles (just a row of menu buttons which then changes the content of the drawer and then activates the openAmination). I have managed to disable the standard handle provided with the slidingdrawer but I want to completely remove it.
None of the standard visibility stuff in xml or java works in hiding/removing the handle:
<SlidingDrawer android:layout_width="fill_parent"
android:id="#+id/slidingDrawer1"
android:layout_height="fill_parent"
android:handle="#+id/handle"
android:content="#+id/content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:allowSingleTap="false"
>
<Button android:layout_width="wrap_content"
android:text="Close"
android:layout_height="wrap_content"
android:id="#+id/handle"
android:visibility="gone" //DOES NOT WORK
</Button>
<LinearLayout android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF">
</LinearLayout>
</SlidingDrawer>
I also tried importing the view in java and doing the same but also does not work.
View h = findViewById(R.id.handle);
h.setVisibility(View.GONE);
I have then tried extending the slidingDrawer class and making my own but it still requires a handle!. Is there anyway I have a sliding drawer without a default handle?
-----SOLUTION----
draw = (SlidingDrawer)findViewById(R.id.slidingDrawer1);
//Close the draw if opened when the user touches elsewhere on the screen
draw.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
if(draw.isOpened())
((SlidingDrawer)v).animateOpen();
return false;
}});
//Open the draw by external button
((Button) findViewById(R.id.quiz_button)).setOnClickListener(
new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
draw.animateOpen();
} });
An the XML for the sliding draw view was:
<SlidingDrawer android:layout_width="fill_parent" android:allowSingleTap="false" android:id="#+id/slidingDrawer1" android:content="#+id/content" android:handle="#+id/handle" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true">
<Button android:layout_height="wrap_content" android:layout_width="0px" android:visibility="invisible" android:text="Close" android:id="#+id/handle"></Button>
<LinearLayout android:id="#+id/content" android:gravity="center" android:background="#4FFFFF44" android:layout_width="fill_parent" android:layout_height="76dp"></LinearLayout>
</SlidingDrawer>
Many Thanks
Sam
I tried for many hours and failed to get rid of the handle, the best I could do wass move it far away from the view window. If you have already extended the slidingdrawer class it should be easy.
In the onLayout method find the line
handle.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
and change it to
handle.layout(10000, 10000, 10000, 10000);
Basically its just setting its position to way of screen.
I found a better way to fix the problem.
Do not hide a handle itself, but it's content. I had an ImageView as a handle, but I changed it to a LinearLayout holding an ImageView.
<LinearLayout
android:id="#id/handle"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/handleImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/sliding_drawer_handle" />
</LinearLayout>
Now handleImage.setVisibility(View.INVISIBLE) works fine in onAnimationEnd.
Hope that helped :)
I have the same problem, I don't want to show the handle because I have a personal button that shows the SlidingDrawer at the click. So, I solve it setting the handle height to 0dp.
This is my handle code:
<ImageButton
android:id="#+id/cash_menuGruop_handle"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_contetn"
android:layout_height="0dp"/>
<Button
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/handle"
android:visibility="gone" //DOES NOT WORK
</Button>
use height and width 0dp
,for open and close use handle.performclick();
it is working for me