I have a lot of layouts like below. Also the same with NestedScrollView instead of the CardView.
But in all cases this leads to nested constraint layouts. Particuallary in one screen I use the following a lot as a custom view type. But this leads to HUGE inflation times. I meassured 500 ms and more. This is of course unaccaptable.
What can I do to improve the layout performance. The custom view is an EditText that looks like
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardView"
android:layout_width="0dp"
android:layout_height="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Some layout code -->
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintStart_toStartOf="#+id/cardView"
app:layout_constraintTop_toBottomOf="#+id/cardView" />
</androidx.constraintlayout.widget.ConstraintLayout>
EDIT: As per request. Here comes the complete xml, java, and how I use it in another xml
CustomEditText.xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingStart="8dp"
android:paddingTop="9dp"
android:paddingEnd="8dp">
<com.google.android.material.card.MaterialCardView
android:id="#+id/cardView"
android:layout_width="0dp"
android:layout_height="48dp"
app:cardCornerRadius="12dp"
app:cardElevation="3dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginBottom="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/iv_startIcon"
android:layout_width="19dp"
android:layout_height="0dp"
android:layout_marginStart="19dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:adjustViewBounds="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorPrimary"
tools:srcCompat="#drawable/icon_phone"
tools:visibility="visible" />
<TextView
android:id="#+id/tv_prefix_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="19dp"
android:textColor="?attr/colorPrimary"
android:visibility="gone"
android:textSize="13sp"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="ABC" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier_start"
android:layout_width="1dp"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="tv_prefix_text,iv_startIcon" />
<androidx.appcompat.widget.AppCompatEditText
android:id="#+id/et_text"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="13dp"
android:layout_marginEnd="19dp"
android:background="#null"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/barrier_end"
app:layout_constraintStart_toEndOf="#+id/barrier_start"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/tv_hint"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="13dp"
android:gravity="center_vertical"
android:textSize="13sp"
android:maxLines="1"
android:layout_marginEnd="57dp"
android:ellipsize="end"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/barrier_start"
app:layout_constraintTop_toTopOf="parent"
tools:hint="Hint text" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrier_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="left"
app:constraint_referenced_ids="iv_endIcon,tv_optional" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_optional"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginEnd="19dp"
android:alpha="0.44"
android:gravity="center_vertical"
android:text="#string/edit_text_optional"
android:textSize="10sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/iv_endIcon"
android:layout_width="39dp"
android:layout_height="0dp"
android:layout_marginEnd="9dp"
android:adjustViewBounds="true"
android:paddingStart="10dp"
android:paddingTop="18dp"
android:paddingEnd="10dp"
android:paddingBottom="18dp"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toEndOf="#+id/barrier_end"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="#drawable/icon_alert"
tools:tint="?colorError"
tools:visibility="visible" />
<androidx.core.widget.ContentLoadingProgressBar
android:id="#+id/pb_loading"
style="?android:attr/progressBarStyle"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:layout_marginEnd="14dp"
android:alpha="0.44"
android:textSize="9sp"
android:textStyle="bold"
android:fontFamily="#font/nunito2"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="#+id/cardView"
app:layout_constraintTop_toBottomOf="#+id/cardView"
tools:text="0/30"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_helper"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="7dp"
android:layout_marginEnd="16dp"
android:alpha="0.44"
android:textSize="9sp"
android:visibility="visible"
app:layout_constraintEnd_toStartOf="#+id/tv_count"
app:layout_constraintStart_toStartOf="#+id/cardView"
app:layout_constraintTop_toBottomOf="#+id/cardView"
app:layout_goneMarginEnd="19dp"
tools:text="Helper text"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
and the CustomEditText.java (Sorry, this is a lot of code. But as I do not know what is important I could not reduce):
public class CustomEditText extends LinearLayoutCompat {
private static final String TAG = "CustomEditText";
private static final String ANDROID_NS = "http://schemas.android.com/apk/res/android";
private static final String APP_NS = "http://schemas.android.com/apk/res-auto";
private static final String COUNTER_SEPARATOR = "/";
private static final int TRANSLATION_Y_DP = 21;
private final int translationY;
private static final float HELPER_ALPHA = 0.44f;
private final String counterErrorText;
private final List<TextWatcher> textWatcherList = new ArrayList<>();
private final Drawable alertIcon;
private final Drawable clearIcon;
private final CustomEditTextBinding b;
private String errorText;
private String helperText;
private String hintText;
private Drawable startIcon;
private int iconTint;
private int counterMaxLength;
private boolean isCounterEnabled;
private boolean isOptional;
private boolean isProgressBarVisible = false;
private boolean isClearEnabled;
private boolean hasFocus;
private boolean isError = false;
private boolean isCounterError = false;
private String prefixText;
private final boolean initialized;
private final boolean hasBorder;
public CustomEditText(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
b = CustomEditTextBinding.inflate(LayoutInflater.from(context), this, true);
b.tvHint.setPivotX(0);
b.pbLoading.hide();
translationY = GuiUtils.dpToPx(context, TRANSLATION_Y_DP);
alertIcon = AppCompatResources.getDrawable(context, R.drawable.icon_alert);
clearIcon = AppCompatResources.getDrawable(context, R.drawable.icon_clear);
counterErrorText = context.getString(R.string.counter_max_length_error);
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText);
//Start icon
startIcon = attributes.getDrawable(R.styleable.CustomEditText_startIcon);
iconTint = attributes.getColor(R.styleable.CustomEditText_iconTint, ColorUtils.getAttrColor(context, R.attr.colorPrimary));
refreshStartIcon();
//Hint text
hintText = attributes.getString(R.styleable.CustomEditText_hint);
refreshHintText();
//Helper text
helperText = attributes.getString(R.styleable.CustomEditText_helperText);
refreshHelperText();
//Error text
errorText = attributes.getString(R.styleable.CustomEditText_errorText);
//Prefix text
prefixText = attributes.getString(R.styleable.CustomEditText_prefixText);
refreshPrefixText();
isClearEnabled = attributes.getBoolean(R.styleable.CustomEditText_clearEnabled, false);
refreshClearEnabled();
//Optional text
isOptional = attributes.getBoolean(R.styleable.CustomEditText_optional, false);
refreshOptional();
b.ivEndIcon.setVisibility(GONE);
refreshEndIcon();
//Counter
isCounterEnabled = attributes.getBoolean(R.styleable.CustomEditText_counterEnabled, false);
counterMaxLength = attributes.getInt(R.styleable.CustomEditText_counterMaxLength, 0);
refreshCounter();
//Elevation
int elevation = attributes.getDimensionPixelSize(R.styleable.CustomEditText_elevation, -1);
if (elevation != -1) b.cardView.setCardElevation(elevation);
//Border
hasBorder = attributes.getBoolean(R.styleable.CustomEditText_hasBorder, false);
refreshStroke();
if (attrs != null) {
//Pass through to edit text
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importantForAutofill = attrs.getAttributeIntValue(ANDROID_NS, "importantForAutofill", 0);
b.etText.setImportantForAutofill(importantForAutofill);
String autofillHints = attrs.getAttributeValue(ANDROID_NS, "autofillHints");
b.etText.setAutofillHints(autofillHints);
}
//Focusable
boolean isFocusable = attrs.getAttributeBooleanValue(ANDROID_NS, "focusable", true);
b.etText.setFocusable(isFocusable);
//CursorVisible
boolean isCursorVisible = attrs.getAttributeBooleanValue(ANDROID_NS, "cursorVisible", true);
b.etText.setCursorVisible(isCursorVisible);
//InputType
int inputType = attrs.getAttributeIntValue(ANDROID_NS, "inputType", InputType.TYPE_CLASS_TEXT);
b.etText.setInputType(inputType);
//ImeOption
int imeOptions = attrs.getAttributeIntValue(ANDROID_NS, "imeOptions", EditorInfo.IME_ACTION_UNSPECIFIED);
b.etText.setImeOptions(imeOptions);
//MaxLines
int maxLines = attrs.getAttributeIntValue(ANDROID_NS, "maxLines", 1);
b.etText.setMaxLines(maxLines);
}
attributes.recycle();
initListeners();
initialized = true;
}
private void refreshClearEnabled() {
refreshEndIcon();
}
private void refreshOptional() {
if (isProgressBarVisible || !isOptional || isError || isCounterError || !isEmpty() && isClearEnabled)
b.tvOptional.setVisibility(GONE);
else b.tvOptional.setVisibility(VISIBLE);
}
private void refreshStartIcon() {
if (startIcon != null) {
b.ivStartIcon.setImageDrawable(startIcon);
b.ivStartIcon.setVisibility(VISIBLE);
b.tvPrefixText.setVisibility(GONE);
b.ivStartIcon.setImageTintList(ColorStateList.valueOf(iconTint));
} else {
b.ivStartIcon.setVisibility(GONE);
}
}
private void refreshPrefixText() {
if (prefixText != null) {
b.ivStartIcon.setVisibility(GONE);
b.tvPrefixText.setVisibility(VISIBLE);
b.tvPrefixText.setText(prefixText);
} else {
b.tvPrefixText.setVisibility(GONE);
}
}
private void refreshEndIcon() {
if (!isProgressBarVisible && (isError || isCounterError)) {
b.ivEndIcon.setVisibility(VISIBLE);
b.ivEndIcon.setImageDrawable(alertIcon);
b.ivEndIcon.setImageTintList(ColorUtils.getAttrColorList(getContext(), R.attr.colorError));
b.ivEndIcon.setAlpha(1f);
} else if (!isProgressBarVisible && isClearEnabled && !isEmpty()) {
b.ivEndIcon.setImageDrawable(clearIcon);
b.ivEndIcon.setImageTintList(ColorUtils.getAttrColorList(getContext(), R.attr.colorOnBackground));
b.ivEndIcon.setVisibility(VISIBLE);
b.ivEndIcon.setAlpha(0.42f);
} else {
b.ivEndIcon.setVisibility(GONE);
}
}
private void refreshHelperText() {
if (isError || isCounterError) {
if (isCounterError) b.tvHelper.setText(counterErrorText);
else b.tvHelper.setText(errorText);
b.tvHelper.setVisibility(VISIBLE);
b.tvHelper.setAlpha(1f);
b.tvHelper.setTextColor(ColorUtils.getAttrColor(getContext(), R.attr.colorError));
} else if (helperText == null) {
b.tvHelper.setVisibility(INVISIBLE);
} else {
b.tvHelper.setAlpha(HELPER_ALPHA);
b.tvHelper.setVisibility(VISIBLE);
b.tvHelper.setText(helperText);
b.tvHelper.setTextColor(ColorUtils.getAttrColor(getContext(), R.attr.colorOnBackground));
}
}
private void refreshCounter() {
if (isCounterEnabled) {
b.tvCount.setVisibility(VISIBLE);
refreshCounterText();
} else {
b.tvCount.setVisibility(GONE);
}
}
private void refreshStroke() {
if (isError || isCounterError) {
setStroke(StrokeType.ERROR);
} else if (hasFocus) {
setStroke(StrokeType.FOCUS);
} else if (hasBorder) {
setStroke(StrokeType.DEFAULT);
} else {
setStroke(StrokeType.NONE);
}
}
private void refreshProgressBar() {
refreshOptional();
refreshClearEnabled();
if (isProgressBarVisible) b.pbLoading.show();
else b.pbLoading.hide();
}
#SuppressLint("SetTextI18n")
private void refreshCounterText() {
if (!isCounterEnabled) return;
int countChars = getText().length();
String counterText = countChars + COUNTER_SEPARATOR + counterMaxLength;
isCounterError = countChars > counterMaxLength;
if(initialized && isCounterError) setError();
b.tvCount.setText(counterText);
}
private void refreshHintText() {
b.tvHint.setHint(hintText);
}
private void initListeners() {
b.etText.addTextChangedListener((TextWatcherAdapter) (s, start, before, count) -> {
//Do not trigger on init, only on user interaction
if (!initialized) return;
if (s.length() == 1) triggerAnimation(true);
else if (s.length() == 0) triggerAnimation(false);
});
b.etText.setOnFocusChangeListener((v, hasFocus) -> {
this.hasFocus = hasFocus;
refreshError();
refreshStroke();
});
b.etText.addTextChangedListener((TextWatcherAdapter) (s, start, before, count) -> {
clearError();
refreshCounterText();
refreshEndIcon();
refreshOptional();
//Trigger all other TextWatchers, add them here instead of the text itself to trigger all internal ones first
for (TextWatcher textWatcher : textWatcherList) textWatcher.onTextChanged(s,start,before,count);
});
b.etText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
//Trigger all other TextWatchers, add them here instead of the text itself to trigger all internal ones first
for (TextWatcher textWatcher : textWatcherList) textWatcher.afterTextChanged(s);
}
});
b.etText.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
b.etText.clearFocus();
}
return false;
});
b.ivEndIcon.setOnClickListener(v -> {
if (isClearEnabled) b.etText.setText(null);
});
}
private void triggerAnimation(boolean fadeOut) {
if (fadeOut) {
b.tvHint.animate().translationY(-translationY * 0.32f).scaleX(0.7f).scaleY(0.7f);
//This works but not with setText because getHeight return 0. The reason for that: i do not know
//b.tvHint.animate().translationY(-b.tvHint.getHeight() * 0.32f).scaleX(0.7f).scaleY(0.7f);
} else {
b.tvHint.animate().translationY(0).translationX(0).scaleX(1f).scaleY(1f);
}
}
public void setText(String text) {
b.etText.setText(text);
if (text != null && !text.isEmpty()) triggerAnimation(true);
}
private void refreshError() {
refreshOptional();
refreshEndIcon();
refreshHelperText();
refreshStroke();
}
#Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
b.etText.setEnabled(enabled);
if (enabled) {
PictureUtils.saturatePicture(b.ivStartIcon, 1);
PictureUtils.saturatePicture(b.ivEndIcon, 1);
b.tvPrefixText.setTextColor(ColorUtils.getPrimary(getContext()));
if (isError) setStroke(StrokeType.ERROR);
else if (hasFocus) setStroke(StrokeType.FOCUS);
else setStroke(StrokeType.DEFAULT);
b.cardView.setCardBackgroundColor(ColorUtils.getAttrColor(getContext(), R.attr.cardColorOnPrimary));
} else {
PictureUtils.saturatePicture(b.ivStartIcon, 0);
PictureUtils.saturatePicture(b.ivEndIcon, 0);
b.tvPrefixText.setTextColor(ColorUtils.getAttrColor(getContext(), R.attr.colorItemDisabled));
setStroke(StrokeType.DISABLED);
b.cardView.setCardBackgroundColor(ColorUtils.getAttrColor(getContext(), R.attr.colorDisabled));
}
}
public void setError() {
isError = true;
refreshError();
}
public void setError(String errorText) {
if (errorText == null) {
clearError();
} else {
isError = true;
this.errorText = errorText;
refreshError();
}
}
public void clearError() {
isError = false;
//Its up to the user to decide that this will not be an error! So reset no matter if more is entered
isCounterError = false;
refreshError();
}
public boolean isValid() {
if (isOptional) return !isError;
else return !getText().isEmpty() && !isError;
}
private void setStroke(StrokeType strokeType) {
switch (strokeType) {
case ERROR:
b.cardView.setStrokeColor(ColorUtils.getAttrColor(getContext(), R.attr.colorError));
b.cardView.setStrokeWidth(4);
break;
case FOCUS:
b.cardView.setStrokeColor(ColorUtils.getAttrColor(getContext(), R.attr.colorPrimary));
b.cardView.setStrokeWidth(4);
break;
case DEFAULT:
int color = ColorUtils.getAttrColor(getContext(), R.attr.colorOnBackground);
ColorDrawable cd = new ColorDrawable(color);
cd.setAlpha(54);
b.cardView.setStrokeColor(cd.getColor());
b.cardView.setStrokeWidth(2);
break;
case DISABLED:
b.cardView.setStrokeColor(ColorUtils.getAttrColor(getContext(), R.attr.colorItemDisabled));
b.cardView.setStrokeWidth(2);
break;
case NONE:
b.cardView.setStrokeColor(null);
b.cardView.setStrokeWidth(0);
break;
}
}
public String getText() {
return b.etText.getEditableText().toString().trim();
}
public void addTextChangedListener(TextWatcher textWatcher) {
//b.etText.addTextChangedListener(textWatcher);
textWatcherList.add(textWatcher);
}
public boolean isEmpty() {
return StringUtils.checkNull(getText());
}
#Override
public void setOnClickListener(#Nullable OnClickListener listener) {
b.etText.setOnClickListener(listener);
}
public void setErrorText(String errorText) {
this.errorText = errorText;
}
public void setHelperText(String helperText) {
this.helperText = helperText;
refreshHelperText();
}
public void setHintText(String hintText) {
this.hintText = hintText;
refreshHintText();
}
public void setStartIcon(Drawable startIcon) {
this.startIcon = startIcon;
refreshStartIcon();
}
public void setPrefixText(String prefix) {
this.prefixText = prefix;
refreshPrefixText();
}
public void setLoading(boolean active) {
this.isProgressBarVisible = active;
refreshProgressBar();
}
public void setCounterMaxLength(int counterMaxLength) {
this.counterMaxLength = counterMaxLength;
refreshCounter();
}
public void setCounterEnabled(boolean counterEnabled) {
isCounterEnabled = counterEnabled;
refreshCounter();
}
public void setOptional(boolean optional) {
isOptional = optional;
refreshOptional();
}
public void setClearEnabled(boolean clearEnabled) {
isClearEnabled = clearEnabled;
refreshClearEnabled();
}
public boolean isCounterError() {
return isCounterError;
}
#Override
public void setFocusable(boolean focusable) {
b.etText.setFocusable(focusable);
}
public void setCursorVisible(boolean cursorVisible) {
b.etText.setCursorVisible(cursorVisible);
}
public boolean isError() {
return isError || isCounterError;
}
private enum StrokeType {ERROR, FOCUS, DEFAULT, DISABLED, NONE}
// TODO: 13.10.2021 Text drawable needs to get bigger
public void scalePictureForText() {
LayoutParams params = new LayoutParams(30, 0);
params.setMargins(19, 5, 0, 5);
b.ivStartIcon.setLayoutParams(params);
}
}
And this is how I use it in another layout (I removed the constraints):
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
android:overScrollMode="never">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<com.company.app.views.CustomEditText
android:id="#+id/et_number_primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="numberDecimal"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<!--Button that should not scroll-->
</androidx.constraintlayout.widget.ConstraintLayout>
I would suggest using ViewStubs for all of the optional parts of the layout, that is items with gone visibility by default. Then these parts won't be inflated until they become visible or are needed, which should save you some initial inflation time.
And maybe you could eliminate the MaterialCardView and then combine the constraint layouts once there's no MaterialCardView between them, less layouts means less inflation time. It looks like you're using MaterialCardView for curved corners and shadows, but you could try to make your own background with curved corners and shadows and then apply it directly to the constraint layout to get the same effect with less layouts.
Is there any reason why your custom view extends LinearLayoutCompat? Could make it a constraint layout and use merge as a root tag to eliminate one layout.
Also, you have a huge amount of code in your constructor which might be the biggest culprit, could you try putting timers in your constructor and logging how much time it takes for b = CustomEditTextBinding.inflate(LayoutInflater.from(context), this, true); vs how much time it takes for everything else in there to complete. That will tell you if the problem is really layout related or if you're doing too many things in the constructor.
I can suggest you some methods to analyze your layout :
You can use Lint tool . Select Analyze (from the top bar) -> Inspect code -> select your layout file or the whole project if you want. this will automatically detect problems in your layout and will suggests fixes for it.
You can also use Profile GPU rendering in the developers option in your device. This tool allows you to see how long the layout-and-measurestage is taking for each frame of rendering. This data can help you diagnose runtime performance issues, and help you determine what, if any layout-and-measure issues you need to address.
Or enable Debug GPU Overdraw option from the developer options to show which area of your ui is overdrawn.
For your help : Inspect GPU rendering speed and overdraw
ConstraintLayout was added to flatten the view hierarchies and is not a light View to inflate. They are not design to be nested, so I would suggest you not to use them if you can avoid using them. In most cases FrameLayout or LinearLayout is sufficient.
Related
Actually I created a pdf viewer and i jus want to create a longclicklistener to open my new activity and as u can see here
Screenshot
And there is already a click listener assigned with this button and i also want to combine longclicklistener so when i long click that button then automatically launch my second activity
public void actionButtonClick(View view) {
if (pageCount == 0) {
Toast.makeText(getApplicationContext(), getString(R.string.no_selected_pdf), Toast.LENGTH_LONG).show();
return;
}
final BottomSheetDialog dialog = new BottomSheetDialog(MainActivity.this);
dialog.setContentView(R.layout.bottom_sheet);
dialog.setCanceledOnTouchOutside(true);
NumberPicker numberPicker = (NumberPicker) dialog.findViewById(R.id.number_picker);
if (numberPicker != null) {
numberPicker.setMaxValue(pageCount);
numberPicker.setValue(pdfView.getCurrentPage() + 1);
numberPicker.setOnValueChangedListener((picker, oldVal, newVal) -> {
pdfView.jumpTo(newVal - 1, true);
});
}
dialog.show();
}
public void openButtonClick(View view) {
launchPicker();
}
private void startAnimation(int state) {
actionLayout.animate()
.translationY(state == 0 ? actionLayout.getHeight() : 0)
.alpha(state == 0 ? 0 : 1.0f)
.setDuration(300).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
menu.findItem(R.id.hide_or_show_button).setChecked(state != 1);
super.onAnimationEnd(animation);
}
});
}
private void hideOrShowActionButton() {
if (actionLayout.getAlpha() == 1.0)
startAnimation(0);
else
startAnimation(1);
}
private void showSnackBar(#NonNull String msg, boolean isError) {
Snackbar snackbar = Snackbar
.make(findViewById(R.id.main_layout), msg, Snackbar.LENGTH_SHORT);
snackbar.setBackgroundTint(ContextCompat
.getColor(Objects.requireNonNull(getApplicationContext()),
isError ? R.color.err_color : R.color.main_color));
snackbar.setTextColor(ContextCompat
.getColor(Objects.requireNonNull(getApplicationContext()), R.color.white));
snackbar.show();
}
#Override
public void loadComplete(int nbPages) {
pageCount = nbPages;
warningLayout.setVisibility(View.GONE);
PdfDocument.Meta meta = pdfView.getDocumentMeta();
detailsMap.clear();
detailsMap.add(meta.getTitle());
detailsMap.add(meta.getAuthor());
detailsMap.add(meta.getSubject());
detailsMap.add(meta.getKeywords());
detailsMap.add(meta.getCreator());
detailsMap.add(meta.getProducer());
detailsMap.add(dateFormatter(meta.getCreationDate()));
detailsMap.add(dateFormatter(meta.getModDate()));
}
private String dateFormatter(String data) {
if (!data.isEmpty()) {
String date = data.substring(2);
String y = date.substring(0, 4);
String m = date.substring(4, 6);
String d = date.substring(6, 8);
return y + "/" + m + "/" + d;
} else {
return data;
}
}
#Override
public void onPageChanged(int page, int pageCount) {
pageNumber.setText(String.valueOf(page + 1));
}
#Override
public void onPageError(int page, Throwable t) {
showSnackBar(getString(R.string.page_not_loaded) + page, true);
}
}
Xml File
This Is Xml File if needed
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bg_color"
tools:context=".MainActivity">
<com.github.barteksc.pdfviewer.PDFView
android:id="#+id/pdf_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bg_color"
app:layout_anchor="#+id/warning"
app:layout_anchorGravity="center">
<Button
android:id="#+id/button"
android:layout_width="42dp"
android:layout_height="11dp"
android:layout_below="#id/textView"
android:layout_alignParentBottom="true"
android:layout_marginBottom="518dp"
android:text="open activity 2" />
</com.github.barteksc.pdfviewer.PDFView>
<LinearLayout
android:id="#+id/warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/no_selected_pdf"
android:textColor="#color/secondary_text_color"
android:textSize="16sp" />
<TextView
android:id="#+id/tv_open_pdf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="true"
android:focusable="true"
android:onClick="openButtonClick"
android:padding="10dp"
android:text="#string/click_to_select_pdf"
android:textColor="#color/main_color"
android:textSize="18sp" />
</LinearLayout>
<FrameLayout
android:id="#+id/action_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="20dp"
android:contentDescription="#string/action_btn_description"
android:onClick="actionButtonClick"
app:backgroundTint="#color/main_color"
app:borderWidth="0dp"
app:tint="#color/white" />
<TextView
android:id="#+id/tv_page_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:elevation="16dp"
android:text="x"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white"
android:textSize="16sp" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
There is an onClick and onLongClick listener for each view :
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
FloatingActionButton actionButton = findViewById(R.id.actionButton);
actionButton.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// start your activity from here
return true;
}
});
}
I have issue when I change some value, example delete comment in my recyclerview it's doesn't update automatically, Google says use LiveData DataBinding RecyclerView, is anyone ever to make RecyclerView LiveData databinding please help me out
This is my MainActivity.java
public class TabDetailHotActivity extends AppCompatActivity {
//GLOBAL
public static MainActivity mainActivity_;
TextView TVGameDate;
TextView TVGameTitle;
ImageView IMGGameImage;
TextView TVSeenCounter;
TextView TVCommentCounter;
TextView TVLikeCounter;
ImageView IMGSeenView;
ImageView IMGCommentView;
ImageView IMGLikeView;
ImageView ICONHotTrendingNewsSaving;
//EVENT BUS
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MainActivity.EventStoredMessageTrending event) {
getMessageTrendingMainActivity(event.SendMessageUrutan, event.SendTotalThread, event.SendMessageIDComment, event.SendMessageComment, event.SendMessageEntryTime, event.SendMessageisEdited, event.SendMessageEditTime);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MainActivity.EventStoredMessageTrendingLogin event) {
getMessageTrendingLoginMainActivity(event.SendMessageUrutan, event.SendTotalThread, event.SendMessageIDComment, event.SendMessageComment, event.SendMessageEntryTime, event.SendMessageisEdited, event.SendMessageEditTime, event.SendMessageEditable);
}
public void getMessageTrendingMainActivity(int ReceivedMessageUrutan, int ReceivedTotalThread, String ReceivedMessageIDComment, String ReceivedMessageComment, String ReceivedMessageEntryTime, int ReceivedMessageEdited, String ReceivedMessageEditTime){
Toast.makeText(this, "Load Comment Not Login :( >> ReceivedMessageComment:"+ReceivedMessageComment+", Toast.LENGTH_LONG).show();
}
public void getMessageTrendingLoginMainActivity(int ReceivedMessageUrutan, int ReceivedTotalThread, String ReceivedMessageIDComment, String ReceivedMessageComment, String ReceivedMessageEntryTime, int ReceivedMessageEdited, String ReceivedMessageEditTime, int ReceivedMessageEditable){
Toast.makeText(this, "Load Comment Login :) >> ReceivedMessageComment:" + ReceivedMessageComment, Toast.LENGTH_LONG).show();
createDummyDataComment(ReceivedMessageUrutan, ReceivedTotalThread, ReceivedMessageIDComment, ReceivedMessageComment, ReceivedMessageEntryTime, ReceivedMessageEdited, ReceivedMessageEditTime, ReceivedMessageEditable);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activitydetail_tabhot);
ToolbarX = findViewById(R.id.toolbar);
setSupportActionBar(ToolbarX);
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
final CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
collapsingToolbarLayout.setTitle("");
Intent intent = getIntent();
mDummyIDContent = intent.getStringExtra("DummyIDContentPKG");
mDummyTitle = intent.getStringExtra("DummyTitlePKG");
mDummyPublishTime = intent.getStringExtra("DummyPublishTimePKG");
mDummyImageOriPKG = intent.getStringExtra("DummyImageOriPKG");
mDummyShortDescription = intent.getStringExtra("DummyShortDescriptionPKG");
mDummySeen = intent.getIntExtra("DummySeenPKG", 0);
mDummyComment = intent.getIntExtra("DummyCommentPKG", 0);
mDummyLike = intent.getIntExtra("DummyLikePKG", 0);
mDummyisComment = intent.getIntExtra("DummyisCommentPKG", 0);
mDummyisLike = intent.getIntExtra("DummyisLikePKG", 0);
mDummyisBookmark = intent.getIntExtra("DummyisBookmarkPKG", 0);
date_Behaviour = findViewById(R.id.date_behavior);
IMGGameImage = findViewById(R.id.backdrop);
TVGameDate = findViewById(R.id.date);
TVGameTitle = findViewById(R.id.title);
TVSeenCounter = findViewById(R.id.TV_SeenCounter);
TVCommentCounter = findViewById(R.id.TV_CommentCounter);
TVLikeCounter = findViewById(R.id.TV_LikeCounter);
RequestOptions requestOptions = new RequestOptions();
requestOptions.error(UtilsNews.getRandomDrawbleColor());
TVGameDate.setText(mDummyPublishTime);
TVGameTitle.setText(mDummyTitle);
TVSeenCounter.setText(String.valueOf(mDummySeen));
TVCommentCounter.setText(String.valueOf(mDummyComment));
TVLikeCounter.setText(String.valueOf(mDummyLike));
Glide.with(this)
.load(mDummyImageOriPKG)
.apply(requestOptions)
.transition(DrawableTransitionOptions.withCrossFade())
.into(IMGGameImage);
/* initWebView(mUrl);*/
ImageButton BTNSendMessageDetailHotTrendingNews = findViewById(R.id.BTN_SendMessageDetailHotTrendingNews);
final TextView ETSendMessageDetailHotTrendingNews = findViewById(R.id.ET_SendMessageDetailHotTrendingNews);
BTNSendMessageDetailHotTrendingNews.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String TheMessage = ETSendMessageDetailHotTrendingNews.getText().toString();
if(!TheMessage.equals("")){
if(mainActivity_!=null) {
mainActivity_.rncryptorLoadSendEditDelete("SendComment", mDummyIDContent, TheMessage);
}
}else{
Toast.makeText(TabDetailHotActivity.this, "You don't send anything", Toast.LENGTH_SHORT).show();
}
ETSendMessageDetailHotTrendingNews.setText("");
}
});
//
if(mainActivity_!=null) {
mainActivity_.rncryptorLoadSendEditDelete("LoadComment", mDummyIDContent, "");
}
}
private void initWebView(String url) {
WebView webView = findViewById(R.id.webView);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(true);
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl(url);
}
ArrayList<ModelDetailHotTrendingNewsComment> modelDetailHotTrendingNewsComments = new ArrayList<ModelDetailHotTrendingNewsComment>();
AdapterDetailHotTrendingNewsComment.RecyclerViewClickListener listenerDetailHotTrendingNewsComment;
public void createDummyDataComment(int ReceivedMessageUrutan, int ReceivedTotalThread, final String ReceivedMessageIDComment, String ReceivedMessageComment, String ReceivedMessageEntryTime, int ReceivedMessageEdited, String ReceivedMessageEditTime, int ReceivedMessageEditable) {
modelDetailHotTrendingNewsComments.add(new ModelDetailHotTrendingNewsComment(ReceivedMessageIDComment,ReceivedMessageComment,ReceivedMessageEntryTime,ReceivedMessageEditable,ReceivedMessageEditTime));
if(ReceivedMessageUrutan == ReceivedTotalThread-1){
listenerDetailHotTrendingNewsComment = new AdapterDetailHotTrendingNewsComment.RecyclerViewClickListener(){
#Override
public void onRowDetailHotTrendingNewsContainerClick(View view, int position) {
}
#Override
public void onRowMessageEditClick(View view, int position) {
}
#Override
public void onRowMessageDeleteClick(View view, final int position) {
String[] YOURCHOICE = {"Yes", "No"};
AlertDialog.Builder builder = new AlertDialog.Builder(TabDetailHotActivity.this);
builder.setTitle("Do you want to delete this comment?");
builder.setItems(YOURCHOICE, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
Toast.makeText(TabDetailHotActivity.this, "Deleted Successfully!", Toast.LENGTH_SHORT).show();
if(mainActivity_!=null) {
mainActivity_.rncryptorLoadSendEditDelete("DeleteComment", modelDetailHotTrendingNewsComments.get(position).getIdcontent(), "");
}
}else if(which == 1){
Toast.makeText(TabDetailHotActivity.this, "You don't delete the Comment", Toast.LENGTH_SHORT).show();
}
}
});
builder.show();
}
};
RecyclerView RVDetailHotTrendingNewsComment = findViewById(R.id.RVDetail_HotTrendingNewsComment);
RVDetailHotTrendingNewsComment.setHasFixedSize(true);
AdapterDetailHotTrendingNewsComment adapterDetailHotTrendingNewsComment = new AdapterDetailHotTrendingNewsComment(this, modelDetailHotTrendingNewsComments, listenerDetailHotTrendingNewsComment);
RVDetailHotTrendingNewsComment.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
RVDetailHotTrendingNewsComment.setAdapter(adapterDetailHotTrendingNewsComment);
//Optimized
RVDetailHotTrendingNewsComment.setHasFixedSize(true);
RVDetailHotTrendingNewsComment.setItemViewCacheSize(20);
}
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
#Override
public void onBackPressed() {
super.onBackPressed();
supportFinishAfterTransition();
}
//EVENTBUS
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
}
This is my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#color/darkgrey"
tools:context=".TabDetailHotActivity">
<androidx.core.widget.NestedScrollView
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:background="#color/darkgrey"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_marginBottom="20dp"
android:layout_marginTop="20dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:background="#color/darkgrey"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/title"
android:textColor="#color/colorWhite"
android:textStyle="bold"
android:fontFamily="sans-serif-light"
android:textSize="19sp"
android:text="Title of News"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="#id/title"
android:textColor="#color/colorWhite"
android:layout_marginTop="10dp"
android:maxLines="1"
android:drawablePadding="10dp"
android:singleLine="true"
android:ellipsize="end"
android:text="a time ago" />
<ImageView
android:id="#+id/IMG_SeenView"
android:src="#drawable/watch"
android:layout_marginLeft="8dp"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#id/TV_SeenCounter"
android:paddingTop="2dp"
android:layout_marginTop="1dp"
android:scaleType="centerInside"
android:adjustViewBounds="true"/>
<TextView
android:id="#+id/TV_SeenCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#id/IMG_CommentView"
android:text="999"
android:layout_marginTop="2dp"
android:textSize="14dp"
android:textColor="#color/white"
android:paddingLeft="#dimen/small_intrinsic_padding"
android:textAppearance="#style/TextAppearance.Second.Light" />
<ImageView
android:id="#+id/IMG_CommentView"
android:src="#drawable/comment_off"
android:layout_toLeftOf="#id/TV_CommentCounter"
android:layout_alignParentBottom="true"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginTop="4dp"
android:layout_marginLeft="5dp"
android:layout_marginBottom="2dp"
android:scaleType="centerInside"
android:adjustViewBounds="true"/>
<TextView
android:id="#+id/TV_CommentCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#id/IMG_LikeView"
android:layout_marginTop="2dp"
android:text="999"
android:textSize="14dp"
android:textColor="#color/white"
android:paddingLeft="#dimen/small_intrinsic_padding"
android:textAppearance="#style/TextAppearance.Second.Light" />
<ImageView
android:id="#+id/IMG_LikeView"
android:src="#drawable/heart_off"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#id/TV_LikeCounter"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginTop="4dp"
android:layout_marginLeft="5dp"
android:layout_marginBottom="2dp"
android:scaleType="centerInside"
android:adjustViewBounds="true"/>
<TextView
android:id="#+id/TV_LikeCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_alignParentEnd="true"
android:text="999"
android:textSize="14dp"
android:layout_alignParentBottom="true"
android:textColor="#color/white"
android:paddingLeft="#dimen/small_intrinsic_padding"
android:textAppearance="#style/TextAppearance.Second.Light" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/darkgrey">
<ProgressBar
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:id="#+id/progress_bar"
android:layout_marginTop="50dp"
android:layout_marginBottom="70dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<WebView
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/RL_Bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:background="#FFFFFF"
android:layout_alignParentBottom="true">
<EditText
android:id="#+id/ET_SendMessageDetailHotTrendingNews"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:hint="Type a comment..."
android:layout_toLeftOf="#id/BTN_SendMessageDetailHotTrendingNews"
android:layout_centerVertical="true"/>
<ImageButton
android:id="#+id/BTN_SendMessageDetailHotTrendingNews"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="#drawable/ic_send_black_24dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/darkgrey">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RVDetail_HotTrendingNewsComment"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<FrameLayout
android:id="#+id/date_behavior"
app:layout_anchor="#+id/appbar"
app:behavior_autoHide="true"
android:adjustViewBounds="true"
app:layout_anchorGravity="right|end|bottom"
android:clickable="false"
android:background="#drawable/round_white"
android:layout_width="wrap_content"
android:padding="5dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"
android:layout_marginBottom="410dp"
android:layout_height="wrap_content"
tools:ignore="UnusedAttribute">
<ImageView
android:src="#drawable/ic_date"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
<TextView
android:textColor="#606060"
android:id="#+id/date"
android:layout_marginLeft="27dp"
android:layout_marginRight="10dp"
android:text="01 January 1990"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
This is AdapterComment.java
public class AdapterDetailHotTrendingNewsComment extends RecyclerView.Adapter {
private Context mContext;
private ArrayList<ModelDetailHotTrendingNewsComment> modelDetailHotTrendingNewsComments;
private AdapterDetailHotTrendingNewsComment.RecyclerViewClickListener mListener;
public AdapterDetailHotTrendingNewsComment(Context mContext, ArrayList<ModelDetailHotTrendingNewsComment> modelDetailHotTrendingNewsComments, AdapterDetailHotTrendingNewsComment.RecyclerViewClickListener mListener) {
this.mContext = mContext;
this.modelDetailHotTrendingNewsComments = modelDetailHotTrendingNewsComments;
this.mListener = mListener;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemdetail_hottrendingnewscomment, null);
return new DetailHotTrendingNewsViewHolder(v, mListener);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
final DetailHotTrendingNewsViewHolder detailHotTrendingNewsViewHolder = (DetailHotTrendingNewsViewHolder) holder;
final ModelDetailHotTrendingNewsComment modelDetailHotTrendingNewsCommentX = modelDetailHotTrendingNewsComments.get(position);
Glide.with(mContext).load(modelDetailHotTrendingNewsCommentX.getMessageimage()).into(detailHotTrendingNewsViewHolder.IMGMessageImage);
detailHotTrendingNewsViewHolder.TVMessageUsername.setText(modelDetailHotTrendingNewsCommentX.getMessageusername());
detailHotTrendingNewsViewHolder.TVMessageDescription.setText(modelDetailHotTrendingNewsCommentX.getMessagedescription());
detailHotTrendingNewsViewHolder.TVMessageDate.setText(modelDetailHotTrendingNewsCommentX.getMessagedate());
}
#Override
public int getItemCount() {
int itemCount = modelDetailHotTrendingNewsComments.size();
return itemCount;
}
public class DetailHotTrendingNewsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView IMGMessageImage;
TextView TVMessageUsername;
TextView TVMessageDescription;
TextView TVMessageDate;
private RelativeLayout ROWDetailHotTrendingNewsContainer;
TextView TVMessageEdit;
ImageView IMGMessageDelete;
private AdapterDetailHotTrendingNewsComment.RecyclerViewClickListener mListener;
public DetailHotTrendingNewsViewHolder(View itemView, AdapterDetailHotTrendingNewsComment.RecyclerViewClickListener listener) {
super(itemView);
IMGMessageImage = itemView.findViewById(R.id.IMG_MessageImage);
TVMessageUsername = itemView.findViewById(R.id.TV_MessageUsername);
TVMessageDescription = itemView.findViewById(R.id.TV_MessageDescription);
TVMessageDate = itemView.findViewById(R.id.TV_MessageDate);
ROWDetailHotTrendingNewsContainer = itemView.findViewById(R.id.ROW_DetailHotTrendingNewsContainer);
TVMessageEdit = itemView.findViewById(R.id.TV_MessageEdit);
IMGMessageDelete = itemView.findViewById(R.id.IMG_MessageDelete);
mListener = listener;
ROWDetailHotTrendingNewsContainer.setOnClickListener(this);
TVMessageEdit.setOnClickListener(this);
IMGMessageDelete.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ROW_DetailHotTrendingNewsContainer:
mListener.onRowDetailHotTrendingNewsContainerClick(ROWDetailHotTrendingNewsContainer, getAdapterPosition());
break;
case R.id.TV_MessageEdit:
mListener.onRowMessageEditClick(TVMessageEdit, getAdapterPosition());
break;
case R.id.IMG_MessageDelete:
mListener.onRowMessageDeleteClick(IMGMessageDelete, getAdapterPosition());
break;
default:
break;
}
}
}
public interface RecyclerViewClickListener {
void onRowDetailHotTrendingNewsContainerClick(View view, int position);
void onRowMessageEditClick(View view, int position);
void onRowMessageDeleteClick(View view, int position);
}
}
This is ModelComment.java
public class ModelDetailHotTrendingNewsComment {
private String idcontent;
private String messageimage;
private String messageusername;
private String messagedescription;
private String messagedate;
private int messageisedit;
private String messageedittime;
private String messageedit;
private String messagedelete;
public ModelDetailHotTrendingNewsComment(String idcontent, String messagedescription, String messagedate, int messageisedit, String messageedittime) {
this.idcontent = idcontent;
this.messagedescription = messagedescription;
this.messagedate = messagedate;
this.messageisedit = messageisedit;
this.messageedittime = messageedittime;
}
public String getIdcontent() {
return idcontent;
}
public void setIdcontent(String idcontent) {
this.idcontent = idcontent;
}
public String getMessageimage() {
return messageimage;
}
public void setMessageimage(String messageimage) {
this.messageimage = messageimage;
}
public String getMessageusername() {
return messageusername;
}
public void setMessageusername(String messageusername) {
this.messageusername = messageusername;
}
public String getMessagedescription() {
return messagedescription;
}
public void setMessagedescription(String messagedescription) {
this.messagedescription = messagedescription;
}
public String getMessagedate() {
return messagedate;
}
public void setMessagedate(String messagedate) {
this.messagedate = messagedate;
}
public String getMessageedittime() {
return messageedittime;
}
public void setMessageedittime(String messageedittime) {
this.messageedittime = messageedittime;
}
public String getMessageedit() {
return messageedit;
}
public void setMessageedit(String messageedit) {
this.messageedit = messageedit;
}
public String getMessagedelete() {
return messagedelete;
}
public void setMessagedelete(String messagedelete) {
this.messagedelete = messagedelete;
}
}
I am confused what might be the reason behind this error.While making my edittext field null after entering a digit into it my application is getting crashed.can you find a solution for this situation ??
here is my code
java file
public class CSLActivity extends AppCompatActivity {
private Common mApp;
private AutoCompleteTextView clgName, conCent, loc;
private MultiAutoCompleteTextView skill;
private String[] qulify = new String[]{"Select Highest Qualification", "PG", "UG", "DIPLOMA"};
public String abc, abcd;
public ScrollView scrollView;
public ProgressBar progressBar;
private String q;
private Spinner level;
private int ab = 1990;
public EditText fullName, frm_yr, to_yr;
private boolean ins = false;
private boolean cIns = false;
private Button next;
private TextfieldValidator textfieldValidator;
private AlphabetValidator alphabetValidator;
private int i = 0, j = 0;
private boolean exit = false;
private String get;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_csl);
scrollView = (ScrollView) findViewById(R.id.scroll_view);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
fullName = (EditText) findViewById(R.id.fullName);
level = (Spinner) findViewById(R.id.level);
clgName = (AutoCompleteTextView) findViewById(R.id.clg_name);
conCent = (AutoCompleteTextView) findViewById(R.id.concent);
frm_yr = (EditText) findViewById(R.id.frm_yr);
to_yr = (EditText) findViewById(R.id.to_yr);
skill = (MultiAutoCompleteTextView) findViewById(R.id.skill);
loc = (AutoCompleteTextView) findViewById(R.id.location);
textfieldValidator = new TextfieldValidator();
alphabetValidator = new AlphabetValidator();
next = (Button) findViewById(R.id.next);
frm_yr.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//abc = frm_yr.getText().toString();
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
//i = Integer.parseInt(frm_yr.getText().toString());
//i = Integer.parseInt(abc.toString());
i = Integer.parseInt(frm_yr.getText().toString());
}
});
to_yr.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
//j = Integer.parseInt(to_yr.getText().toString());
//j = Integer.parseInt(abcd.toString());
j = Integer.parseInt(to_yr.getText().toString());
}
});
new GetCollege(CSLActivity.this, progressBar, scrollView, clgName).execute();
new GetCourse(CSLActivity.this, conCent).execute();
new GetSkillSet(CSLActivity.this, scrollView, progressBar, skill).execute();
new GetLocation(CSLActivity.this, scrollView, loc, progressBar).execute();
ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(getApplicationContext(), R.layout.spinner_item, qulify);
level.setAdapter(adapter1);
level.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
get = level.getSelectedItem().toString();
if (get.equalsIgnoreCase("PG")) {
q = "1";
} else if (get.equalsIgnoreCase("UG")) {
q = "2";
} else {
q = "3";
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
clgName.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView txt = (TextView) view.findViewById(R.id.ins_name);
clgName.setText(txt.getText().toString());
conCent.requestFocus();
ins = true;
}
});
conCent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView txt = (TextView) view.findViewById(R.id.display);
conCent.setText(txt.getText().toString());
cIns = true;
frm_yr.requestFocus();
}
});
loc.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView txt1 = (TextView) view.findViewById(R.id.ins_name);
loc.setText(txt1.getText().toString());
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromInputMethod(view.getWindowToken(), 0);
}
});
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.next:
if (fullName.getText().toString().length() == 0) {
fullName.setError("Field Mandatory");
fullName.requestFocus();
} else if (!alphabetValidator.validate(fullName.getText().toString())) {
fullName.setError("Enter a Valid Name");
fullName.requestFocus();
} else if (get.equalsIgnoreCase("Select Highest Qualification")) {
level.requestFocus();
Toast.makeText(getApplicationContext(), "select Qualification", Toast.LENGTH_SHORT).show();
} else if (clgName.getText().toString().length() == 0) {
clgName.setError("Field Mandatory");
clgName.requestFocus();
} else if (conCent.getText().toString().length() == 0) {
conCent.setError("Field Mandatory");
conCent.requestFocus();
} else if (frm_yr.getText().toString().length() == 0) {
frm_yr.setError("Field Mandatory");
frm_yr.requestFocus();
} else if (to_yr.getText().toString().length() == 0) {
to_yr.setError("Field Mandatory");
to_yr.requestFocus();
} else if (i > j) {
to_yr.setError("Passed out year less than join year");
to_yr.requestFocus();
} else if (i == j) {
to_yr.setError("Check the year entered");
to_yr.requestFocus();
} else if (i <= ab) {
frm_yr.setError("Enter a valid Year");
frm_yr.requestFocus();
} else if (j <= ab) {
to_yr.setError("Enter a valid Year");
to_yr.requestFocus();
} else if (skill.getText().toString().length() == 0) {
skill.setError("Field Mandatory");
skill.requestFocus();
} else if (!textfieldValidator.validate(skill.getText().toString())) {
skill.setError("Enter a Valid Skill");
skill.requestFocus();
} else if (loc.getText().toString().length() == 0) {
loc.setError("Field Mandatory");
loc.requestFocus();
} else if (!textfieldValidator.validate(loc.getText().toString())) {
loc.setError("Enter a Valid Location");
} else {
next.setEnabled(false);
new CslIns(CSLActivity.this, mApp.getPreference().getString(Common.u_id, ""), fullName.getText().toString(), q,
clgName.getText().toString(), conCent.getText().toString(), frm_yr.getText().toString(), to_yr.getText().toString(),
skill.getText().toString(), loc.getText().toString(), ins, cIns).execute();
/*startActivity(new Intent(getApplicationContext(), MailVerify.class));
finish();*/
}
break;
}
}
});
}
#Override
public void onBackPressed() {
if (exit) {
mApp.getPreference().edit().putBoolean(Common.PAGE1, false).commit();
super.onBackPressed();
return;
} else {
Toast.makeText(this, "Press Back again to Cancel Signup Process.", Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
exit = false;
}
}, 2000);
}
}
}
my xml file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.shuan.Project.signup.employee.CSLActivity">
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<ScrollView
android:id="#+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/activity_horizontal_margin"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/fullName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin"
android:hint="Full Name"
android:imeOptions="actionNext"
android:inputType="textPersonName" />
</android.support.design.widget.TextInputLayout>
<Spinner
android:id="#+id/level"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin">
<AutoCompleteTextView
android:id="#+id/clg_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/clg_name"
android:imeOptions="actionNext" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin">
<AutoCompleteTextView
android:id="#+id/concent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/concent"
android:imeOptions="actionNext"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:id="#+id/yr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Joined"
android:textColor="#000"
android:textStyle="bold" />
<EditText
android:id="#+id/frm_yr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/small_margin"
android:hint="Year"
android:imeOptions="actionNext"
android:inputType="numberDecimal"
android:maxLength="4"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Passed :"
android:textColor="#000"
android:textStyle="bold" />
<EditText
android:id="#+id/to_yr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/small_margin"
android:hint="Year"
android:imeOptions="actionNext"
android:inputType="numberDecimal"
android:maxLength="4"
android:singleLine="true" />
</LinearLayout>
</LinearLayout>
<android.support.design.widget.TextInputLayout
android:id="#+id/layout_skill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin">
<MultiAutoCompleteTextView
android:id="#+id/skill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Your Skills"
android:imeOptions="actionNext"
android:inputType="text" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="#+id/layout_location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/standard_margin">
<AutoCompleteTextView
android:id="#+id/location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/location"
android:imeOptions="actionDone"
android:inputType="textAutoComplete" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="#+id/next"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="#dimen/activity_horizontal_margin"
android:background="#drawable/signin_border"
android:text="START"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#fff"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
log cat
FATAL EXCEPTION: main
Process: com.shuan.Project, PID: 1432
java.lang.NumberFormatException: Invalid int: ""
at java.lang.Integer.invalidInt(Integer.java:138)
at java.lang.Integer.parseInt(Integer.java:358)
at java.lang.Integer.parseInt(Integer.java:334)
at com.shuan.Project.signup.employee.CSLActivity$1.afterTextChanged(CSLActivity.java:95)
at android.widget.TextView.sendAfterTextChanged(TextView.java:7998)
at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:9814)
at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:990)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:529)
at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:224)
at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:38)
at android.view.inputmethod.BaseInputConnection.deleteSurroundingText(BaseInputConnection.java:252)
at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:389)
at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:78)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5649)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
Try this code
public void afterTextChanged(Editable s) {
if(to_yr.getText().toString().length != 0){
j =Integer.parseInt(to_yr.getText().toString());
}
}
it works fine for me
At a first look, to me it seems to block on onAfterTextChanged, because is trying to parse an int from a String which is empty, so it just throws the error.
Try to verify if the EditText is "" before of parsing the integer, if it is not "" or null do as your code, if it's "" or null give it a default value, like 0 or what you want.
This crash is because of your code in afterTextChanged callback.
You should check if to_yr.getText is having some valid value before parsing it to the integer. Do not parse empty string.
Use below code:
public void afterTextChanged(Editable s) {
if(!TextUtils.isEmpty(to_yr.getText()){
j = Integer.parseInt(to_yr.getText().toString());
}
}
This is happening because you parse the empty string and the Integer class throws exception named:
Invalid int
java.lang.NumberFormatException
Do the check before parsing integer. For example
String s;
if(s != null && (!s.isEmpty())){
Integer i = s.ParseInt();
}
As a beginner I have some questions about optimizing my application speed. I'm building a simple quiz app there I have an sqlite database inside with some information. With that information I'm generating my questions in quiz page.
It was working pretty fine and fast until I fixed some buttons/background in sketch and use them. Now it's working much more slower and I'm getting error messages at logcat like "Skipped xxx frames! The application may be doing too much work on its main thread." I have searched on google for a while and found out that the bitmaps are slowing down my application. Have read about async and using a new thread to make it run faster.
As a solution I have resized some of my bitmaps, but then I'm getting less quality in my design, so I decided to fix it. I have googled some more about loading my layout with async or a new thread but didn't really find out how/where to do it. What makes me confused is that I don't know if it's to load layout with a new thread is the best solution or to load other processes with new thread. Need some recommendation about how to optimize my app. Here is my code, at least the quiz page that is slowest. I'm not really sure what to optimize there with a new thread. Under a question it's just countdowntimer that is running, and when next clicked countdowntimer starts over and the gui updates with the new question.
My quizpage code:
public class QuizPage extends ActionBarActivity
{
DatabaseHelper dbHelper = new DatabaseHelper(this);
Cursor kommunCrs, lanCrs, riktCrs;
ArrayList<Kommuner> kommunLista = new ArrayList<Kommuner>();
ArrayList<Lan> lanLista = new ArrayList<Lan>();
ArrayList<Riktnummer> riktLista = new ArrayList<Riktnummer>();
ArrayList<Fragar> fragaLista = new ArrayList<Fragar>();
Fragar svList = new Fragar();
Fragar frageObj = new Fragar();
int buttonRaknare = 0;
CountDownTimer cd;
long millisLeft;
long totalMillis = 10100;
int pBarProgress;
TextView pageNr, fraga, cdText;
RadioButton valA, valB, valC, valD;
RadioGroup rg;
Button avsluta, nasta;
ProgressBar pBar;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz_page);
checkDB(); // Checking the DB
getCursorData(); // Getting data to cursors
setCrsdataList(); // Setting cursor data to lists
setViewElements(); // Set textview, buttons etc.
setButtonListeners();
getNastaFragaData(); // Refresing the gui with the next question
startCountdownTimer(totalMillis, false); // Countdowntimer starts
}
private void getCursorData()
{
kommunCrs = dbHelper.getDatabase().query("Kommuner ORDER BY RANDOM() LIMIT 50", new String[]{"kommun_id", "kommun_namn", "kommun_lan", "kommun_befolkning"}, null, null, null, null, null);
lanCrs = dbHelper.getDatabase().query("Lan ORDER BY RANDOM()", new String[]{"lan_namn", "lan_befolkning", "lan_antal_kommun", "lan_yta", "lan_id"}, null, null, null, null, null);
riktCrs = dbHelper.getDatabase().query("Riktnummer ORDER BY RANDOM() LIMIT 50", new String[]{"riktnr", "riktnr_omrade", "riktnr_id"}, null, null, null, null, null);
}
private void setCrsdataList()
{
if (kommunCrs.getCount() != 0 && lanCrs.getCount() != 0 && riktCrs.getCount() != 0) {
kommunCrs.moveToFirst();
lanCrs.moveToFirst();
riktCrs.moveToFirst();
for (int i = 0; i < kommunCrs.getCount(); i++) {
Kommuner tempKommun = new Kommuner();
tempKommun.setKommun_namn(kommunCrs.getString(kommunCrs.getColumnIndex("kommun_namn")));
tempKommun.setKommun_lan(kommunCrs.getString(kommunCrs.getColumnIndex("kommun_lan")));
tempKommun.setKommun_befolkning(kommunCrs.getString(kommunCrs.getColumnIndex("kommun_befolkning")));
tempKommun.setKommun_id(kommunCrs.getInt(kommunCrs.getColumnIndex("kommun_id")));
kommunLista.add(tempKommun);
kommunCrs.moveToNext();
}
for (int i = 0; i < lanCrs.getCount(); i++) {
Lan tempLan = new Lan();
tempLan.setLan_namn(lanCrs.getString(lanCrs.getColumnIndex("lan_namn")));
tempLan.setLan_befolkning(lanCrs.getString(lanCrs.getColumnIndex("lan_befolkning")));
tempLan.setLan_antal_kommun(lanCrs.getString(lanCrs.getColumnIndex("lan_antal_kommun")));
tempLan.setLan_yta(lanCrs.getString(lanCrs.getColumnIndex("lan_yta")));
tempLan.setLan_id(lanCrs.getInt(lanCrs.getColumnIndex("lan_id")));
lanLista.add(tempLan);
lanCrs.moveToNext();
}
for (int i = 0; i < riktCrs.getCount(); i++) {
Riktnummer tempRiktnr = new Riktnummer();
tempRiktnr.setRiktnr(riktCrs.getString(riktCrs.getColumnIndex("riktnr")));
tempRiktnr.setRiktnr_omrade(riktCrs.getString(riktCrs.getColumnIndex("riktnr_omrade")));
tempRiktnr.setRiktnr_id(riktCrs.getInt(riktCrs.getColumnIndex("riktnr_id")));
riktLista.add(tempRiktnr);
riktCrs.moveToNext();
}
//Generating my questions here and taking in to a list
fragaLista = frageObj.slumpaFragor(kommunLista, lanLista, riktLista);
Collections.shuffle(fragaLista);
}
else
{
Toast.makeText(getApplicationContext(), "Finns ingen data i databasen!", Toast.LENGTH_SHORT).show();
}
}
private void getNastaFragaData()
{
fraga.setText(fragaLista.get(buttonRaknare).getFraga());
valA.setText(fragaLista.get(buttonRaknare).getSvarArr().get(0).toString());
valB.setText(fragaLista.get(buttonRaknare).getSvarArr().get(1).toString());
valC.setText(fragaLista.get(buttonRaknare).getSvarArr().get(2).toString());
valD.setText(fragaLista.get(buttonRaknare).getSvarArr().get(3).toString());
pageNr.setText(Integer.toString(buttonRaknare+1) + "/20");
}
private void rattSvarCheck()
{
if (valA.isChecked())
{
fragaLista.get(buttonRaknare).userInput = valA.getText().toString();
if (valA.getText().hashCode() == fragaLista.get(buttonRaknare).getRattSvar().hashCode())
{
svList.antalRattSvar++;
}
else
{
svList.antalFelSvar++;
}
}
else if (valB.isChecked())
{
fragaLista.get(buttonRaknare).userInput = valB.getText().toString();
if (valB.getText().hashCode() == fragaLista.get(buttonRaknare).getRattSvar().hashCode())
{
svList.antalRattSvar++;
}
else
{
svList.antalFelSvar++;
}
}
else if (valC.isChecked())
{
fragaLista.get(buttonRaknare).userInput = valC.getText().toString();
if (valC.getText().hashCode() == fragaLista.get(buttonRaknare).getRattSvar().hashCode())
{
svList.antalRattSvar++;
}
else
{
svList.antalFelSvar++;
}
}
else if (valD.isChecked())
{
fragaLista.get(buttonRaknare).userInput = valD.getText().toString();
if (valD.getText().hashCode() == fragaLista.get(buttonRaknare).getRattSvar().hashCode())
{
svList.antalRattSvar++;
}
else
{
svList.antalFelSvar++;
}
}
else
{
fragaLista.get(buttonRaknare).userInput = "";
svList.antalTomtSvar++;
}
}
private void resultatToDatabas()
{
dbHelper.resultatToDatabas(svList.antalRattSvar, svList.antalFelSvar, svList.antalTomtSvar);
Intent i = new Intent(getBaseContext(),QuizResultat.class);
i.putExtra("rslist", fragaLista);
i.putExtra("sl", svList);
finish();
startActivity(i);
}
private void startCountdownTimer(long millis, final boolean isResume)
{
if (!isResume)
{
pBar.setProgress(100);
pBar.setProgressDrawable(pBar.getResources().getDrawable(R.drawable.nypbar));
}
else
{
pBar.setProgress(pBarProgress);
pBar.setProgressDrawable(pBar.getResources().getDrawable(R.drawable.nypbar));
if (pBar.getProgress() < 55 && pBar.getProgress() > 23 )
{
pBar.getProgressDrawable().setColorFilter(Color.parseColor("#FFFFB800"), PorterDuff.Mode.SRC_IN);
}
else if (pBar.getProgress() < 23)
{
pBar.getProgressDrawable().setColorFilter(Color.parseColor("#FFE71000"), PorterDuff.Mode.SRC_IN);
}
}
int callInterval = 100;
cd = new CountDownTimer(millis, callInterval)
{
public void onTick(long millisUntilFinished)
{
millisLeft = millisUntilFinished;
pBarProgress = pBar.getProgress();
int secondsRemaining = (int) millisUntilFinished / 100;
float fraction = millisUntilFinished / (float) totalMillis;
// progress bar is based on scale of 1 to 100;
pBar.setProgress((int) (fraction * 100));
cdText.setText(String.format("%2.1f", secondsRemaining / 10.0, Integer.toString(secondsRemaining)));
if (pBar.getProgress() < 55 && pBar.getProgress() > 23 )
{
pBar.getProgressDrawable().setColorFilter(Color.parseColor("#FFFFB800"), PorterDuff.Mode.SRC_IN);
}
else if (pBar.getProgress() < 23)
{
pBar.getProgressDrawable().setColorFilter(Color.parseColor("#FFE71000"), PorterDuff.Mode.SRC_IN);
}
}
public void onFinish() {
nasta.performClick();
}
}.start();
}
// Deklarera knappar, textview osv.
private void setViewElements()
{
pageNr = (TextView) findViewById(R.id.pageNumberTxt);
fraga = (TextView) findViewById(R.id.fragaTxt);
valA = (RadioButton) findViewById(R.id.valAbtn);
valB = (RadioButton) findViewById(R.id.valBbtn);
valC = (RadioButton) findViewById(R.id.valCbtn);
valD = (RadioButton) findViewById(R.id.valDbtn);
rg = (RadioGroup) findViewById(R.id.valRadioGrupp);
avsluta = (Button) findViewById(R.id.avslutaBtn);
nasta = (Button) findViewById(R.id.nastaBtn);
pBar = (ProgressBar) findViewById(R.id.progressBar);
cdText = (TextView) findViewById(R.id.counterTxt);
}
private void setButtonListeners()
{
// Nästaknapp onClick
nasta.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
cd.cancel(); // Avslutar countdowntimer
rattSvarCheck(); // Kontrollerar om svaret är rätt
if (buttonRaknare > 17)
{
nasta.setBackground(getResources().getDrawable(R.drawable.avsluta_selector));
}
if (buttonRaknare != 19) // Så länge det inte är sista frågan
{
buttonRaknare++;
rg.clearCheck(); // Tar bort check från valknapparna
startCountdownTimer(totalMillis, false); // Startar om den avslutade countdowntimer
getNastaFragaData(); // Tar nästa frågans innehåll till view
}
else if (buttonRaknare == 19)
{
resultatToDatabas(); // Sparar resultaten till databasen
}
}
});
// Avslutaknapp onClick
avsluta.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
cd.cancel(); // Pausar cooldowntimer först
visaAlertDialog(); // Visar alert dialog
}
});
}
// Visa alertDialog
private void visaAlertDialog()
{
AlertDialog.Builder adBuild = new AlertDialog.Builder(this)
.setTitle("Avsluta")
.setMessage("Vill du avsluta quizet?")
.setIcon(android.R.drawable.ic_delete)
.setPositiveButton(new String(Character.toChars(0x1F616)) + " Japp! ", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton(new String(Character.toChars(0x1F60A)) + " Nej", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
cd.cancel();
//RESUME COUNTDOWNTIMER
startCountdownTimer(millisLeft, true);
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
dialog.cancel();
cd.cancel();
//RESUME COUNTDOWNTIMER
startCountdownTimer(millisLeft, true);
}
});
AlertDialog alertDialog = adBuild.create();
alertDialog.show();
}
private void checkDB()
{
try
{
dbHelper.createDataBase();
dbHelper.openDataBase();
} catch (IOException a) {
a.printStackTrace();
} catch (SQLException b) {
b.printStackTrace();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
{
setContentView(R.layout.activity_quiz_page);
setViewElements();
setButtonListeners();
getNastaFragaData();
}
else
{
setContentView(R.layout.activity_quiz_page);
setViewElements();
setButtonListeners();
getNastaFragaData();
}
}
// onBackPressed metod som visar alertDialog
#Override
public void onBackPressed()
{
cd.cancel();
visaAlertDialog();
}
// onStop METHOD
#Override
protected void onStop()
{
super.onStop();
dbHelper.close();
}
}
My quizpage layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" 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"
android:background="#drawable/quizpage_bg"
tools:context="com.example.onur.quiz.QuizPage">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:text="1/20"
android:id="#+id/pageNumberTxt"
android:textSize="18dp"
android:textColor="#ffab6200"
android:background="#drawable/pagenumberbg"
android:textStyle="italic|bold"
android:gravity="center"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:paddingTop="2dp"
android:paddingBottom="5dp"
android:paddingRight="3dp"
android:paddingLeft="3dp" />
<Button
android:layout_width="135dp"
android:layout_height="50dp"
android:id="#+id/nastaBtn"
android:focusable="false"
android:nestedScrollingEnabled="false"
android:background="#drawable/nasta_selector"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginBottom="15dp" />
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:id="#+id/avslutaBtn"
android:background="#drawable/exit_selector"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true" />
<RadioGroup
android:id="#+id/valRadioGrupp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="false"
android:gravity="center_vertical"
android:layout_marginTop="20dp"
android:layout_alignParentStart="false"
android:layout_below="#+id/progressBar"
android:divider="#00FFFFFF"
android:layout_above="#+id/nastaBtn"
android:layout_marginBottom="10dp"
android:background="#drawable/svarbg" >
<RadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="valAtxt"
android:id="#+id/valAbtn"
android:checked="false"
android:textSize="22dp"
android:layout_alignParentLeft="true"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#drawable/custom_rg_drawer"
android:paddingLeft="15dp" />
<RadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="valBbtn"
android:id="#+id/valBbtn"
android:checked="false"
android:textSize="22dp"
android:layout_alignLeft="#+id/nastaBtn"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#drawable/custom_rg_drawer"
android:paddingLeft="15dp" />
<RadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="valCbtn"
android:id="#+id/valCbtn"
android:checked="false"
android:textSize="22dp"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#drawable/custom_rg_drawer"
android:paddingLeft="15dp" />
<RadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="valDbtn"
android:id="#+id/valDbtn"
android:checked="false"
android:textSize="22dp"
android:layout_alignParentLeft="true"
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:background="#drawable/custom_rg_drawer"
android:paddingLeft="15dp" />
</RadioGroup>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Hur många personer bor i Trollhättan?"
android:id="#+id/fragaTxt"
android:textColor="#ffc37800"
android:textSize="24dp"
android:layout_marginTop="20dp"
android:layout_below="#+id/avslutaBtn"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="false"
android:gravity="center"
android:background="#drawable/fragabg"
android:paddingLeft="10dp"
android:paddingRight="10dp" />
<ProgressBar
style="#android:style/Widget.ProgressBar.Horizontal"
android:progressDrawable = "#drawable/nypbar"
android:layout_width="290dp"
android:layout_height="10dp"
android:id="#+id/progressBar"
android:layout_marginTop="15dp"
android:layout_below="#+id/fragaTxt" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="10.00"
android:id="#+id/counterTxt"
android:layout_alignParentRight="true"
android:layout_below="#+id/fragaTxt"
android:layout_marginTop="11dp" />
</RelativeLayout>
I don't think it has much to do with bitmaps, especially if you are pulling them from Drawable resources. The source of your lag is likely your database queries, which are happening in onCreate, which are blocking the main thread to do disk access. Instead, use a CursorLoader as described in https://developer.android.com/training/load-data-background/setup-loader.html
I have a custom listview with two textviews . If I use the emulator d-pad, everything works fine, the row is selected, but if I click on the item on the emulator (or try to select on the phone) nothing get selected.
addresslist.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="wrap_content"
android:orientation="horizontal" android:paddingBottom="6dip"
android:paddingTop="4dip">
<TextView android:id="#+id/DENUMIRE_CELL"
android:layout_width="50dp" android:layout_height="wrap_content"
android:layout_weight="1.03" />
<TextView android:id="#+id/ADRESA_CELL" android:layout_width="50dp"
android:layout_height="wrap_content" android:layout_weight="0.84" />
</LinearLayout>
clienti.xml:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<TableRow android:id="#+id/tableRow1" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout android:orientation="horizontal"
android:focusable="true" android:focusableInTouchMode="true">
<EditText android:id="#+id/editTextCauta"
android:layout_width="100dp" android:layout_height="wrap_content"
android:layout_weight="0.04" />
<Button android:id="#+id/buttonCauta" android:layout_width="70dp"
android:layout_height="wrap_content" android:text="Cauta" />
</LinearLayout>
</TableRow>
<TableRow android:id="#+id/tableRowHeader"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:background="#000000">
<LinearLayout android:orientation="horizontal">
<TextView android:id="#+id/textView1" android:layout_width="159dp"
android:layout_height="wrap_content" android:text="Denumire"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#BBBBBB" android:textSize="15sp" />
<TextView android:id="#+id/textView2" android:layout_width="159dp"
android:layout_height="wrap_content" android:text="Adresa"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#BBBBBB" android:textSize="15sp" />
</LinearLayout>
</TableRow>
<TableRow android:id="#+id/tableRow2" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:baselineAligned="false">
<ListView android:id="#+id/adresslist" android:layout_width="wrap_content"
android:choiceMode="singleChoice" android:layout_height="wrap_content"
android:scrollbars="horizontal|vertical" />
</TableRow>
</TableLayout>
Code:
public void adresalistBind()
{
listview = (ListView) findViewById(R.id.adresslist);
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
ArrayList<ClientClass> clientlist=new ArrayList<ClientClass>();
ClientClass.setClientContextForDB(this);
clientlist=ClientClass.ClientiGet();
listaAll=clientlist;
HashMap<String, String> map;
for(int i=0;i<clientlist.size();i++)
{
map = new HashMap<String, String>();
map.put("denumire", clientlist.get(i).getDenumire());
map.put("adresa", clientlist.get(i).getAdresa());
map.put("clientid", String.valueOf(clientlist.get(i).getClientID()));
mylist.add(map);
}
SimpleAdapter mAdapter = new SimpleAdapter(this, mylist, R.layout.addresslist,
new String[] {"denumire", "adresa"}, new int[] {R.id.DENUMIRE_CELL, R.id.ADRESA_CELL});
listview.setAdapter(mAdapter);
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listview.setSelection(1);
listview.setOnItemSelectedListener(new OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> adaptview, View clickedview, int position,
long id)
{
//adaptview.setSelected(true);
listview.setSelection(position);
}
public void onNothingSelected(AdapterView<?> arg0)
{
}
});
listview.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> adaptview, View arg1,
int position, long arg3)
{
//adaptview.setSelected(true);
// View rowview = (View) adaptview.getChildAt(position);
// rowview.setSelected(true);
listview.setSelection(position);
//Toast.makeText(ClientiForm.this, (String) listview.getItemAtPosition(position).toString(), 10000).show();
}
});
listview.setOnItemLongClickListener(new OnItemLongClickListener()
{
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int position, long arg3)
{
listview.setSelection(position);
openOptionsMenu();
Toast.makeText(ClientiForm.this, (String) listview.getItemAtPosition(position).toString(), 10000).show();
return false;
}
});
}
In order for item to be "checkable", the top view of the item should implement Checkable interface. Only in this case you'll get "checked"/"unchecked" states within ListView.
Note that "selectable" and "checkable" items have different meanings. In your case you mean "checkable" item. Not "selectable". You need your items to be "checked", but ListView makes sure there is at most one item checked at a time in CHOICE_MODE_SINGLE. While "selected" item is item that is currently active (this is mostly used for accessibility needs).
You can verify what I said by simply replacing LinearLayout with CheckBox view in your list item's layout. And ListView should start handling "checked" states automatically.
If you want to use LinearLayout and still be able to support "checked"/"unchecked" states, you need to implement custom layout that extends LinearLayout and implements Checkable interface.
Here is what my version of this implementation is:
public class CheckableLinearLayout extends LinearLayout implements Checkable {
private boolean mChecked;
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
public CheckableLinearLayout(Context context) {
this(context, null);
init();
}
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setClickable(true);
}
/**********************/
/** Handle clicks **/
/**********************/
#Override
public boolean performClick() {
toggle();
return super.performClick();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return onTouchEvent(ev);
}
/**************************/
/** Checkable **/
/**************************/
public void toggle() {
setChecked(!mChecked);
}
public boolean isChecked() {
return mChecked;
}
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
setCheckedRecursive(this, checked);
}
}
private void setCheckedRecursive(ViewGroup parent, boolean checked) {
int count = parent.getChildCount();
for(int i = 0; i < count; i++ ) {
View v = parent.getChildAt(i);
if(v instanceof Checkable) {
((Checkable) v).setChecked(checked);
}
if(v instanceof ViewGroup) {
setCheckedRecursive((ViewGroup)v, checked);
}
}
}
/**************************/
/** Drawable States **/
/**************************/
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
Drawable drawable = getBackground();
if (drawable != null) {
int[] myDrawableState = getDrawableState();
drawable.setState(myDrawableState);
invalidate();
}
}
/**************************/
/** State persistency **/
/**************************/
static class SavedState extends BaseSavedState {
boolean checked;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
checked = (Boolean)in.readValue(null);
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeValue(checked);
}
#Override
public String toString() {
return "CheckableLinearLayout.SavedState{"
+ Integer.toHexString(System.identityHashCode(this))
+ " checked=" + checked + "}";
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
#Override
public Parcelable onSaveInstanceState() {
// Force our ancestor class to save its state
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.checked = isChecked();
return ss;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.checked);
requestLayout();
}
}
Your item layout should look something like:
<com.your.pkg.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/checkable_item">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</com.your.pkg.CheckableLinearLayout>
And note that "drawable/checakble_item". It should handle different states. In my example it looks like:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="#drawable/item_pressed" />
<item android:state_checked="true" android:drawable="#drawable/item_checked"/>
<item android:drawable="#drawable/item_unchecked" />
</selector>
Where drawable/item_pressed, drawable/item_checked and drawable/item_unchecked are my custom drawables.
The last note: in your Adapter's getView() you'll have to call view.setClickable(false); for checkable states to be handled by ListView and not by CheckableLinearLayout.