Orientation change does not redraw layout completely - android

This is a Major Edit on my previous question
I'm creating a custom (composite) component named OneLineSeeker that consists of a TextView and a SeekBar.
When I have multiple OneLineSeekers declared in a layout, they don't retain their state on configuration change. All seeker thumbs assume the same position (the position of the last OneLineSeeker) on configuration change.
If I don't use the custom component and use only SeekBars individually (uncomment //a() in main activity), they will retain their individual positions on configuration change.
Can anyone help?
src files
A_seekbarsActivity.java
package com.an;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
public class A_seekbarsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//a();
}
void a() {
setContentView(R.layout.main_1);
Button b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SeekBar sb = (SeekBar) findViewById(R.id.seekBar1);
if(sb.getProgress() > 50) sb.setProgress(0);
else sb.incrementProgressBy(5);
}
});
}
}
OneLineSeeker.java
package com.an;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class OneLineSeeker extends LinearLayout {
public OneLineSeeker(Context context, AttributeSet attrs) {
super(context, attrs);
View ols = LayoutInflater.from(context).inflate(R.layout.one_line_seeker, this, true);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OneLineSeeker, 0, 0);
String text = array.getString(R.styleable.OneLineSeeker_name);
if (text != null)
((TextView) ols.findViewById(R.id.name)).setText(text);
array.recycle();
}
}
res/layout files
main_1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SeekBar android:id="#+id/seekBar1" android:layout_height="wrap_content" android:layout_width="match_parent"></SeekBar>
<SeekBar android:id="#+id/seekBar2" android:layout_height="wrap_content" android:layout_width="match_parent"></SeekBar>
<SeekBar android:id="#+id/seekBar3" android:layout_height="wrap_content" android:layout_width="match_parent"></SeekBar>
<Button android:text="Button" android:id="#+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:oneLineSeeker="http://schemas.android.com/apk/res/com.an"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.an.OneLineSeeker
android:id="#+id/s1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
oneLineSeeker:name="1"
/>
<com.an.OneLineSeeker
android:id="#+id/s2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
oneLineSeeker:name="2"
/>
<com.an.OneLineSeeker
android:id="#+id/s3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
oneLineSeeker:name='3'
/>
</LinearLayout>
one_line_seeker.xml
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id='#+id/name'
android:text='name'
/>
<SeekBar
android:id='#+id/seekbar'
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</merge>
res/values files
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="OneLineSeeker">
<attr name="name" format="string"/>
</declare-styleable>
</resources>

Its not supposed to reset its position to zero. This is actually a feature. When view has id associated with, it usually saves and the restores its state on configuration changes.
If you don't want specific view to save state on configuration change, you can remove android:id from view's entry in layout (but you won't be able to control that view then). Another alternative is to extend ProgressBar and disable its ability to restore state.
The last one option is the easiest one: override onRestoreInstanceState() and reset state there:
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
bar.setProgress(0);
}
But I would strongly recommend not resetting view state. After all the whole idea of restoring state on configuration change is to make user think as if nothing really changed. And you need to have very strong reasons to disable this behavior.

In that u have to define Orientation Change Methods.....
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
onCreate(null);
}
Try this Code may u get any Help.....

Related

Is it possible to dynamically add AndroidAnnotation #EViewGroups instead of using the traditional inflate directly?

