Если вы делаете большое приложение с другими разработчиками в своей команде и собираетесь иметь все хорошо организованное без разброса кода или разных экземпляров SharedPreferences, вы можете сделать что-то вроде этого:
//SharedPreferences manager class
public class SharedPrefs {
//SharedPreferences file name
private static String SHARED_PREFS_FILE_NAME = "my_app_shared_prefs";
//here you can centralize all your shared prefs keys
public static String KEY_MY_SHARED_BOOLEAN = "my_shared_boolean";
public static String KEY_MY_SHARED_FOO = "my_shared_foo";
//get the SharedPreferences object instance
//create SharedPreferences file if not present
private static SharedPreferences getPrefs(Context context) {
return context.getSharedPreferences(SHARED_PREFS_FILE_NAME, Context.MODE_PRIVATE);
}
//Save Booleans
public static void savePref(Context context, String key, boolean value) {
getPrefs(context).edit().putBoolean(key, value).commit();
}
//Get Booleans
public static boolean getBoolean(Context context, String key) {
return getPrefs(context).getBoolean(key, false);
}
//Get Booleans if not found return a predefined default value
public static boolean getBoolean(Context context, String key, boolean defaultValue) {
return getPrefs(context).getBoolean(key, defaultValue);
}
//Strings
public static void save(Context context, String key, String value) {
getPrefs(context).edit().putString(key, value).commit();
}
public static String getString(Context context, String key) {
return getPrefs(context).getString(key, "");
}
public static String getString(Context context, String key, String defaultValue) {
return getPrefs(context).getString(key, defaultValue);
}
//Integers
public static void save(Context context, String key, int value) {
getPrefs(context).edit().putInt(key, value).commit();
}
public static int getInt(Context context, String key) {
return getPrefs(context).getInt(key, 0);
}
public static int getInt(Context context, String key, int defaultValue) {
return getPrefs(context).getInt(key, defaultValue);
}
//Floats
public static void save(Context context, String key, float value) {
getPrefs(context).edit().putFloat(key, value).commit();
}
public static float getFloat(Context context, String key) {
return getPrefs(context).getFloat(key, 0);
}
public static float getFloat(Context context, String key, float defaultValue) {
return getPrefs(context).getFloat(key, defaultValue);
}
//Longs
public static void save(Context context, String key, long value) {
getPrefs(context).edit().putLong(key, value).commit();
}
public static long getLong(Context context, String key) {
return getPrefs(context).getLong(key, 0);
}
public static long getLong(Context context, String key, long defaultValue) {
return getPrefs(context).getLong(key, defaultValue);
}
//StringSets
public static void save(Context context, String key, Set<String> value) {
getPrefs(context).edit().putStringSet(key, value).commit();
}
public static Set<String> getStringSet(Context context, String key) {
return getPrefs(context).getStringSet(key, null);
}
public static Set<String> getStringSet(Context context, String key, Set<String> defaultValue) {
return getPrefs(context).getStringSet(key, defaultValue);
}
}
В вашем вы можете сохранить SharedPreferences таким образом
//saving a boolean into prefs
SharedPrefs.savePref(this, SharedPrefs.KEY_MY_SHARED_BOOLEAN, booleanVar);
, и вы можете получить свои SharedPreferences таким образом
//getting a boolean from prefs
booleanVar = SharedPrefs.getBoolean(this, SharedPrefs.KEY_MY_SHARED_BOOLEAN);
Наконец я получил обходное решение для вышеупомянутого решения. Я сделал это путем установки StrokeThickness
из Path
относительно масштабирования Canvas
.
Как это:
// scale = scaling factor applied to the canvas
path.StrokeThickness = 1.0 / scale;
Это только работает если ScaleX
и ScaleY
универсальны.
Лучшим решением было бы использовать один или несколько объектов System.Windows.Media.Geometry для хранения ваших путей, точек и т. д.
Эту геометрию можно нарисовать пером, поэтому вы действительно можете изменить толщину обводки при масштабировании, но более гибким является использование свойства Transform.
Используя преобразование, вы можете «масштабировать» фактическое координаты геометрического представления, а не визуализации - поэтому при рисовании вам не нужно возиться с преобразованиями рендеринга.
Чтобы вычислить преобразование, я использую следующий код, например:
public static Matrix TransformShape(Rect fromPosition, Rect toPosition, bool flipVertical) {
Matrix translateThenScale = Matrix.Identity;
//we first translate to origin since that's just easier
translateThenScale.Translate(-fromPosition.X, -fromPosition.Y);
//now we scale the graph to the appropriate dimensions
translateThenScale.Scale(toPosition.Width / fromPosition.Width, toPosition.Height / fromPosition.Height);
//then we flip the graph vertically around the viewport middle since in our graph positive is up, not down.
if (flipVertical)
translateThenScale.ScaleAt(1.0, -1.0, 0.0, toPosition.Height / 2.0);
//now we push the graph to the right spot, which will usually simply be 0,0.
translateThenScale.Translate(toPosition.X, toPosition.Y);
return translateThenScale;
}
где fromPosition Rect должен содержат нетрансформированные границы, а объект toPosition Rect должен содержать трансформированные границы. Это также тривиально позволяет масштабировать X и Y отдельно, что часто необходимо для построения графика.
Легко вычислить границы вашей геометрии:
Geometry graphGeom;
//[...]
//the bounds are modified by the transform, so we want no transform!
graphGeom.Transform = Transform.Identity;
Rect graphBounds = graphGeom.Bounds;
//then set the transform again
//or, if the transform is axis-aligned, the following _should_ work:
Rect graphBoundsAlt = graphGeom.Transform.Inverse.TransformBounds(graphGeom.Bounds);
И, конечно, WPF может сказать вам, в какие границы вам нужно визуализировать, если это будет необходимо. Собрав все вместе, вы могли бы сделать что-то вроде
public void RecomputeTransform(Rect targetRect, bool flipVertical) {
graphGeom.Transform = Transform.Identity;
Rect graphBounds = graphGeom.Bounds;
Matrix transMat = TransformShape(graphBounds,targetRect,flipVertical);
graphGeom.Transform = new MatrixTransform(transMat);
}
. Преимущество использования этого решения в том, что вам не нужно связываться с RenderTransforms, вы можете свободно использовать преобразования, которые срезают и / или масштабируют X и Y независимо друг от друга, не получая странных искажения в ваших линиях, и вы можете рассматривать перо как непрозрачный объект (т. е. его проще настроить из пользовательского интерфейса - если вы выберете ширину пера или что-то еще, дальнейшая коррекция не требуется).
Я думаю, что Вам было нужно YourPathObject.RenderedGeometry.Transform
свойство