I use PreferenceActivity for setting of live wallpaper utilizing OpenGL ES 2.0. And quite often I get completely garbled screen for this PreferenceActivity.
Steps to reproduce:
Open live wallpaper preview.
Open preferences by tapping "Settings..." button
Activity is displayed correctly no matter how often you repeat step 2.
Change orientation of device while in preview.
Open preferences by tapping "Settings..." button again.
Screen of PreferenceActivity is garbled.
I have no custom code for drawing PreferenceActivity - only a few helper methods to initialize data.
Bug disappears after disabling h/w acceleration by setting android:hardwareAccelerated="false" in manifest. Apparently, scroll animation is not as smooth as with h/w acceleration.
Example of garbled screen:
Code of activity:
package org.package.name;
import android.content.SharedPreferences;
import android.os.Bundle;
public class Prefs extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener
{
public static final String PREFERENCES = "org.package.name";
// Option names and default values
public static final String OPT_AUTOROTATE = "autorotate";
private static final boolean OPT_AUTOROTATE_DEF = true;
public static final String OPT_FLOATING = "floating_type";
public static final String OPT_FLOATING_DEF = "1";
public static final String OPT_ZOOM = "zoom";
private static final boolean OPT_ZOOM_DEF = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName(PREFERENCES);
addPreferencesFromResource(R.xml.settings);
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onDestroy() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
public static boolean getAutoRotate(SharedPreferences prefs) {
return prefs.getBoolean(OPT_AUTOROTATE, OPT_AUTOROTATE_DEF);
}
public static int getFloatingType(SharedPreferences prefs) {
return Integer.parseInt(prefs.getString(OPT_FLOATING, OPT_FLOATING_DEF));
}
public static boolean getZoom(SharedPreferences prefs) {
return prefs.getBoolean(OPT_ZOOM, OPT_ZOOM_DEF);
}
}
Related
My list is not scrolling when I use digital crown
This is what I do ;
<androidx.wear.widget.WearableRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/wrv_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
/>
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wrv_demo);
WearableRecyclerView wrv = findViewById(R.id.wrv_container);
wrv.setLayoutManager(new WearableLinearLayoutManager(this));
wrv.setAdapter(new DemoAdapter());
wrv.setHasFixedSize(true);
wrv.setCircularScrollingGestureEnabled(true);
wrv.setEdgeItemsCenteringEnabled(true);
wrv.setOnGenericMotionListener(new View.OnGenericMotionListener() {
#Override
public boolean onGenericMotion(View view, MotionEvent motionEvent) {
return false;
}
});
wrv.setBezelFraction(0.5f);
wrv.setScrollDegreesPerScreen(90);
}
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView mView;
ViewHolder(TextView itemView) {
super(itemView);
mView = itemView;
}
}
private static class DemoAdapter extends WearableRecyclerView.Adapter<ViewHolder> {
private static final int ITEM_COUNT = 100;
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView view = new TextView(parent.getContext());
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mView.setText("Holder at position " + position);
holder.mView.setTag(position);
}
#Override
public int getItemCount() {
return ITEM_COUNT;
}
}
}
short answer:
wrv.requestFocus();
long answer:
this page outlines how to capture rotary input.
https://developer.android.com/training/wearables/ui/rotary-input
I found that my WearOS app's recyclerview worked automatically in the emulator without any of what it said on that page; however, it did not work on my watch. I implemented every step on that page and then the watch worked. Then I removed every thing on that page. For me, the only thing needed was the recyclerView.requestFocus() line.
I am trying to get started with mapbox android and can't get any of the example projects to work.
My problem is with the imports
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import com.mapbox.mapboxandroiddemo.R;
I get I "cannot resolve symbol annotation", "cannot resolve symbol v7" and "cannot resolve symbol mapboxandroiddemo".
I feel like this is some android problem that I am just not understanding correctly so if anyone has some insight that would be amazing. I have tried taking out some code and using the recommended bug fixes but all that has done is break my project.
Here is the entire MainActivity.java file
package com.example.mapboxtut;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textOffset;
/**
* Use the {#link MapView#addOnStyleImageMissingListener(MapView.OnStyleImageMissingListener)}
* to handle the situation where a SymbolLayer tries using a missing image as an icon. If an icon-image
* cannot be found in a map style, a custom image can be provided to the map via
* the listener.
*/
public class MissingIconActivity extends AppCompatActivity {
private static final String ICON_SOURCE_ID = "ICON_SOURCE_ID";
private static final String ICON_LAYER_ID = "ICON_LAYER_ID";
private static final String PROFILE_NAME = "PROFILE_NAME";
private static final String CARLOS = "Carlos";
private static final String ANTONY = "Antony";
private static final String MARIA = "Maria";
private static final String LUCIANA = "Luciana";
private MapView mapView;
private MapboxMap mapboxMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, getString(R.string.access_token));
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_styles_missing_icon);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
// Add Features which represent the location of each profile photo SymbolLayer icon
Feature carlosFeature = Feature.fromGeometry(Point.fromLngLat(-7.9760742,
41.2778064));
carlosFeature.addStringProperty(PROFILE_NAME, CARLOS);
Feature antonyFeature = Feature.fromGeometry(Point.fromLngLat(-8.0639648,
37.5445773));
antonyFeature.addStringProperty(PROFILE_NAME, ANTONY);
Feature mariaFeature = Feature.fromGeometry(Point.fromLngLat(-9.1845703,
38.9764924));
mariaFeature.addStringProperty(PROFILE_NAME, MARIA);
Feature lucianaFeature = Feature.fromGeometry(Point.fromLngLat(-7.5146484,
40.2459915));
lucianaFeature.addStringProperty(PROFILE_NAME, LUCIANA);
// Use a URL to build and add a Style object to the map. Then add a source to the Style.
mapboxMap.setStyle(
new Style.Builder().fromUrl(Style.LIGHT)
.withSource(new GeoJsonSource(ICON_SOURCE_ID,
FeatureCollection.fromFeatures(new Feature[] {
carlosFeature,
antonyFeature,
mariaFeature,
lucianaFeature}))),
new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
MissingIconActivity.this.mapboxMap = mapboxMap;
// Add a SymbolLayer to the style. iconImage is set to a value that will
// be used later in the addOnStyleImageMissingListener below
style.addLayer(new SymbolLayer(ICON_LAYER_ID, ICON_SOURCE_ID).withProperties(
iconImage(get(PROFILE_NAME)),
iconIgnorePlacement(true),
iconAllowOverlap(true),
textField(get(PROFILE_NAME)),
textIgnorePlacement(true),
textAllowOverlap(true),
textOffset(new Float[] {0f, 2f})
));
}
});
}
});
// Use the listener to match the id with the appropriate person. The correct profile photo is
// given to the map during "runtime".
mapView.addOnStyleImageMissingListener(new MapView.OnStyleImageMissingListener() {
#Override
public void onStyleImageMissing(#NonNull String id) {
switch (id) {
case CARLOS:
addImage(id, R.drawable.carlos);
break;
case ANTONY:
addImage(id, R.drawable.antony);
break;
case MARIA:
addImage(id, R.drawable.maria);
break;
case LUCIANA:
addImage(id, R.drawable.luciana);
break;
default:
addImage(id, R.drawable.carlos);
break;
}
}
});
}
private void addImage(String id, int drawableImage) {
Style style = mapboxMap.getStyle();
if (style != null) {
style.addImageAsync(id, BitmapUtils.getBitmapFromDrawable(
getResources().getDrawable(drawableImage)));
}
}
// Add the mapView lifecycle to the activity's lifecycle methods
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
#Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
In my Android app I use AAC.
Here my activity:
public class AddTraderActivity extends AppCompatActivity {
AddTraderViewModel addTraderViewModel;
private static final String TAG = AddTraderActivity.class.getName();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AddTraderActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.add_trader_activity);
binding.setHandler(this);
init();
}
private void init() {
ViewModelProvider viewViewModelProvider = ViewModelProviders.of(this);
addTraderViewModel = viewViewModelProvider.get(AddTraderViewModel.class);
Observer<String> () {
#Override
public void onChanged (String message){
Debug.d(TAG, "onChanged: message = " + message);
Toast.makeText(AddTraderActivity.this, message, Toast.LENGTH_LONG).show();
}
});
}
public void onClickStart() {
EditText baseEditText = findViewById(R.id.baseEditText);
EditText quoteEditText = findViewById(R.id.quoteEditText);
addTraderViewModel.doClickStart(baseEditText.getText().toString(), quoteEditText.getText().toString());
}
}
Here my ViewModel:
public class AddTraderViewModel extends AndroidViewModel {
private MutableLiveData<String> messageLiveData = new MutableLiveData<>();
private static final String TAG = AddTraderViewModel.class.getName();
public AddTraderViewModel(#NonNull Application application) {
super(application);
}
public void doClickStart(String base, String quote) {
Debug.d(TAG, "doClickStart: ");
if (base.trim().isEmpty() || quote.trim().isEmpty()) {
String message = getApplication().getApplicationContext().getString(R.string.please_input_all_fields);
messageLiveData.setValue(message);
return;
}
}
public LiveData<String> getMessageLiveData() {
return messageLiveData;
}
}
So when I click on button on Activity call method onClickStart()
If any fields is empty the show toast. In the activity call method:
onChanged (String message)
Nice. It's work fine.
But the problem is, when I rotate the device in the activity method onChanged(String message) is called AGAIN and as result show toast. This happened on every rotation.
Why?
This is the expected behaviour. If you want to avoid this you must set message = "" and keep an empty check before showing the toast.
A better way to use it is something like Event Wrapper or SingleLiveEvent
Highly recommend you to read this article. This explains why you are facing this and what are your options in detail.
I am creating a javaFx application that runs in Mac OSX El Capitan. When I create a bundle from my jar file to .app file, the application window dimension changes.
I want window dimension to be the same before and after bundling. Any help is appreciated.
As I known JavaFX doesn't save/restore window position/dimension automatically.
So, you should restore window position/dimension before show window and save then before window hide. For example I am using such helper:
import javafx.stage.Stage;
import java.util.prefs.Preferences;
public class StagePositionManager {
public static final String IS_FIRST_RUN_KEY = "isFirstRun";
public static final String X_KEY = "x";
public static final String Y_KEY = "y";
public static final String WIDTH_KEY = "width";
public static final String HEIGHT_KEY = "height";
private final Stage stage;
private final Class<?> windowClass;
public StagePositionManager(Stage stage, Class<?> windowClass) {
this.stage = stage;
this.windowClass = windowClass;
restoreStagePosition();
stage.setOnHidden(event -> saveStagePosition());
}
private void saveStagePosition() {
Preferences preferences = Preferences.userNodeForPackage(windowClass);
preferences.putBoolean(IS_FIRST_RUN_KEY, false);
preferences.putDouble(X_KEY, stage.getX());
preferences.putDouble(Y_KEY, stage.getY());
preferences.putDouble(WIDTH_KEY, stage.getWidth());
preferences.putDouble(HEIGHT_KEY, stage.getHeight());
}
private void restoreStagePosition() {
Preferences preferences = Preferences.userNodeForPackage(windowClass);
if (!preferences.getBoolean(IS_FIRST_RUN_KEY, true)) {
stage.setX(preferences.getDouble(X_KEY, 0));
stage.setY(preferences.getDouble(Y_KEY, 0));
stage.setWidth(preferences.getDouble(WIDTH_KEY, 1024));
stage.setHeight(preferences.getDouble(HEIGHT_KEY, 768));
}
}
}
and call it after application start:
public class MyApplication extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
...
new StagePositionManager(primaryStage, Main.class);
...
This is a wierd problem.
This will be a terrible question because I have little to no information.
About two days ago I had the ViewPagerAdapter working just fine. I could swipe and it would switch between views as defined by the adapter.
However, all of a sudden (not by itself, I'm sure I did something) the TitlePagerIndicator doesn't snap to the headings and doesn't display any content. By not snapping I mean that if I drag to the left, the title will sit at 3/4 of the screen instead of snapping to the side and displaying the next page (screenshot below).
I have debugged and instantiate item is called and a proper view is returned.
However, when I open the app I'm getting a lot of warnings like these:
VFY: unable to resolve virtual method 3015: Landroid/widget/LinearLayout;.getAlpha ()F
VFY: unable to resolve direct method 3011: Landroid/widget/LinearLayout;. (Landroid/content/Context;Landroid/util/AttributeSet;I)V
VFY: unable to resolve virtual method 2965: Landroid/widget/FrameLayout;.setAlpha (F)V
I'm assuming this is a problem with my imports, but everything compiles just fine, I have the ViewPagerIndicator as a library project, as well as Sherlock.
Here's my adapter code:
public class ViewPagerAdapter extends PagerAdapter implements TitleProvider {
private static String[] titles = new String[] {
"My Klinks",
"Received Klinks"
};
private final Context context;
public ViewPagerAdapter(Context context) {
this.context = context;
}
public String getTitle(int position) {
return titles[position];
}
#Override
public int getCount() {
return titles.length;
}
#Override
public Object instantiateItem(View pager, int position) {
TextView t = new TextView(context);
t.setText("WheeeE");
return t;
}
#Override
public void destroyItem(View pager, int position, Object view) {
((ViewPager) pager).removeView((TextView) view);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void finishUpdate(View view) {
}
#Override
public void restoreState(Parcelable p, ClassLoader c) {
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public void startUpdate(View view) {
}
}
And here is my activity code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.main );
// set up the slidey tabs
ViewPagerAdapter adapter = new ViewPagerAdapter( this );
ViewPager pager = (ViewPager)findViewById( R.id.viewpager );
TitlePageIndicator indicator = (TitlePageIndicator)findViewById( R.id.indicator );
pager.setAdapter( adapter );
indicator.setViewPager( pager );
// set up the action bar
final ActionBar ab = getSupportActionBar();
ab.setBackgroundDrawable(getResources().getDrawable(R.drawable.ad_action_bar_gradient_bak));
}
If someone else gets the same problem:
In instantiateView: don't forget to attach your new View to the ViewPager:
#Override
public Object instantiateItem(View pager, int position) {
TextView t = new TextView(context);
t.setText("WheeeE");
((ViewPager)pager).addView(t);
return t;
}
The current version of instantiateItem gets a ViewGroup instead of a View, the solution should be the same.
Well after a couple days of banging my head against a wall I've come to the conclusion that my ViewPagerAdapter was the problem.
I simply created a dynamic fragment and created a subclass of FragmentPagerAdapter instead and now it works just fine...