I'm trying to use Android Annotations and dynamically add layout components when my createNewRow button is clicked. The app runs and displays the default rows defined in activity_main.xml and, after clicking createNewButton I see children attached to my dynamicTable in the debugger but the new children are not displayed. Here is my main activity XML:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/inflateLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="net.richardriley.inflate.app.MainActivity">
<Button
android:id="#+id/createNewRow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/newRowButton"/>
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/dynamicTable">
<TableRow>
<TextView
android:text="#string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</TableRow>
</TableLayout>
</LinearLayout>
So simply a linear layout with a button and then a table container. Clicking createNewRow should add a new InflatedRow. Here is the XML for the row I want to dynamically add:
inflatedrow.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:id="#+id/inflatedRowTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/inflatedRowLabel"/>
<Button
android:id="#+id/inflatedRowButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/defaultNewRowText"
/>
</merge>
Using AA my subclass for a tableRow is
InflatedRow.java
package net.richardriley.inflate.app;
import android.content.Context;
import android.widget.Button;
import android.widget.TableRow;
import android.widget.TextView;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;
/**
* inflate : Created by rgr on 20/03/14.
*/
#EViewGroup(R.layout.inflatedrow)
public class InflatedRow extends TableRow {
#ViewById
Button inflatedRowButton;
#ViewById
TextView inflatedRowTextView;
public InflatedRow(Context context) {
super(context);
}
}
and finally my main activity java itself:
MainActivity.java
package net.richardriley.inflate.app;
import android.support.v7.app.ActionBarActivity;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import org.androidannotations.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static ch.qos.logback.classic.android.BasicLogcatConfigurator.configureDefaultContext;
#OptionsMenu(R.menu.main)
#EActivity(R.layout.activity_main)
public class MainActivity extends ActionBarActivity {
static {
configureDefaultContext();
log = LoggerFactory.getLogger(MainActivity.class);
}
#ViewById
LinearLayout inflateLayout;
#ViewById
TableLayout dynamicTable;
public MainActivity() {
}
protected static Logger log;
#Click
void createNewRow() {
log.info("clicked");
InflatedRow_ inflatedRow=new InflatedRow_(this);
dynamicTable.addView(inflatedRow,0);
/*LayoutInflater layoutInflater= (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.inflatedrow,null);
dynamicTable.addView(view);*/
}
#OptionsItem
void openSettingsSelected(){
log.info("Hello");
}
}
In createNewRow if I use the inflater service directly it works.
What am I missing?
many thanks.
Don't use the annotated class when you're inflating the view and make sure you're calling the build method that inflates it.
#Click
void createNewRow() {
log.info("clicked");
InflatedRow inflatedRow = new InflatedRow_.build(this);
dynamicTable.addView(inflatedRow,0);
}
instead of 'View inflatedRow= new InflatedRow_(this);' I use 'View inflatedRow=InflatedRow_.build(this);'. This is documented for custom controls and I needed to do it for a merged control group too. So mea culpa to a degree!
#Click
void createNewRow() {
log.info("clicked");
InflatedRow_ inflatedRow=InflatedRow_.build(this);
dynamicTable.addView(inflatedRow,0);
}
Alternatively (and no idea if this would continue to be supported:
#Click
void createNewRow() {
log.info("clicked");
/*View inflatedRow = InflatedRow_.build(this);*/
InflatedRow_ inflatedRow = new InflatedRow_(this);
inflatedRow.onFinishInflate();
dynamicTable.addView(inflatedRow, 0);
}

Android project display error on R.id.button

I surdenly noticed that My project starts throwing error anytime I try to access a resources that is a button. It underlines R.id.button. I dont understand why. I even deleted the last xml that I created but problem persist.
This is an example of my xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/layoutborder"
android:orientation="vertical" >
<TextView
android:id="#+id/chat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="#string/stepone"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/wine" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="#drawable/ai" />
<Button
android:id="#+id/drugdetails"
style="#style/smallButtonStyleBlackpearl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:text="#string/nextbut" />
</LinearLayout>
My Java code
package com.example.rhemahealthcare;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.actionbarsherlock.app.SherlockActivity;
import com.example.rhemahealthcare.R;
public class SteponeActivity extends SherlockActivity{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.steponeactivity);
final Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
// TODO Auto-generated method stub
Intent intent = new Intent(SteponeActivity.this,SteptwoActivity.class);
startActivity(intent);
}
});
}
}
i think you change any button1 id buy clicking right click and choose edit id. this option changes all the ids with that name in all the layouts.
As #Aleks G gussed it right in the comment, you don't have any button with id as button1 in your xml file. You've mentioned it :
final Button button = (Button)findViewById(R.id.button1);
Use the appropriate ID or put one in your layout file.
I have figured out the problem. My button ids were automatically change to button1 so they did not reference their previous ids that I gave to them. Thanks alot

Custom Text For Dialog implements OnClick Listener Android

