added TabSelector view, migrated to ViewPager2, code cleanup, version upgrade

This commit is contained in:
nuclearfog 2023-04-16 19:05:51 +02:00
parent 88ea1dd48e
commit 09a62e3aa3
No known key found for this signature in database
GPG Key ID: 03488A185C476379
29 changed files with 456 additions and 368 deletions

View File

@ -12,8 +12,8 @@ android {
applicationId 'org.nuclearfog.twidda'
minSdkVersion 21
targetSdkVersion 33
versionCode 80
versionName '3.1'
versionCode 81
versionName '3.1.1'
resConfigs 'en', 'de-rDE', 'zh-rCN'
}

View File

@ -1,18 +1,14 @@
package org.nuclearfog.twidda.backend.utils;
import static android.graphics.Bitmap.Config.ARGB_8888;
import static android.graphics.PorterDuff.Mode.SRC_IN;
import static android.view.View.GONE;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@ -31,17 +27,14 @@ import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.ArrayRes;
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.core.content.res.ResourcesCompat;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.kyleduo.switchbutton.SwitchButton;
import org.nuclearfog.twidda.R;
@ -211,7 +204,7 @@ public class AppStyles {
public static void setProgressColor(ProgressBar circle, int color) {
Drawable icon = circle.getIndeterminateDrawable();
if (icon != null) {
icon.setColorFilter(new PorterDuffColorFilter(color, SRC_IN));
icon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
}
}
@ -228,59 +221,6 @@ public class AppStyles {
}
}
/**
* set tab icons
*
* @param tabLayout Tab layout with tab icons
* @param settings settings to set color
* @param array set of icons
*/
public static void setTabIcons(TabLayout tabLayout, GlobalSettings settings, @ArrayRes int array) {
TextView[] textViews = setTabIconsWithText(tabLayout, settings, array);
for (TextView textView : textViews) {
if (textView != null) {
textView.setVisibility(GONE);
}
}
}
/**
* create tab icons with TextView
*
* @param tabLayout TabLayout to set the icons
* @param settings settings instance
* @param array Array of drawable resources to set the icons
* @return array of TextViews
*/
public static TextView[] setTabIconsWithText(TabLayout tabLayout, GlobalSettings settings, @ArrayRes int array) {
Context context = tabLayout.getContext();
TypedArray tArray = context.getResources().obtainTypedArray(array);
TextView[] tabs = new TextView[tabLayout.getTabCount()];
for (int index = 0; index < tArray.length() && index < tabLayout.getTabCount(); index++) {
TabLayout.Tab mTab = tabLayout.getTabAt(index);
if (mTab != null) {
View tabView;
int resId = tArray.getResourceId(index, 0);
Drawable icon = AppCompatResources.getDrawable(context, resId);
setDrawableColor(icon, settings.getIconColor());
if (mTab.getCustomView() == null) {
tabView = View.inflate(context, R.layout.item_tab, null);
mTab.setCustomView(tabView);
} else {
// Update existing view
tabView = mTab.getCustomView();
}
ImageView imageIcon = tabView.findViewById(R.id.tab_icon);
tabs[index] = tabView.findViewById(R.id.tab_text);
tabs[index].setTextColor(settings.getFontColor());
tabs[index].setTypeface(settings.getTypeFace());
imageIcon.setImageDrawable(icon);
}
}
tArray.recycle();
return tabs;
}
/**
* setup a transparent blurry toolbar
*
@ -292,7 +232,7 @@ public class AppStyles {
Drawable backgroundDrawable = background.getDrawable();
if (backgroundDrawable instanceof BitmapDrawable) {
try {
Bitmap image = ((BitmapDrawable) backgroundDrawable).getBitmap().copy(ARGB_8888, true);
Bitmap image = ((BitmapDrawable) backgroundDrawable).getBitmap().copy(Bitmap.Config.ARGB_8888, true);
// check if image is valid
if (image.getWidth() > 1 && image.getHeight() > 1) {
// crop image to background size
@ -330,9 +270,9 @@ public class AppStyles {
* @param settings global settings instance
*/
public static void setSeekBarColor(SeekBar seekBar, GlobalSettings settings) {
seekBar.getProgressDrawable().setColorFilter(new PorterDuffColorFilter(settings.getHighlightColor(), SRC_IN));
seekBar.getProgressDrawable().setColorFilter(new PorterDuffColorFilter(settings.getHighlightColor(), PorterDuff.Mode.SRC_IN));
if (seekBar.getThumb() != null) {
seekBar.getThumb().setColorFilter(new PorterDuffColorFilter(settings.getIconColor(), SRC_IN));
seekBar.getThumb().setColorFilter(new PorterDuffColorFilter(settings.getIconColor(), PorterDuff.Mode.SRC_IN));
}
}
@ -344,7 +284,7 @@ public class AppStyles {
*/
public static void setDrawableColor(@Nullable Drawable drawable, int color) {
if (drawable != null) {
drawable.mutate().setColorFilter(new PorterDuffColorFilter(color, SRC_IN));
drawable.mutate().setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
}
}
@ -386,10 +326,7 @@ public class AppStyles {
private void setSubViewTheme(ViewGroup group) {
for (int pos = 0; pos < group.getChildCount(); pos++) {
View child = group.getChildAt(pos);
if (child instanceof TabLayout) {
TabLayout tablayout = (TabLayout) child;
tablayout.setSelectedTabIndicatorColor(settings.getHighlightColor());
} else if (child instanceof SwitchButton) {
if (child instanceof SwitchButton) {
SwitchButton sw = (SwitchButton) child;
int[] color = {settings.getIconColor()};
sw.setTintColor(settings.getHighlightColor());
@ -403,28 +340,28 @@ public class AppStyles {
} else if (child instanceof TextView) {
TextView tv = (TextView) child;
tv.setTypeface(settings.getTypeFace());
tv.setTextColor(settings.getFontColor());
tv.setTextColor(settings.getTextColor());
setDrawableColor(tv, settings.getIconColor());
if (child instanceof Button) {
Button btn = (Button) child;
setButtonColor(btn, settings.getFontColor());
setButtonColor(btn, settings.getTextColor());
} else if (child instanceof EditText) {
EditText edit = (EditText) child;
edit.setHintTextColor(settings.getFontColor() & HINT_TRANSPARENCY);
edit.setHintTextColor(settings.getTextColor() & HINT_TRANSPARENCY);
}
} else if (child instanceof ImageView) {
ImageView img = (ImageView) child;
setDrawableColor(img.getDrawable(), settings.getIconColor());
if (child instanceof ImageButton) {
ImageButton btn = (ImageButton) child;
setButtonColor(btn, settings.getFontColor());
setButtonColor(btn, settings.getTextColor());
}
} else if (child instanceof ViewGroup) {
if (child instanceof CardView) {
CardView card = (CardView) child;
card.setCardBackgroundColor(settings.getCardColor());
setSubViewTheme(card);
} else if (!(child instanceof ViewPager)) {
} else if (!(child instanceof ViewPager2)) {
setSubViewTheme((ViewGroup) child);
}
}

View File

@ -1,5 +1,8 @@
package org.nuclearfog.twidda.config;
import androidx.annotation.ArrayRes;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.model.Account;
/**
@ -41,6 +44,7 @@ public enum Configuration {
private final boolean statusSpoilerSupported;
private final boolean statusVisibilitySupported;
private final boolean directMessageSupported;
private final int arrayResHome;
/**
* @param accountType account login type, see {@link Account}
@ -61,6 +65,7 @@ public enum Configuration {
statusSpoilerSupported = false;
statusVisibilitySupported = false;
directMessageSupported = true;
arrayResHome = R.array.home_twitter_icons;
break;
default:
@ -76,6 +81,7 @@ public enum Configuration {
statusSpoilerSupported = true;
statusVisibilitySupported = true;
directMessageSupported = false;
arrayResHome = R.array.home_mastodon_icons;
break;
}
}
@ -163,4 +169,14 @@ public enum Configuration {
public boolean directmessageSupported() {
return directMessageSupported;
}
/**
* get home tabitems drawable IDs
*
* @return Integer array resource containing drawable IDs
*/
@ArrayRes
public int getHomeTabIcons() {
return arrayResHome;
}
}

View File

@ -210,7 +210,7 @@ public class GlobalSettings {
*
* @return font color value
*/
public int getFontColor() {
public int getTextColor() {
return font_color;
}
@ -219,7 +219,7 @@ public class GlobalSettings {
*
* @param color font color value
*/
public void setFontColor(int color) {
public void setTextColor(int color) {
font_color = color;
Editor edit = settings.edit();

View File

@ -23,17 +23,15 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SearchView.OnQueryTextListener;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter;
import org.nuclearfog.twidda.ui.dialogs.ProgressDialog;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
/**
* Main Activity of the App
@ -49,8 +47,8 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
private Intent loginIntent;
private Dialog loadingCircle;
private TabLayout tabLayout;
private ViewPager pager;
private TabSelector tabSelector;
private ViewPager2 viewPager;
private Toolbar toolbar;
private ViewGroup root;
@ -66,23 +64,23 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
super.onCreate(savedInstanceState);
setContentView(R.layout.page_main);
toolbar = findViewById(R.id.home_toolbar);
pager = findViewById(R.id.home_pager);
tabLayout = findViewById(R.id.home_tab);
viewPager = findViewById(R.id.home_pager);
tabSelector = findViewById(R.id.home_tab);
root = findViewById(R.id.main_layout);
loadingCircle = new ProgressDialog(this);
settings = GlobalSettings.getInstance(this);
tabLayout.setupWithViewPager(pager);
pager.setOffscreenPageLimit(4);
adapter = new FragmentAdapter(this, getSupportFragmentManager());
pager.setAdapter(adapter);
tabSelector.addViewPager(viewPager);
viewPager.setOffscreenPageLimit(4);
adapter = new FragmentAdapter(this);
viewPager.setAdapter(adapter);
AppStyles.setTheme(root);
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
toolbar.setTitle("");
setSupportActionBar(toolbar);
tabLayout.addOnTabSelectedListener(this);
tabSelector.addOnTabSelectedListener(this);
}
@ -123,7 +121,7 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
case SettingsActivity.RETURN_APP_LOGOUT:
adapter.clear();
pager.setAdapter(adapter);
viewPager.setAdapter(adapter);
loginIntent = new Intent(this, LoginActivity.class);
activityResultLauncher.launch(loginIntent);
break;
@ -200,8 +198,8 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
@Override
public void onBackPressed() {
if (tabLayout.getSelectedTabPosition() > 0) {
pager.setCurrentItem(0);
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
super.onBackPressed();
}
@ -228,19 +226,8 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
@Override
public void onTabSelected(Tab tab) {
}
@Override
public void onTabUnselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public void onTabReselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
public void onTabSelected(int oldPosition, int position) {
adapter.scrollToTop(oldPosition);
}
/**
@ -250,15 +237,6 @@ public class MainActivity extends AppCompatActivity implements ActivityResultCal
AppStyles.setTheme(root);
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
adapter.setupForHomePage();
switch (settings.getLogin().getConfiguration()) {
case TWITTER1:
case TWITTER2:
AppStyles.setTabIcons(tabLayout, settings, R.array.home_twitter_icons);
break;
case MASTODON:
AppStyles.setTabIcons(tabLayout, settings, R.array.home_mastodon_icons);
break;
}
tabSelector.addTabIcons(settings.getLogin().getConfiguration().getHomeTabIcons());
}
}

View File

@ -46,11 +46,8 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.core.widget.NestedScrollView;
import androidx.core.widget.NestedScrollView.OnScrollChangeListener;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Transformation;
@ -83,6 +80,8 @@ import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener;
import org.nuclearfog.twidda.ui.views.LockableLinearLayout;
import org.nuclearfog.twidda.ui.views.LockableLinearLayout.LockCallback;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
import java.text.SimpleDateFormat;
import java.util.List;
@ -159,12 +158,11 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
private NestedScrollView root;
private ConstraintLayout header;
private LockableLinearLayout body;
private TextView[] tabIndicator;
private TextView user_location, user_createdAt, user_website, description, follow_back, username, screenName;
private ImageView profileImage, bannerImage, toolbarBackground;
private Button following, follower;
private ViewPager tabPages;
private TabLayout tabLayout;
private ViewPager2 viewPager;
private TabSelector tabSelector;
private Toolbar toolbar;
@Nullable
@ -200,8 +198,8 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
user_location = findViewById(R.id.location);
user_createdAt = findViewById(R.id.profile_date);
follow_back = findViewById(R.id.follow_back);
tabLayout = findViewById(R.id.profile_tab);
tabPages = findViewById(R.id.profile_pager);
tabSelector = findViewById(R.id.profile_tab);
viewPager = findViewById(R.id.profile_pager);
relationLoader = new RelationLoader(this);
userLoader = new UserLoader(this);
@ -227,14 +225,14 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
description.setLinkTextColor(settings.getHighlightColor());
AppStyles.setTheme(root);
user_website.setTextColor(settings.getHighlightColor());
tabLayout.setBackgroundColor(Color.TRANSPARENT);
tabSelector.setBackgroundColor(Color.TRANSPARENT);
toolbar.setTitle("");
setSupportActionBar(toolbar);
adapter = new FragmentAdapter(this, getSupportFragmentManager());
tabPages.setAdapter(adapter);
tabPages.setOffscreenPageLimit(3);
tabLayout.setupWithViewPager(tabPages);
adapter = new FragmentAdapter(this);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
tabSelector.addViewPager(viewPager);
confirmDialog = new ConfirmDialog(this);
// get parameters
@ -251,9 +249,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
}
adapter.setupProfilePage(userId);
if (settings.likeEnabled()) {
tabIndicator = AppStyles.setTabIconsWithText(tabLayout, settings, R.array.profile_tab_icons_like);
tabSelector.addTabIcons(R.array.profile_tab_icons_like);
} else {
tabIndicator = AppStyles.setTabIconsWithText(tabLayout, settings, R.array.profile_tab_icons);
tabSelector.addTabIcons(R.array.profile_tab_icons);
}
if (user != null) {
setUser(user);
@ -267,7 +265,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
RelationParam param = new RelationParam(userId, RelationParam.LOAD);
relationLoader.execute(param, relationCallback);
}
tabLayout.addOnTabSelectedListener(this);
tabSelector.addOnTabSelectedListener(this);
following.setOnClickListener(this);
follower.setOnClickListener(this);
profileImage.setOnClickListener(this);
@ -480,8 +478,8 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
@Override
public void onBackPressed() {
if (tabLayout.getSelectedTabPosition() > 0) {
tabPages.setCurrentItem(0);
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
Intent returnData = new Intent();
returnData.putExtra(KEY_USER_UPDATE, user);
@ -618,19 +616,8 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
@Override
public void onTabSelected(Tab tab) {
}
@Override
public void onTabUnselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public void onTabReselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
public void onTabSelected(int oldPosition, int position) {
adapter.scrollToTop(oldPosition);
}
@ -747,16 +734,14 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
username.setText(user.getUsername());
screenName.setText(user.getScreenname());
if (user.getStatusCount() >= 0) {
tabIndicator[0].setText(StringUtils.NUMBER_FORMAT.format(user.getStatusCount()));
tabSelector.setLabel(0, StringUtils.NUMBER_FORMAT.format(user.getStatusCount()));
} else {
tabIndicator[0].setText("");
tabSelector.setLabel(0, "");
}
if (tabIndicator.length > 1) {
if (user.getFavoriteCount() >= 0) {
tabIndicator[1].setText(StringUtils.NUMBER_FORMAT.format(user.getFavoriteCount()));
} else {
tabIndicator[1].setText("");
}
if (user.getFavoriteCount() >= 0) {
tabSelector.setLabel(1, StringUtils.NUMBER_FORMAT.format(user.getFavoriteCount()));
} else {
tabSelector.setLabel(1, "");
}
if (user_createdAt.getVisibility() != VISIBLE) {
String date = SimpleDateFormat.getDateTimeInstance().format(user.getTimestamp());

View File

@ -17,17 +17,15 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SearchView.OnQueryTextListener;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
/**
* search Activity for statuses and users
@ -46,8 +44,7 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
private FragmentAdapter adapter;
private GlobalSettings settings;
private TabLayout tabLayout;
private ViewPager pager;
private ViewPager2 viewPager;
private Toolbar toolbar;
private String search = "";
@ -64,26 +61,26 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
super.onCreate(b);
setContentView(R.layout.page_search);
ViewGroup root = findViewById(R.id.search_layout);
TabSelector tabSelector = findViewById(R.id.search_tab);
toolbar = findViewById(R.id.search_toolbar);
tabLayout = findViewById(R.id.search_tab);
pager = findViewById(R.id.search_pager);
viewPager = findViewById(R.id.search_pager);
toolbar.setTitle("");
setSupportActionBar(toolbar);
settings = GlobalSettings.getInstance(this);
adapter = new FragmentAdapter(this, getSupportFragmentManager());
tabLayout.setupWithViewPager(pager);
tabLayout.addOnTabSelectedListener(this);
pager.setAdapter(adapter);
pager.setOffscreenPageLimit(2);
adapter = new FragmentAdapter(this);
tabSelector.addViewPager(viewPager);
tabSelector.addOnTabSelectedListener(this);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
String search = getIntent().getStringExtra(KEY_SEARCH_QUERY);
if (search != null) {
this.search = search;
boolean enableHashtags = !search.startsWith("#") && settings.getLogin().getConfiguration() == Configuration.MASTODON;
adapter.setupSearchPage(search, enableHashtags);
AppStyles.setTabIcons(tabLayout, settings, R.array.search_tab_icons);
tabSelector.addTabIcons(R.array.search_tab_icons);
}
AppStyles.setTheme(root);
}
@ -91,8 +88,8 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
@Override
public void onBackPressed() {
if (tabLayout.getSelectedTabPosition() > 0) {
pager.setCurrentItem(0);
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
super.onBackPressed();
}
@ -162,19 +159,8 @@ public class SearchActivity extends AppCompatActivity implements OnTabSelectedLi
@Override
public void onTabSelected(Tab tab) {
public void onTabSelected(int oldPosition, int position) {
invalidateOptionsMenu();
}
@Override
public void onTabUnselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public void onTabReselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
adapter.scrollToTop(oldPosition);
}
}

View File

@ -348,7 +348,7 @@ public class SettingsActivity extends AppCompatActivity implements OnClickListen
// set font color
else if (v.getId() == R.id.color_text) {
mode = COLOR_TEXT;
color = settings.getFontColor();
color = settings.getTextColor();
showColorPicker(color, false);
}
// set popup color
@ -418,7 +418,7 @@ public class SettingsActivity extends AppCompatActivity implements OnClickListen
break;
case COLOR_TEXT:
settings.setFontColor(color);
settings.setTextColor(color);
fontAdapter.notifyDataSetChanged();
scaleAdapter.notifyDataSetChanged();
if (settings.isLoggedIn()) {

View File

@ -22,11 +22,7 @@ import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SearchView.OnQueryTextListener;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.api.ConnectionException;
@ -46,6 +42,8 @@ import org.nuclearfog.twidda.ui.adapter.FragmentAdapter;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener;
import org.nuclearfog.twidda.ui.fragments.UserFragment;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
import java.util.regex.Pattern;
@ -111,8 +109,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
private ConfirmDialog confirmDialog;
private TabLayout tablayout;
private ViewPager pager;
private ViewPager2 viewPager;
private Toolbar toolbar;
@Nullable
@ -132,17 +129,17 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
super.onCreate(b);
setContentView(R.layout.page_listdetail);
ViewGroup root = findViewById(R.id.listdetail_root);
TabSelector tabSelector = findViewById(R.id.listdetail_tab);
toolbar = findViewById(R.id.listdetail_toolbar);
tablayout = findViewById(R.id.listdetail_tab);
pager = findViewById(R.id.listdetail_pager);
viewPager = findViewById(R.id.listdetail_pager);
confirmDialog = new ConfirmDialog(this);
listLoaderAsync = new ListAction(this);
listManagerAsync = new ListManager(this);
adapter = new FragmentAdapter(this, getSupportFragmentManager());
pager.setOffscreenPageLimit(3);
pager.setAdapter(adapter);
tablayout.setupWithViewPager(pager);
adapter = new FragmentAdapter(this);
viewPager.setOffscreenPageLimit(3);
viewPager.setAdapter(adapter);
tabSelector.addViewPager(viewPager);
settings = GlobalSettings.getInstance(this);
Object data = getIntent().getSerializableExtra(KEY_LIST_DATA);
@ -155,10 +152,10 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
setSupportActionBar(toolbar);
AppStyles.setTheme(root);
AppStyles.setTabIcons(tablayout, settings, R.array.list_tab_icons);
tabSelector.addTabIcons(R.array.list_tab_icons);
confirmDialog.setConfirmListener(this);
tablayout.addOnTabSelectedListener(this);
tabSelector.addOnTabSelectedListener(this);
}
@ -254,8 +251,8 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
@Override
public void onBackPressed() {
if (tablayout.getSelectedTabPosition() > 0) {
pager.setCurrentItem(0);
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
Intent result = new Intent();
result.putExtra(RESULT_UPDATE_LIST, userList);
@ -308,19 +305,8 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
@Override
public void onTabSelected(Tab tab) {
}
@Override
public void onTabUnselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public void onTabReselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
public void onTabSelected(int oldPosition, int position) {
adapter.scrollToTop(oldPosition);
}

View File

@ -18,16 +18,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
/**
* Activity to show userlists of an user
@ -47,8 +45,7 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
private FragmentAdapter adapter;
private GlobalSettings settings;
private ViewPager pager;
private TabLayout tabLayout;
private ViewPager2 viewPager;
private boolean isHome = false;
@ -65,25 +62,25 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
setContentView(R.layout.page_list);
ViewGroup root = findViewById(R.id.list_view);
Toolbar toolbar = findViewById(R.id.list_toolbar);
pager = findViewById(R.id.list_pager);
tabLayout = findViewById(R.id.list_tab);
TabSelector tabSelector = findViewById(R.id.list_tab);
viewPager = findViewById(R.id.list_pager);
toolbar.setTitle(R.string.list_appbar);
setSupportActionBar(toolbar);
adapter = new FragmentAdapter(this, getSupportFragmentManager());
adapter = new FragmentAdapter(this);
settings = GlobalSettings.getInstance(this);
AppStyles.setTheme(root);
pager.setAdapter(adapter);
pager.setOffscreenPageLimit(2);
tabLayout.setupWithViewPager(pager);
tabLayout.addOnTabSelectedListener(this);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
tabSelector.addViewPager(viewPager);
tabSelector.addOnTabSelectedListener(this);
long ownerId = getIntent().getLongExtra(KEY_USERLIST_OWNER_ID, 0L);
isHome = ownerId == settings.getLogin().getId();
adapter.setupListPage(ownerId);
AppStyles.setTabIcons(tabLayout, settings, R.array.userlist_tab_icons);
tabSelector.addTabIcons(R.array.userlist_tab_icons);
AppStyles.setOverflowIcon(toolbar, settings.getIconColor());
}
@ -98,8 +95,8 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
@Override
public void onBackPressed() {
if (tabLayout.getSelectedTabPosition() > 0) {
pager.setCurrentItem(0);
if (viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
super.onBackPressed();
}
@ -134,18 +131,7 @@ public class UserlistsActivity extends AppCompatActivity implements ActivityResu
@Override
public void onTabSelected(Tab tab) {
}
@Override
public void onTabUnselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public void onTabReselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
public void onTabSelected(int oldPosition, int position) {
adapter.scrollToTop(oldPosition);
}
}

View File

@ -14,11 +14,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SearchView.OnQueryTextListener;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
import com.google.android.material.tabs.TabLayout.Tab;
import androidx.viewpager2.widget.ViewPager2;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
@ -29,6 +25,8 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.ui.adapter.FragmentAdapter;
import org.nuclearfog.twidda.ui.views.TabSelector;
import org.nuclearfog.twidda.ui.views.TabSelector.OnTabSelectedListener;
import java.util.regex.Pattern;
@ -103,8 +101,8 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
private FragmentAdapter adapter;
private Toolbar toolbar;
private TabLayout tablayout;
private ViewPager pager;
private TabSelector tabSelector;
private ViewPager2 viewPager;
private int mode;
@ -121,13 +119,13 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
setContentView(R.layout.page_exclude);
ViewGroup root = findViewById(R.id.page_exclude_root);
toolbar = findViewById(R.id.page_exclude_toolbar);
tablayout = findViewById(R.id.page_exclude_tab);
pager = findViewById(R.id.page_exclude_pager);
tabSelector = findViewById(R.id.page_exclude_tab);
viewPager = findViewById(R.id.page_exclude_pager);
filterAsync = new FilterLoader(this);
settings = GlobalSettings.getInstance(this);
adapter = new FragmentAdapter(this, getSupportFragmentManager());
pager.setAdapter(adapter);
adapter = new FragmentAdapter(this);
//pager.setAdapter(adapter);
mode = getIntent().getIntExtra(KEY_USERS_MODE, 0);
long id = getIntent().getLongExtra(KEY_USERS_ID, 0L);
@ -135,48 +133,48 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
switch (mode) {
case USERS_FRIENDS:
adapter.setupFollowingPage(id);
pager.setOffscreenPageLimit(1);
tablayout.setVisibility(View.GONE);
viewPager.setOffscreenPageLimit(1);
tabSelector.setVisibility(View.GONE);
toolbar.setTitle(R.string.userlist_following);
break;
case USERS_FOLLOWER:
adapter.setupFollowerPage(id);
pager.setOffscreenPageLimit(1);
tablayout.setVisibility(View.GONE);
viewPager.setOffscreenPageLimit(1);
tabSelector.setVisibility(View.GONE);
toolbar.setTitle(R.string.userlist_follower);
break;
case USERS_REPOST:
adapter.setupReposterPage(id);
pager.setOffscreenPageLimit(1);
tablayout.setVisibility(View.GONE);
viewPager.setOffscreenPageLimit(1);
tabSelector.setVisibility(View.GONE);
toolbar.setTitle(R.string.toolbar_userlist_repost);
break;
case USERS_FAVORIT:
int title = settings.likeEnabled() ? R.string.toolbar_status_liker : R.string.toolbar_status_favoriter;
adapter.setFavoriterPage(id);
pager.setOffscreenPageLimit(1);
tablayout.setVisibility(View.GONE);
viewPager.setOffscreenPageLimit(1);
tabSelector.setVisibility(View.GONE);
toolbar.setTitle(title);
break;
case USERS_EXCLUDED:
adapter.setupMuteBlockPage();
pager.setOffscreenPageLimit(2);
tablayout.setupWithViewPager(pager);
tablayout.addOnTabSelectedListener(this);
AppStyles.setTabIcons(tablayout, settings, R.array.user_exclude_icons);
viewPager.setOffscreenPageLimit(2);
tabSelector.addViewPager(viewPager);
tabSelector.addOnTabSelectedListener(this);
tabSelector.addTabIcons(R.array.user_exclude_icons);
toolbar.setTitle(R.string.menu_toolbar_excluded_users);
break;
case USERS_REQUESTS:
adapter.setupFollowRequestPage();
pager.setOffscreenPageLimit(2);
tablayout.setupWithViewPager(pager);
tablayout.addOnTabSelectedListener(this);
AppStyles.setTabIcons(tablayout, settings, R.array.user_requests_icon);
viewPager.setOffscreenPageLimit(2);
tabSelector.addViewPager(viewPager);
tabSelector.addOnTabSelectedListener(this);
tabSelector.addTabIcons(R.array.user_requests_icon);
toolbar.setTitle(R.string.menu_toolbar_request);
break;
}
@ -187,8 +185,8 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
@Override
public void onBackPressed() {
if (tablayout.getVisibility() == View.VISIBLE && tablayout.getSelectedTabPosition() > 0) {
pager.setCurrentItem(0);
if (tabSelector.getVisibility() == View.VISIBLE && viewPager.getCurrentItem() > 0) {
viewPager.setCurrentItem(0);
} else {
super.onBackPressed();
}
@ -217,10 +215,10 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
public boolean onPrepareOptionsMenu(Menu m) {
if (mode == USERS_EXCLUDED) {
SearchView searchView = (SearchView) m.findItem(R.id.menu_exclude_user).getActionView();
if (tablayout.getSelectedTabPosition() == 0) {
if (viewPager.getCurrentItem() == 0) {
String hint = getString(R.string.menu_hint_mute_user);
searchView.setQueryHint(hint);
} else if (tablayout.getSelectedTabPosition() == 1) {
} else if (viewPager.getCurrentItem() == 1) {
String hint = getString(R.string.menu_hint_block_user);
searchView.setQueryHint(hint);
}
@ -244,32 +242,21 @@ public class UsersActivity extends AppCompatActivity implements OnTabSelectedLis
@Override
public void onTabSelected(Tab tab) {
public void onTabSelected(int oldPosition, int position) {
adapter.scrollToTop(oldPosition);
// reset menu
invalidateOptionsMenu();
}
@Override
public void onTabUnselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public void onTabReselected(Tab tab) {
adapter.scrollToTop(tab.getPosition());
}
@Override
public boolean onQueryTextSubmit(String query) {
if (USERNAME_PATTERN.matcher(query).matches()) {
if (filterAsync.isIdle()) {
if (tablayout.getSelectedTabPosition() == 0) {
if (viewPager.getCurrentItem() == 0) {
FilterParam param = new FilterParam(FilterParam.MUTE, query);
filterAsync.execute(param, this);
} else if (tablayout.getSelectedTabPosition() == 1) {
} else if (viewPager.getCurrentItem() == 1) {
FilterParam param = new FilterParam(FilterParam.BLOCK, query);
filterAsync.execute(param, this);
}

View File

@ -60,7 +60,7 @@ public class FontAdapter extends BaseAdapter {
textItem = view.findViewById(R.id.dropdown_textitem);
textItem.setText(FONT_NAMES[pos]);
textItem.setTypeface(FONT_TYPES[pos]);
textItem.setTextColor(settings.getFontColor());
textItem.setTextColor(settings.getTextColor());
textItem.setBackgroundColor(settings.getCardColor());
view.setBackgroundColor(settings.getBackgroundColor());
return view;

View File

@ -31,13 +31,12 @@ import static org.nuclearfog.twidda.ui.fragments.UserListFragment.KEY_FRAG_LIST_
import static org.nuclearfog.twidda.ui.fragments.UserListFragment.LIST_USER_OWNS;
import static org.nuclearfog.twidda.ui.fragments.UserListFragment.LIST_USER_SUBSCR_TO;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Account;
@ -50,36 +49,49 @@ import org.nuclearfog.twidda.ui.fragments.UserFragment;
import org.nuclearfog.twidda.ui.fragments.UserListFragment;
/**
* custom adapter used for {@link androidx.viewpager.widget.ViewPager}
* custom adapter used for {@link androidx.viewpager2.widget.ViewPager2}
*
* @author nuclearfog
*/
public class FragmentAdapter extends FragmentStatePagerAdapter {
public class FragmentAdapter extends FragmentStateAdapter {
private ListFragment[] fragments = {};
private GlobalSettings settings;
/**
* @param fManager Activity Fragment Manager
* @param fragmentActivity fragment activity
*/
public FragmentAdapter(Context context, FragmentManager fManager) {
super(fManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
settings = GlobalSettings.getInstance(context);
public FragmentAdapter(FragmentActivity fragmentActivity) {
super(fragmentActivity);
settings = GlobalSettings.getInstance(fragmentActivity.getApplicationContext());
}
@Override
@NonNull
public Fragment getItem(int index) {
return fragments[index];
@Override
public Fragment createFragment(int position) {
return fragments[position];
}
@Override
public int getCount() {
public int getItemCount() {
return fragments.length;
}
/**
* get fragment at index
*
* @param index index of the fragment
* @return fragment
*/
public ListFragment getItem(int index) {
if (index >= 0 && index < fragments.length) {
return fragments[index];
}
return null;
}
/**
* Check if adapter is empty
*

View File

@ -63,7 +63,7 @@ public class LocationAdapter extends BaseAdapter {
}
textItem = view.findViewById(R.id.dropdown_textitem);
textItem.setBackgroundColor(settings.getCardColor());
textItem.setTextColor(settings.getFontColor());
textItem.setTextColor(settings.getTextColor());
textItem.setTypeface(settings.getTypeFace());
textItem.setText(locations.get(pos).getFullName());
view.setBackgroundColor(settings.getBackgroundColor());

View File

@ -81,7 +81,7 @@ public class NetworkAdapter extends BaseAdapter {
textItem = convertView.findViewById(R.id.dropdown_textitem);
textItem.setText(STRINGS[position]);
textItem.setCompoundDrawablesWithIntrinsicBounds(ICONS[position], 0, 0, 0);
textItem.setTextColor(settings.getFontColor());
textItem.setTextColor(settings.getTextColor());
textItem.setBackgroundColor(settings.getCardColor());
AppStyles.setDrawableColor(textItem, settings.getIconColor());
convertView.setBackgroundColor(settings.getBackgroundColor());

View File

@ -58,7 +58,7 @@ public class ScaleAdapter extends BaseAdapter {
textItem = view.findViewById(R.id.dropdown_textitem);
textItem.setText(String.format(Locale.getDefault(), "%.1f X", FONT_SCALES[pos]));
textItem.setTypeface(settings.getTypeFace());
textItem.setTextColor(settings.getFontColor());
textItem.setTextColor(settings.getTextColor());
textItem.setBackgroundColor(settings.getCardColor());
view.setBackgroundColor(settings.getBackgroundColor());
return view;

View File

@ -63,7 +63,7 @@ public class CardHolder extends ViewHolder implements OnClickListener {
itemView.getLayoutParams().width = parent.getMeasuredHeight() * 16 / 9;
linkText.setTypeface(settings.getTypeFace());
linkText.setTextColor(settings.getFontColor());
linkText.setTextColor(settings.getTextColor());
linkText.setBackgroundColor(settings.getBackgroundColor() & TEXT_TRANSPARENCY);
linkText.setOnClickListener(this);

View File

@ -44,9 +44,9 @@ public class Optionholder extends ViewHolder implements OnClickListener {
this.settings = settings;
this.listener = listener;
optionName.setTextColor(settings.getFontColor());
optionName.setTextColor(settings.getTextColor());
optionName.setTypeface(settings.getTypeFace());
optionVotes.setTextColor(settings.getFontColor());
optionVotes.setTextColor(settings.getTextColor());
optionVotes.setTypeface(settings.getTypeFace());
AppStyles.setSeekBarColor(voteProgress, settings);
checkIcon.setColorFilter(settings.getIconColor());

View File

@ -43,9 +43,9 @@ public class PlaceHolder extends ViewHolder implements OnClickListener {
loadBtn = itemView.findViewById(R.id.placeholder_button);
background.setCardBackgroundColor(settings.getCardColor());
loadBtn.setTextColor(settings.getFontColor());
loadBtn.setTextColor(settings.getTextColor());
loadBtn.setTypeface(settings.getTypeFace());
AppStyles.setButtonColor(loadBtn, settings.getFontColor());
AppStyles.setButtonColor(loadBtn, settings.getTextColor());
AppStyles.setProgressColor(loadCircle, settings.getHighlightColor());
// enable extra views

View File

@ -44,7 +44,7 @@ public class PollHolder extends ViewHolder implements OnClickListener {
this.listener = listener;
cardBackground.setCardBackgroundColor(settings.getCardColor());
votesCount.setTextColor(settings.getFontColor());
votesCount.setTextColor(settings.getTextColor());
votesCount.setTypeface(settings.getTypeFace());
itemView.getLayoutParams().width = parent.getMeasuredHeight() * 2; // 2:1 ratio

View File

@ -0,0 +1,224 @@
package org.nuclearfog.twidda.ui.views;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ArrayRes;
import androidx.annotation.Nullable;
import androidx.viewpager2.widget.ViewPager2;
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings;
/**
* TabLayout implementation to provide a tab selector
*
* @author nuclearfog
*/
public class TabSelector extends LinearLayout implements OnClickListener, OnGlobalLayoutListener {
@Nullable
private ViewPager2 viewPager;
private LinearLayout tabContainer;
private View indicator;
@Nullable
private OnTabSelectedListener listener;
private GlobalSettings settings;
private int indicator_height;
private int oldPosition;
private int tabCount;
/**
* @inheritDoc
*/
public TabSelector(Context context) {
this(context, null);
}
/**
* @inheritDoc
*/
public TabSelector(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
settings = GlobalSettings.getInstance(context);
tabContainer = new LinearLayout(context);
tabContainer.setOrientation(LinearLayout.HORIZONTAL);
indicator = new View(context);
indicator.setVisibility(INVISIBLE);
indicator_height = (int) getResources().getDimension(R.dimen.tabs_indicator_height);
LayoutParams tabContainerParam = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
tabContainerParam.weight = 1;
tabContainer.setLayoutParams(tabContainerParam);
addView(tabContainer);
addView(indicator);
}
@Override
public void onClick(View v) {
for (int i = 0 ; i < tabContainer.getChildCount(); i++) {
if (tabContainer.getChildAt(i) == v && listener != null) {
if (viewPager != null && viewPager.getAdapter() != null && i < viewPager.getAdapter().getItemCount()) {
listener.onTabSelected(oldPosition, i);
viewPager.setCurrentItem(i);
oldPosition = i;
}
break;
}
}
}
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
for (int i = 0 ; i < tabContainer.getChildCount(); i++) {
View tabItemView = tabContainer.getChildAt(i);
ImageView icon = tabItemView.findViewById(R.id.tab_icon);
TextView label = tabItemView.findViewById(R.id.tab_text);
tabItemView.getLayoutParams().width = getMeasuredWidth() / Math.max(tabCount, 1);
tabItemView.getLayoutParams().height = getMeasuredHeight();
AppStyles.setDrawableColor(icon, settings.getIconColor());
label.setTextColor(settings.getTextColor());
}
LayoutParams params = new LayoutParams(getMeasuredWidth() / Math.max(tabCount, 1), 5);
indicator.setLayoutParams(params);
indicator.setBackgroundColor(settings.getHighlightColor());
indicator.setVisibility(VISIBLE);
}
/**
* attach {@link ViewPager2} to this view
*
* @param viewPager ViewPager to interact with
*/
public void addViewPager(ViewPager2 viewPager) {
this.viewPager = viewPager;
viewPager.registerOnPageChangeCallback(new ViewPagerCallback());
}
/**
* set tab icons
*
* @param arrayRes array ID containing drawable IDs
*/
public void addTabIcons(@ArrayRes int arrayRes) {
TypedArray tArray = getResources().obtainTypedArray(arrayRes);
tabContainer.removeAllViews();
if (viewPager != null && viewPager.getAdapter() != null) {
tabCount = Math.min(tArray.length(), viewPager.getAdapter().getItemCount());
} else {
tabCount = tArray.length();
}
for (int i = 0 ; i < tabCount ; i++) {
View tabItemView = inflate(getContext(), R.layout.item_tab, null);
ImageView icon = tabItemView.findViewById(R.id.tab_icon);
int resId = tArray.getResourceId(i, 0);
icon.setImageResource(resId);
tabContainer.addView(tabItemView);
tabItemView.setOnClickListener(this);
}
tArray.recycle();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
/**
* set tab item label
*
* @param position index of the tab item
* @param text text to set
*/
public void setLabel(int position, String text) {
if (position >= 0 && position < tabContainer.getChildCount()) {
View tabItemView = tabContainer.getChildAt(position);
TextView tabLabel = tabItemView.findViewById(R.id.tab_text);
tabLabel.setText(text);
tabLabel.setVisibility(VISIBLE);
}
}
/**
* add listener to call when a tab is selected
*/
public void addOnTabSelectedListener(OnTabSelectedListener listener) {
this.listener = listener;
}
/**
*/
private void setPosition(float positionOffset) {
if (viewPager != null && viewPager.getAdapter() != null && tabCount > 0) {
LayoutParams params = new LayoutParams(getMeasuredWidth() / tabCount, indicator_height);
params.setMarginStart((int) (getMeasuredWidth() * positionOffset / tabCount));
indicator.setLayoutParams(params);
indicator.setVisibility(VISIBLE);
}
}
/**
*/
private void setPage(int page) {
if (viewPager != null && viewPager.getAdapter() != null && page < viewPager.getAdapter().getItemCount() && page < tabCount) {
if (listener != null) {
listener.onTabSelected(oldPosition, page);
}
oldPosition = page;
}
}
/**
* Listener to call when a new tab is selected
*/
public interface OnTabSelectedListener {
/**
* called on tab item click
*
* @param oldPosition unselected position
* @param position selected position
*/
void onTabSelected(int oldPosition, int position);
}
/**
* {@link ViewPager2} callback used to determine page & scroll position
*/
private class ViewPagerCallback extends OnPageChangeCallback {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (positionOffsetPixels > 0) {
setPosition(positionOffset + position);
}
}
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
setPage(position);
}
@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
}
}
}

View File

@ -1,32 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_horizontal">
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="@dimen/item_tab_padding">
<ImageView
android:id="@+id/tab_icon"
android:layout_width="@dimen/tabitem_icon_size"
android:layout_height="@dimen/tabitem_icon_size"
android:layout_width="@dimen/item_tab_icon_size"
android:layout_height="@dimen/item_tab_icon_size"
android:scaleType="fitXY"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/tab_text"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tab_text"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:lines="1"
android:textSize="@dimen/tabitem_textsize"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tab_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
android:textSize="@dimen/item_tab_textsize"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View File

@ -13,13 +13,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.tabs.TabLayout
<org.nuclearfog.twidda.ui.views.TabSelector
android:id="@+id/page_exclude_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
android:layout_height="@dimen/tabselector_height" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/page_exclude_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@ -13,13 +13,12 @@
android:layout_width="match_parent"
android:layout_height="@dimen/listpage_toolbar_height" />
<com.google.android.material.tabs.TabLayout
<org.nuclearfog.twidda.ui.views.TabSelector
android:id="@+id/list_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
android:layout_height="@dimen/tabselector_height" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/list_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -13,13 +13,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.google.android.material.tabs.TabLayout
<org.nuclearfog.twidda.ui.views.TabSelector
android:id="@+id/listdetail_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
android:layout_height="@dimen/tabselector_height" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/listdetail_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -13,15 +13,15 @@
android:layout_width="match_parent"
android:layout_height="@dimen/mainpage_toolbar_height" />
<com.google.android.material.tabs.TabLayout
<org.nuclearfog.twidda.ui.views.TabSelector
android:id="@+id/home_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
android:layout_height="@dimen/tabselector_height" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:orientation="horizontal"/>
</LinearLayout>

View File

@ -223,14 +223,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
<org.nuclearfog.twidda.ui.views.TabSelector
android:id="@+id/profile_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:tabMinWidth="@dimen/profile_tabitem_min_width" />
android:layout_height="@dimen/profile_tabselector_height" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/profile_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -13,13 +13,12 @@
android:layout_width="match_parent"
android:layout_height="@dimen/searchpage_toolbar_height" />
<com.google.android.material.tabs.TabLayout
<org.nuclearfog.twidda.ui.views.TabSelector
android:id="@+id/search_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent" />
android:layout_height="@dimen/tabselector_height" />
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/search_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -3,6 +3,8 @@
<!--global dimens-->
<dimen name="toolbar_height">56dp</dimen>
<dimen name="toolbar_height_small">48dp</dimen>
<dimen name="tabselector_height">40dp</dimen>
<dimen name="tabs_indicator_height">2dp</dimen>
<dimen name="edittext_background_padding">5dp</dimen>
<dimen name="edittext_textsize">16sp</dimen>
<dimen name="edittext_margin">2dp</dimen>
@ -54,8 +56,8 @@
<dimen name="profile_button_background_padding">5dp</dimen>
<dimen name="profile_textsize_big">14sp</dimen>
<dimen name="profile_textsize_small">12sp</dimen>
<dimen name="profile_tabitem_min_width">120sp</dimen>
<dimen name="profile_icon_size">14sp</dimen>
<dimen name="profile_tabselector_height">52dp</dimen>
<integer name="profile_text_bio_lines">6</integer>
<!--dimens of page_editprofile.xml-->
@ -251,9 +253,10 @@
<dimen name="dialog_poll_button_height">20sp</dimen>
<dimen name="dialog_poll_spinner_height">22sp</dimen>
<!--dimens of tabitem.xml-->
<dimen name="tabitem_icon_size">22sp</dimen>
<dimen name="tabitem_textsize">11sp</dimen>
<!--dimens of item_tab.xml-->
<dimen name="item_tab_icon_size">22sp</dimen>
<dimen name="item_tab_textsize">11sp</dimen>
<dimen name="item_tab_padding">5dp</dimen>
<!--dimens of item_card.xml-->
<dimen name="item_card_textsize">11sp</dimen>