Friends I just Wanna set Custom Typeface Form my assets/fonts folder
My Java Code Looks like this
package customtext;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
public class Custom extends Dialog implements android.view.View.OnClickListener{
public Custom(Context context) {
super(context);
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom);
btn=(Button) findViewById(R.id.dismis_dialog);
btn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
dismiss();
}
}
When I try to add like this Its not worked for me
its giving error
here this is my XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
style="#style/Theme.CustomDialog" >
<FrameLayout
android:layout_width="250sp"
android:layout_height="70sp"
android:background="#ee8f03" >
<TextView
android:layout_width="180sp"
android:layout_height="wrap_content"
android:id="#+id/sharedialog"
android:text="#string/msg"
android:textColor="#272b2d"
android:background="#ef8e01"
android:layout_gravity="center" >
</TextView>
</FrameLayout>
<FrameLayout
android:layout_width="250sp"
android:layout_height="70sp"
android:background="#fff" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:clickable="true"
android:id="#+id/dismis_dialog"
android:text="#string/dismis"/>
</FrameLayout>
</LinearLayout>
Would you please tell how to add custom font to this type of context Dialog Box
Thank you
check out this links for creating Custom Dialog
http://www.mkyong.com/android/android-custom-dialog-example/
also you can set the custom font like this way
Typeface type = Typeface.createFromAsset(getAssets()/fonts, "myfonts.ttc");
youTextView.setTypeface(type);
put your fonts into fonts folder under assets dir
Try this
Typeface type = Typeface.createFromAsset(getAssets(), "name.ttc");
dismis_dialog.setTypeface(type);
sharedialog.setTypeface(type);

How to use Compound Controls

I've created a custom ViewGroup based on a LinearLayout.
ClearableEditText.java
package test.todolist;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
public class ClearableEditText extends LinearLayout{
private EditText editText;
private Button button;
public ClearableEditText (Context context){
super (context);
String service = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li = (LayoutInflater)getContext ().getSystemService (service);
li.inflate (R.layout.clearable_edit_text, this, true);
editText = (EditText)findViewById (R.id.clearEditText);
button = (Button)findViewById (R.id.clearButton);
configButton ();
}
private void configButton (){
button.setOnClickListener (new Button.OnClickListener (){
public void onClick (View v){
editText.setText ("");
}
});
}
}
clearable_edit_text.xml
<?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="wrap_content">
<EditText
android:id="#+id/clearEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="#+id/clearButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/clear"
/>
</LinearLayout>
How can I use ClearableEditText now?
I've tried to put a node inside a layout (main.xml) in 2 ways:
<test.todolist.ClearableEditText/>
and
<test.todolist.clearable_edit_text/>
but none of them have worked.
My main.xml:
<?xml version="1.0" encoding="utf-8"?>
<test.todolist.ClearableEditText/>
My ToDoList.java (main activity):
package test.todolist;
import android.app.Activity;
import android.os.Bundle;
public class ToDoList extends Activity{
#Override
public void onCreate (Bundle savedInstanceState){
super.onCreate (savedInstanceState);
setContentView (R.layout.main);
}
}
Thanks.
Solved. The main.xml should be like:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<test.todolist.ClearableEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</merge>
First, merge tag because it is needed when using custom views. My custom view have a LinearLayout root, so it's inefficient if I set another LinearLayout or FrameLayout root in main.xml to use my custom view. merge solves that.
And second, all views must have the layout_width and layout_height attributes.

Error "android (name of project) has stopped unexpectedly

package com.iperetz1.android.testbutton1;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class TestButton extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button test2 = (Button)findViewById(R.id.test2);
test2.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
setContentView(R.layout.test2);;
}
});
Button other = (Button)findViewById(R.id.backmain);
other.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
setContentView(R.layout.main);;
}
});
}
}
main.xls
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
android:id="#+id/widget0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<Button
android:id="#+id/test2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test2"
android:layout_x="24px"
android:layout_y="165px"
>
</Button>
</AbsoluteLayout>
test2.xml
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
android:id="#+id/widget0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<Button
android:id="#+id/backmain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="backmain"
android:layout_x="24px"
android:layout_y="165px"
>
</Button>
</AbsoluteLayout>
findViewById is a lot simpler than people tend to think it is. It traverses the view hierarchy looking for a view with the given ID. If it's not found, findViewById returns null.
You started by setting the content view to your main layout but later on you tried to findViewById(R.id.backmain). Since there is no view with that ID in your main layout, it returns null. At that point attempting other.setOnClickListener will fail. You will only be able to do this when your button actually exists in the view hierarchy.
There's nothing inherently wrong with dynamically changing your view hierarchy, but you'll have to handle some things differently if you go that route. (Such as when you wire up events to views that don't exist during onCreate like you're trying to do above.)
As #Cristian Castiblanco said, changing the view dynamically is causing the problem, for these kind of scenarios, you have to create separate activities and invoke them using intents and pass data between them using bundles.

Categories

Resources